Contract Rounds API
Use the Contract Rounds API to retrieve information about contract review rounds, approval progression, reviewer statuses, SLAs, turnaround times, metadata, and watchers in Coupa CLM.
Overview
The Contract Rounds API provides REST access to contract review history and active review cycles. Use this endpoint to monitor reviewer bottlenecks, track negotiation turnaround times against SLAs, and audit review chain triggers across contract iterations.
Elements
The top-level payload response contains the following primary objects:
| Element | Description | Required Field? | Unique? | Allowable Value | Api_In Field? | Api_Out Field? | Data Type |
|---|---|---|---|---|---|---|---|
contract_rounds | Array of contract review round objects (XML tag: contract-rounds) | no | no | any | no | yes | array |
metadata | Object containing user permission flags for the review round | no | no | any | no | yes | object |
watchers | Array of watcher objects tracking the contract round | no | no | any | no | yes | array |
The following elements are nested under contract_rounds (XML tag: contract-round):
| Element | Description | Required Field? | Unique? | Allowable Value | Api_In Field? | Api_Out Field? | Data Type |
|---|---|---|---|---|---|---|---|
id | Coupa unique identifier for the round | no | no | any | no | yes | integer |
status | Status of the contract round | no | no | draft, pending_review, completed, closed | no | yes | string |
position | Sequential position or iteration number of the review round | no | no | any | no | yes | integer |
started_at | Timestamp when the overall round was started | no | no | any | no | yes | datetime |
internal_review_started_at | Timestamp when internal review phase began | no | no | any | no | yes | datetime |
internal_review_completed_at | Timestamp when internal review phase completed | no | no | any | no | yes | datetime |
negotiation_started_at | Timestamp when counterparty negotiation phase started | no | no | any | no | yes | datetime |
negotiation_completed_at | Timestamp when counterparty negotiation phase completed | no | no | any | no | yes | datetime |
created_at | Timestamp when round was created in format YYYY-MM-DDTHH:MM:SS+HH:MM | no | no | any | no | yes | datetime |
updated_at | Timestamp when round was updated in format YYYY-MM-DDTHH:MM:SS+HH:MM | no | no | any | no | yes | datetime |
created_by | User who created the round | no | no | any | no | yes | User |
updated_by | User who updated the round | no | no | any | no | yes | User |
reviews | Array of review assignments for this round | no | no | any | no | yes | array |
counterparty_reviews | Array of counterparty review assignments for this round | no | no | any | no | yes | array |
The following elements are nested under reviews:
| Element | Description | Required Field? | Unique? | Allowable Value | Api_In Field? | Api_Out Field? | Data Type |
|---|---|---|---|---|---|---|---|
id | Coupa unique identifier of the review record | no | no | any | no | yes | integer |
status | Current status of the review | no | no | pending_review, completed, skipped | no | yes | string |
reviewer_id | Coupa unique identifier of the reviewer or user group (XML tag: reviewer-id) | no | no | any | no | yes | integer |
reviewer_type | Type of reviewer entity (e.g. User, UserGroup) | no | no | any | no | yes | string |
reviewer_name | Full name of the assigned reviewer or user group | no | no | any | no | yes | string |
reviewer_email | Email address of the assigned reviewer | no | no | any | no | yes | string |
first_notified_at | Timestamp when reviewer was notified (XML tag: first-notified-at) | no | no | any | no | yes | datetime |
last_reminded_at | Timestamp when reviewer was last reminded (XML tag: last-reminded-at) | no | no | any | no | yes | datetime |
reviewed_at | Timestamp when review was completed (XML tag: reviewed-at) | no | no | any | no | yes | datetime |
reviewed_by_id | Coupa unique identifier of the user who completed the review (XML tag: reviewed-by-id) | no | no | any | no | yes | integer |
reviewed_by_name | Full name of the user who completed the review | no | no | any | no | yes | string |
added_by_id | Coupa unique identifier of the user who added this reviewer (XML tag: added-by-id) | no | no | any | no | yes | integer |
added_by_name | Full name of the user who added this reviewer | no | no | any | no | yes | string |
can_bypass_review | Boolean flag indicating whether review bypass is permitted (XML tag: can-bypass-review) | no | no | true, false | no | yes | boolean |
note | Notes or review comments entered by the reviewer | no | no | any | no | yes | text |
review_chain_description | Description explaining the rule or chain that triggered the review (Array of strings in JSON; Array of rule description objects in XML) | no | no | any | no | yes | array |
created_at | Timestamp when review entry was created (XML tag: created-at) | no | no | any | no | yes | datetime |
updated_at | Timestamp when review entry was updated (XML tag: updated-at) | no | no | any | no | yes | datetime |
created_by | User who created the review record (XML tag: created-by) | no | no | any | no | yes | User |
updated_by | User who updated the review record (XML tag: updated-by) | no | no | any | no | yes | User |
The following elements are nested under metadata:
| Element | Description | Required Field? | Unique? | Allowable Value | Api_In Field? | Api_Out Field? | Data Type |
|---|---|---|---|---|---|---|---|
can_complete_review | Indicates if current user can complete the review (XML tag: can-complete-review) | no | no | true, false | no | yes | boolean |
can_start_review | Indicates if current user can start the review (XML tag: can-start-review) | no | no | true, false | no | yes | boolean |
can_add_reviewer | Indicates if current user can add a reviewer (XML tag: can-add-reviewer) | no | no | true, false | no | yes | boolean |
has_counterparty_reviews | Indicates presence of counterparty reviews (XML tag: has-counterparty-reviews) | no | no | true, false | no | yes | boolean |
can_add_watcher | Indicates if current user can add a watcher (XML tag: can-add-watcher) | no | no | true, false | no | yes | boolean |
is_reviewer | Indicates if current user is assigned as a reviewer (XML tag: is-reviewer) | no | no | true, false | no | yes | boolean |
is_watcher | Indicates if current user is an active watcher (XML tag: is-watcher) | no | no | true, false | no | yes | boolean |
is_owner_creator | Indicates if current user is the contract owner/creator (XML tag: is-owner-creator) | no | no | true, false | no | yes | boolean |
The following elements are nested under watchers (XML tag: watcher):
| Element | Description | Required Field? | Unique? | Allowable Value | Api_In Field? | Api_Out Field? | Data Type |
|---|---|---|---|---|---|---|---|
id | Coupa unique identifier of the watcher record | no | no | any | no | yes | integer |
watcher_id | Coupa unique user ID of the watcher (XML tag: watcher-id) | no | no | any | no | yes | integer |
watcher_type | Watcher entity type (e.g. User) | no | no | any | no | yes | string |
watcher_name | Full name of the watcher | no | no | any | no | yes | string |
watcher_email | Email address of the watcher | no | no | any | no | yes | string |
can_remove_watcher | Indicates if current user can remove this watcher (XML tag: can-remove-watcher) | no | no | true, false | no | yes | boolean |
created_at | Timestamp when watcher was added (XML tag: created-at) | no | no | any | no | yes | datetime |
created_by_id | Coupa user ID of creator (XML tag: created-by-id) | no | no | any | no | yes | integer |
created_by_name | Full name of the user who added the watcher | no | no | any | no | yes | string |
Contract Rounds API Example Calls
Query Options for Contract Rounds:
This query retrieves all rounds, reviewer statuses, metadata, and watchers for a contract:
https://<instance>.coupahost.com/api/contracts/<contract_id>/contract_rounds
Please note key structural and naming conventions across formats:
- JSON Naming & Root Structure: Standard JSON responses use underscores (
snake_case, e.g.created_at,first_notified_at) and return a top-level JSON object containing"contract_rounds","metadata", and"watchers". Thereview_chain_descriptionfield returns an array of formatted strings. - XML Naming & Root Structure: XML responses are wrapped in a top-level
<hash>root element containing<contract-rounds>,<metadata>, and<watchers>. Standard timestamp/relationship tags use hyphens (kebab-case, e.g.<created-at>), while specific attributes use underscores (e.g.<reviewer_type>,<reviewer_email>). The<review-chain-description>node returns an array of structured rule objects.
Contract Rounds API GET Example (XML)
In this example, we queried for the contract rounds associated with contract ID 1263.
We did a GET to the URL:
https://<instance url>/api/contracts/1263/contract_rounds
Here is the response matching the search criteria:
<?xml version="1.0" encoding="UTF-8"?>
<hash>
<contract-rounds type="array">
<contract-round>
<id type="integer">1263</id>
<created-at type="dateTime">2026-06-05T10:29:05-06:00</created-at>
<updated-at type="dateTime">2026-06-05T10:50:21-06:00</updated-at>
<status>closed</status>
<reviews type="array">
<review>
<id type="integer">589</id>
<created-at type="dateTime">2026-06-05T10:46:44-06:00</created-at>
<updated-at type="dateTime">2026-06-05T10:50:21-06:00</updated-at>
<status>completed</status>
<note>Contract terms verified and approved.</note>
<reviewed-at type="dateTime">2026-06-05T10:50:21-06:00</reviewed-at>
<reviewed-by-id type="integer">522</reviewed-by-id>
<first-notified-at type="dateTime">2026-06-05T10:46:44-06:00</first-notified-at>
<last-reminded-at nil="true"/>
<reviewer-id type="integer">522</reviewer-id>
<reviewer_type>User</reviewer_type>
<added-by-id nil="true"/>
<reviewer_name>Alex Morgan</reviewer_name>
<reviewed-by-name>Alex Morgan</reviewed-by-name>
<added-by-name nil="true"/>
<review-chain-description type="array">
<review-chain-description>
<id type="integer">699</id>
<review-id type="integer">589</review-id>
<key>review.reason.added_by_review_chain</key>
<params>
<review_chain_name>Legal High Value Chain</review_chain_name>
</params>
<created-at type="dateTime">2026-06-05T10:46:44-06:00</created-at>
<updated-at type="dateTime">2026-06-05T10:46:44-06:00</updated-at>
</review-chain-description>
</review-chain-description>
<can-bypass-review type="boolean">false</can-bypass-review>
<reviewer_email>alex.morgan@example.com</reviewer_email>
<created-by>
<id type="integer">522</id>
<login>alex.morgan@example.com</login>
<employee-number nil="true"/>
<firstname>Alex</firstname>
<lastname>Morgan</lastname>
<fullname>Alex Morgan</fullname>
<email>alex.morgan@example.com</email>
<salesforce-id nil="true"/>
<avatar-thumb-url nil="true"/>
</created-by>
<updated-by>
<id type="integer">522</id>
<login>alex.morgan@example.com</login>
<employee-number nil="true"/>
<firstname>Alex</firstname>
<lastname>Morgan</lastname>
<fullname>Alex Morgan</fullname>
<email>alex.morgan@example.com</email>
<salesforce-id nil="true"/>
<avatar-thumb-url nil="true"/>
</updated-by>
</review>
</reviews>
<started-at type="dateTime">2026-06-05T10:29:05-06:00</started-at>
<internal-review-started-at type="dateTime">2026-06-05T10:29:05-06:00</internal-review-started-at>
<internal-review-completed-at type="dateTime">2026-06-05T10:50:21-06:00</internal-review-completed-at>
<negotiation-started-at nil="true"/>
<negotiation-completed-at nil="true"/>
<position type="integer">1</position>
<counterparty-reviews type="array"/>
<created-by>
<id type="integer">522</id>
<login>alex.morgan@example.com</login>
<employee-number nil="true"/>
<firstname>Alex</firstname>
<lastname>Morgan</lastname>
<fullname>Alex Morgan</fullname>
<email>alex.morgan@example.com</email>
<salesforce-id nil="true"/>
<avatar-thumb-url nil="true"/>
</created-by>
<updated-by>
<id type="integer">522</id>
<login>alex.morgan@example.com</login>
<employee-number nil="true"/>
<firstname>Alex</firstname>
<lastname>Morgan</lastname>
<fullname>Alex Morgan</fullname>
<email>alex.morgan@example.com</email>
<salesforce-id nil="true"/>
<avatar-thumb-url nil="true"/>
</updated-by>
</contract-round>
</contract-rounds>
<metadata>
<can-complete-review type="boolean">false</can-complete-review>
<can-start-review type="boolean">false</can-start-review>
<can-add-reviewer type="boolean">false</can-add-reviewer>
<has-counterparty-reviews type="boolean">false</has-counterparty-reviews>
<can-add-watcher type="boolean">false</can-add-watcher>
<is-reviewer type="boolean">false</is-reviewer>
<is-watcher type="boolean">false</is-watcher>
<is-owner-creator type="boolean">false</is-owner-creator>
</metadata>
<watchers type="array">
<watcher>
<id type="integer">171</id>
<watcher_type>User</watcher_type>
<watcher_name>Taylor Reed</watcher_name>
<can-remove-watcher type="boolean">false</can-remove-watcher>
<created-at type="dateTime">2026-06-05T10:50:21-06:00</created-at>
<created-by-id type="integer">541</created-by-id>
<watcher-id type="integer">541</watcher-id>
<watcher_email>taylor.reed@example.com</watcher_email>
<created_by_name>Taylor Reed</created_by_name>
</watcher>
</watchers>
</hash>
Contract Rounds API GET Example (JSON)
We did a GET with header Accept: application/json to the URL:
https://<instance url>/api/contracts/1263/contract_rounds
Here is the response matching the search criteria:
{
"contract_rounds": [
{
"id": 1263,
"created_at": "2026-06-05T10:29:05-06:00",
"updated_at": "2026-06-05T10:50:21-06:00",
"status": "closed",
"reviews": [
{
"id": 589,
"created_at": "2026-06-05T10:46:44-06:00",
"updated_at": "2026-06-05T10:50:21-06:00",
"status": "completed",
"note": "Contract terms verified and approved.",
"reviewed_at": "2026-06-05T10:50:21-06:00",
"reviewed_by_id": 522,
"first_notified_at": "2026-06-05T10:46:44-06:00",
"last_reminded_at": null,
"reviewer_id": 522,
"reviewer_type": "User",
"added_by_id": null,
"reviewer_name": "Alex Morgan",
"reviewed_by_name": "Alex Morgan",
"added_by_name": null,
"review_chain_description": [
"Added by the review chain: Legal High Value Chain"
],
"can_bypass_review": false,
"reviewer_email": "alex.morgan@example.com",
"created_by": {
"id": 522,
"login": "alex.morgan@example.com",
"employee_number": null,
"firstname": "Alex",
"lastname": "Morgan",
"fullname": "Alex Morgan",
"email": "alex.morgan@example.com",
"salesforce_id": null,
"avatar_thumb_url": null
},
"updated_by": {
"id": 522,
"login": "alex.morgan@example.com",
"employee_number": null,
"firstname": "Alex",
"lastname": "Morgan",
"fullname": "Alex Morgan",
"email": "alex.morgan@example.com",
"salesforce_id": null,
"avatar_thumb_url": null
}
}
],
"started_at": "2026-06-05T10:29:05-06:00",
"internal_review_started_at": "2026-06-05T10:29:05-06:00",
"internal_review_completed_at": "2026-06-05T10:50:21-06:00",
"negotiation_started_at": null,
"negotiation_completed_at": null,
"position": 1,
"counterparty_reviews": [],
"created_by": {
"id": 522,
"login": "alex.morgan@example.com",
"employee_number": null,
"firstname": "Alex",
"lastname": "Morgan",
"fullname": "Alex Morgan",
"email": "alex.morgan@example.com",
"salesforce_id": null,
"avatar_thumb_url": null
},
"updated_by": {
"id": 522,
"login": "alex.morgan@example.com",
"employee_number": null,
"firstname": "Alex",
"lastname": "Morgan",
"fullname": "Alex Morgan",
"email": "alex.morgan@example.com",
"salesforce_id": null,
"avatar_thumb_url": null
}
}
],
"metadata": {
"can_complete_review": false,
"can_start_review": false,
"can_add_reviewer": false,
"has_counterparty_reviews": false,
"can_add_watcher": false,
"is_reviewer": false,
"is_watcher": false,
"is_owner_creator": false
},
"watchers": [
{
"id": 171,
"watcher_type": "User",
"watcher_name": "Taylor Reed",
"can_remove_watcher": false,
"created_at": "2026-06-05T10:50:21-06:00",
"created_by_id": 541,
"watcher_id": 541,
"watcher_email": "taylor.reed@example.com",
"created_by_name": "Taylor Reed"
}
]
}
Error Handling
| Response Code | Message / Reason | Solution |
|---|---|---|
401 Unauthorized | Unauthorized | Verify your X-COUPA-API-KEY is active and passed correctly. |
404 Not Found | Contract not found. | Verify the contract ID exists and that the specified user has membership in the contract's Content Group. |
404 Not Found | User not found. | Verify the user ID specified in X-COUPA-USER-ID exists in the instance. |