Coupa Approvals Handling
Overview
This is an experience API that allows One Zurich to retrieve all outstanding Coupa object approvals for a given employee.
Functionality
The operations allowed by the API are:
- Retrieve Coupa approvals matching certain criteria (GET /approvals)
- Perform approve action to the employee with unique approval id (PUT /approvals/approve)
- Perform reject action to the employee with unique approval id (PUT /approvals/reject)
Obtaining Access
These steps assume you are already registered to use the Zurich Sourcing & Procurement Exchange. If you are not, please Register for an account in order to proceed.
Request Access to a specific API
- If you have not already done so you will need to obtain an application client identifier and secret that you use to interact with this API. This can be obtained from the Zurich Sourcing & Procurement Exchange by selecting this API and click "Request API access".
- Select the "Instance" you wish to access - i.e. for a specific test environment or Production. Depending on the type of API you may have multiple options or just one available to you.
- Select the "Tier" that you wish to access. The tiers represent the policies that might apply to the API (i.e. Bronze may be restricted to n calls per minute). Tiering for most APIs is set as follows:
- Bronze (1 API call per second - designed for testing and development)
- Silver (10 API calls per second - for larger volume scenarios)
- Gold (100 API calls per second - use for Production scenarios)
- Click Next
- "Select an existing application" from the dropdown (if you have already requested access for other APIs), or "Create a new client application" and add a meaningful name. This Client Application will be linked to the key you'll be issued with for this API.
- Read the Terms & Conditions and check the box to accept these.
- Click "Request Access" to complete the request.
- Once submitted your access request will be reviewed and approved usually within 1 working day. You will receive an e-mail upon approval containing the client credentials required to access this API.
Make your first API request
In this example we will use the HTTP GET method to retrieve approvals information. The steps described here are generic and follow cURL based conventions, however feel free to use your preferred API client.
- Set the API endpoint based on target environment instance, for example: https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1/approvals
- Set your client identifier and client secret in the respective headers.
cURL examples
Example Request
Using cURL it is possible to send the example request detailed above using the command shown below:
curl --location --request GET 'https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1/approvals?employeeNumber=1234567890' \
--header 'X-Z-Request-Id: 980ee44a-58e2-4cde-92c3-9317ca205fe0' \
--header 'client_id: client-id' \
--header 'client_secret: client-secret' \
Example response
A successful request for this endpoint will return a 200 OK status code with various approvals and details matching the search criteria:
{
"employeeNumber": "1234567890",
"userId": 1234,
"userFullname": "John Doe",
"requisitionApprovals": [
{
"requisitionDetails": {
"url": "https://zurich-test.coupahost.com:443/api/requisitions/456",
"status": "ordered",
"requestedBy": "John Doe",
"requestedByUserType": "Employee",
"requisitionTitle": "Requisition Title",
"requisitionSupplier": "SUPPLIER LTD",
"requisitionTotal": "100.00",
"requisitionLineCount": 2,
"requisitionJustification": "Justification comment",
"comments": [
{
"comment": "Additional comment.",
"createdBy": "John Doe",
"createdDate": "2018-11-06T09:33:09+00:00"
}
]
},
"approvableId": 456,
"approvableType": "InvoiceHeader",
"approvalReason": "Added by the approval chain.",
"approvalStatus": "pending_approval",
"approvalId": 123,
"approvalCreatedDate": "2018-11-02T12:07:49+00:00",
"approvalNote": "Approval note",
"approvalType": "DelegateApproval"
}
],
"invoiceApprovals": [
{
"invoiceDetails": {
"url": "https://zurich-test.coupahost.com:443/api/invoices/456",
"status": "approved",
"createdBy": "John Doe",
"createdByUserType": "Employee",
"invoiceNumber": "1234567890",
"invoiceSupplier": "SUPPLIER LTD",
"invoiceGrossTotal": "100.00",
"invoiceLineCount": 2,
"comments": [
{
"comment": "Additional comment.",
"createdBy": "John Doe",
"createdDate": "2018-11-06T09:33:09+00:00"
}
]
},
"approvableId": 456,
"approvableType": "InvoiceHeader",
"approvalReason": "Added by the approval chain.",
"approvalStatus": "pending_approval",
"approvalId": 123,
"approvalCreatedDate": "2018-11-02T12:07:49+00:00",
"approvalNote": "Approval note",
"approvalType": "DelegateApproval"
}
],
"expenseReportApprovals": [
{
"approvableId": 456,
"approvableType": "InvoiceHeader",
"approvalReason": "Added by the approval chain.",
"approvalStatus": "pending_approval",
"approvalId": 123,
"approvalCreatedDate": "2018-11-02T12:07:49+00:00",
"expenseReportDetails": {
"url": "https://zurich-test.coupahost.com:443/api/expense_reports/456",
"status": "approved_for_payment",
"expensedBy": "John Doe",
"expensedByUserType": "Employee",
"expenseReportTitle": "Expense Report Title",
"expenseReportTotal": "100.00",
"expenseReportScore": 84,
"expenseReportLineCount": 2,
"comments": [
{
"comment": "Additional comment.",
"createdBy": "John Doe",
"createdDate": "2018-11-06T09:33:09+00:00"
}
]
},
"approvalNote": "Approval note",
"approvalType": "DelegateApproval"
}
],
"contractApprovals": [
{
"contractDetails": {
"url": "https://zurich-test.coupahost.com:443/api/contracts/456",
"status": "published",
"createdBy": "John Doe",
"createdByUserType": "Employee",
"contractNumber": "456",
"contractName": "Contract Name",
"contractSupplier": "SUPPLIER LTD",
"contactStartDate": "2018-10-29T05:53:18+00:00",
"contactEndDate": "2019-10-29T05:53:18+00:00"
},
"approvableId": 456,
"approvableType": "InvoiceHeader",
"approvalReason": "Added by the approval chain.",
"approvalStatus": "pending_approval",
"approvalId": 123,
"approvalCreatedDate": "2018-11-02T12:07:49+00:00",
"approvalNote": "Approval note",
"approvalType": "DelegateApproval"
}
]
}
In this example we will use the HTTP PUT method to perform approve action based on unique approval id. The steps described here are generic and follow cURL based conventions, however feel free to use your preferred API client.
- Set the API endpoint based on target environment instance, for example: https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1/approvals/approve
- Set your client identifier and client secret in the respective headers.
cURL examples
Example Request
Using cURL it is possible to send the example request detailed above using the command shown below:
curl --location --request GET 'https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1/approvals/approve' \
--header 'X-Z-Request-Id: 980ee44a-58e2-4cde-92c3-9317ca205fe0' \
--header 'client_id: client-id' \
--header 'client_secret: client-secret' \
--data '{
"employeeId": "C8634xxxx",
"userId": "22875",
"userFullName": "John Doe",
"approvalId": 1,
"approvable": {
"type": "InvoiceHeader",
"objectId": "1",
"reason": "Approve reason"
}
}'
Example response
A successful request for this endpoint will return information that the approve action is successfully completed.
204 - The approve has been replaced successfully.
In this example we will use the HTTP PUT method to perform approve action based on unique approval id. The steps described here are generic and follow cURL based conventions, however feel free to use your preferred API client.
- Set the API endpoint based on target environment instance, for example: https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1/approvals/reject
- Set your client identifier and client secret in the respective headers.
cURL examples
Example Request
Using cURL it is possible to send the example request detailed above using the command shown below:
curl --location --request GET 'https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1/approvals/reject' \
--header 'X-Z-Request-Id: 980ee44a-58e2-4cde-92c3-9317ca205fe0' \
--header 'client_id: client-id' \
--header 'client_secret: client-secret' \
--data '{
"employeeId": "C8634xxxx",
"userId": "22875",
"userFullName": "John Doe",
"approvalId": 1,
"approvable": {
"type": "InvoiceHeader",
"objectId": "1",
"reason": "Reject reason"
}
}'
Example response
A successful request for this endpoint will return information that the reject action is successfully completed.
204 - The approve has been replaced successfully.
The s2p-e-one-zurich-approvals API accepts HTTPS/TLS connections only in order to protect the integrity and confidentiality of any data transferred. HTTP connections are refused - plaintext communication is not supported.
API access is governed through an Anypoint Platform enforced Client Id/Secret policy.
Client ID/Secret
Complete the pre-requisite steps on the Getting Started page to obtain API client credentials.
The Client Id/Secret is enforced using the Client ID Authentication scheme. This requires the client id and client secret values to be passed as HTTP headers on the request.
The format of the headers is as follows:
client_id
client_secret
The values for these headers will correspond to the values provided after requesting access to the API.
The API will return a 401 HTTP Status Code in case of invalid credentials.
This API uses conventional HTTP response codes to indicate the success or failure of an API request.
In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required field was omitted). Codes in the 5xx range indicate an error with the server.
Error HTTP Status Code Summary
Status Code | Description |
---|---|
400 Bad Request | The server could not understand the request due to invalid syntax. |
401 Unauthorized | Invalid token. The server was unable to authenticate the user. |
412 Precondition Failed | Failed updating resource due to invalid If-Match. |
415 Unsupported Media Type | The media format of the requested data is not supported by the server. |
428 Precondition Required | Required header 'If-Match' not provided. |
500 Internal Server Error | An internal server error was observed. |
502 Bad Gateway | The server encountered received an invalid response from an inbound server it accessed while attempting to fulfil the request. |
503 Service Unavailable | The server was unable to handle the request due to a temporary overloading or maintenance of the server. |
Please refer to each individual resource and method endpoint definition for specific details on the possible status codes returned.
Error Response
Attributes
Field Name | Description |
---|---|
code | Pattern based scheme that identifies a specific and unique error condition. Typically human readable but more suited for machine processing. |
message | Human readable description of the error that occurred that is not intended to be machine parseable. |
correlationId | Provide ability to rapidly identify and trace distributed request processing. |
source | Optional. Describes the source of the error; used to indicate the error originated elsewhere or self-reference when error was generated internally or in direct consequence of downstream events. |
source/name | Implementation provider defined name for the API, service or system. |
source/layer | Implementation provider defined API architecture layer for the API, service or system. |
causes | Optional. A list of error causes that provide further detail around the exception at hand. |
causes/code | Optional. Pattern based string that identifies a more fine grained error condition, which contributed to the general/parent error code above. |
causes/message | Mandatory. More specific information on the failure cause. |
causes/field | Optional. A JSON Pointer (RFC6901) that identifies the entity or entity attribute responsible for the more specific error code and message. |
causes/source | Optional. See “source” object definition above. |
Error Codes
The table below lists the possible error codes that can be returned from the API. This code identifies a specific and unique error condition, as described in the table below:
Field Name | Description |
---|---|
data_validation | Request does not adhere to the specification. |
not_found | The requested endpoint or resource does not exist. |
method_not_allowed | The method received in the request-line is known by the origin server but not supported by the target resource. |
not_acceptable | The service is unable to fulfil the request based on the Accept header provided. |
unsupported_media_type | The payload format is in an unsupported format. |
not_implemented | The requested resource is defined in the specification but not implemented. |
internal_server_error | An internal server error was observed. |
Error Response Payload Examples
{
"code": "authentication_error",
"message": "Invalid token.",
"correlationId": "15432490-fcfd-11ec-a8fb-0a2137830b12"
}
Exchange Name: s2p-e-one-zurich-approvals
Environments available
By default we only publish the Mock and Production versions of the API for consumption because the underlying service is the same in all circumstances. Additional environments can be subscribed on special request.
URLs
This API is published to the following environments:
Environment | URL |
---|---|
Mock | See mocking service. |
Production | https://prod.esmuleapi.zurich.com/z-s2p-e-one-zurich-approvals-v1 |
Additional environments are provided for development of the API but these should only be used in consultation with the API team.
Approach to versioning
Where possible, the S2P team will make changes to the API but not change the version number because the changes are not considered to be backward compatible. Such changes can be any of the following:
- Addition of new resources
- Addition of new non-mandatory request parameters of attributes
- Addition of new data fields returned in the response
- Change in the order of data fields returned by the API
There might be some instances in which breaking enhancements need to happen. In such circumstances, a new version is released not to break compatibility. Such enhancements include:
- Inclusion or removal of mandatory parameters
- Restructuring of the API interface
Upon the release of a new version, applications can continue using the old version, allowing the consumer to assess the changes needed. Release notes with all the changes will be provided with every new version, describing all the changes in detail.
Upon upgrading, consumers are required to request access to the new major version of the API. Given the potential breaking changes, consumers are encouraged to perform regression testing against the new version before upgrading to the new API version in production.
Release Notes
Contact the S2P team or your local service desk for more information or support.
Known Issues
Defect Id | Description |
---|---|
- | - |
Of particular importance is the requirement for all consumers of the API to ensure that the content that they send via the API has been assessed for compliance with Zurich's information security policies and are in compliance with your local data laws. This is a responsibility of the API Consumer and not the Service Provider.
In addition you may not:
- modify, obscure, reverse engineer, circumvent, or disable any element of the API or its access control features.
- disclose, share, or transfer your access credentials to any third party.
- transmit any viruses, worms, defects, trojan horses, or any other malware through your Application or use of the API.
- use robots, spiders, crawlers, scraping or other similar technology to obtain any information beyond what Zurich provides to you under these terms.
- use the API in a manner that exceeds reasonable request volume, constitutes excessive or abusive usage or otherwise fails to comply or is inconsistent with any part of the Zurich API documentation.
- infringe, misuse, or claim ownership of Zurich intellectual property or intellectual property rights therein.
- use it with an Application that is offensive, abusive, libelous, harassing, threatening, discriminatory, vulgar, pornographic, unethical, unlawful, or otherwise inappropriate as determined by Zurich in its sole discretion.
- assign or transfer your rights or obligations under this agreement.
Further terms of service are provided in separate terms & conditions which are presented when registering for the API.