General
Tipalti Procurement provides programmatic access to data through REST APIs. With our APIs, you can read and modify Procurement data, enabling integration with your own platforms.
Disclaimer
The Procurement APIs and this document are subject to change. We may update the APIs occasionally and add new fields to the existing API version, which you can ignore.
We’ll make a new API version available and communicate any structural changes that may break APIs, such as deleting existing fields or changing their location.
Technical details
The API is accessible via HTTPS calls to specific access points, as detailed below. The URL contains the resource requested or updated and query parameters on the URL line where relevant.
POST requests also include a request body.
Both the request body and responses are in standard JSON format, and the dates are in ISO 8601 format.
Rate limit
Tipalti API employs several safeguards against bursts of incoming traffic to help maximize its stability. If many requests are sent in quick succession, this might lead to error responses that show up as status code 429 - Too many requests.
We have an API rate limit limiting the number of requests the API receives during a set period. The API is typically low-scale since it deals with POs. We expect no more than 5 requests per minute from typical customers for updating POs. Getting PRs or POs should be no more than every 10 minutes. This is typically what works for customers using this API, together with setting the fromDate property correctly.
HTTP status codes
|
Status code |
Description |
|---|---|
| 429 Too many requests |
The client sent too many requests in a given timeframe, exceeding the predefined rate limit. The response indicates which limit was reached and when. |
HTTP 429 error response
Text
{
Content: 'API calls quota exceeded. The maximum number of requests allowed: X per YYY {s/m/h/d}'
}
The response header includes:
|
Header |
Description |
|---|---|
|
Retry-After Integer |
Indicates the time, in seconds, the developer must wait before performing a new API request. |
Authentication
To access the sandbox or production environments, contact your Implementation Manager to obtain an API token. The token must be included in the x-api-key header of every endpoint.
Environments
Tipalti has two environments for running your code:
- Sandbox is the test environment. The base URL is https://triggers.sandbox.approve.com
- Production is the live environment. The base URL is https://triggers.approve.com
These environments are completely separated and have no integration between them.
Conventions
|
Type |
Convention |
|---|---|
| ID property |
Each resource has a unique ID represented as a string. |
| date-time |
Date and times are always UTC unless stated otherwise. The date-time format of returned data adheres to ISO 8601 and is in this format: yyyy-MM-ddTHH:mm:ss:fffZ. The date-time format of fromDate and toDate (which the user provides) is YYYY-MM-DDTHH:mm. |
| Body |
Each resource has a unique ID represented as a string. |
APIs
The purchase orders API is designed to collect information on your purchase orders from Tipalti using the GET PO endpoint and the Update PO endpoint to update the POs in Tipalti to match your system's latest updates.
You can use these endpoints to ensure your Tipalti Procurement account and your system are both up to date and in sync without Tipalti directly accessing your system. This is an alternative way to ensure your Tipalti and system accounts are in sync while keeping within your system’s security requirements.
Purchase orders are purchase requests that were already approved in Tipalti. Use the Purchase request endpoint to retrieve data on your outstanding purchase requests.
Main workflow
The main workflow is:
- Retrieve a list of POs from Tipalti using the GET POs endpoint.
- If you set forceReadAll = true, you can retrieve all the POs in Tipalti regardless of whether they have external IDs or not.
- If you set forceReadAll = false, this only retrieves the POs in Tipalti without an external ID.
- Use the Update POs POST endpoint to push the POs back to Tipalti with the external ID you took from your system.
GET GET /api/v1/resources/pos
Retrieves a list of POs from Tipalti.
Request
Header
x-api-key: <api_token>
Query parameters
| Parameter | Mandatory | Valid value | Default value | Description |
|---|---|---|---|---|
| forceReadAll | No |
true false |
false |
False Only returns POs without an externalId so the caller can push them into their ERP True Returns all POs with or without an externalId |
| fromDate | N | Date | Beginning of time: 0000-01-01T00:00 | The date you want to collect POs from. Typically, no more than 1 day before. |
|
toDate Required if forceRead is true |
N | Date | Present time |
If specified, toDate only returns results for POs that were created up to the specified date. Otherwise, all results are returned up until the present time. Use toDate with fromDate to get POs from a specific date range in the past. Example with both fromDate and toDate: /api/v1/resources/pos?fromDate=2025-02-19T10:00&toDate=2025-02-19T11:00 |
Response
| Name | Description |
|---|---|
| id, string | The unique identifier of the PO in Tipalti. You must use this when calling the Update PO endpoint. |
| title, string | The PO title as it appears in your system or if the purchase request was created in Tipalti, then the title of the PO generated in Procurement. |
| description, string | The PO's description |
| currency, string | The currency of this PO |
| amount, string | The amount of this PO |
| requests, array | An array of one or more purchase request objects that are part of this PO. If this PO merges several purchase requests (PRs), there’ll be more than one element. Otherwise, this will be an array of one element. |
| items, array |
An array of zero or more item objects contained in this PO. These are the PRs that are part of this PO. If this PO has more than one PR, all the items of all the PRs are shown as part of this one PO. |
| vendor, object | Properties of the vendor of this PO |
| requesters, array |
An array of one or more requesters that are part of this PO. Every PR in this PO has a corresponding requester. |
| externalId, string |
The unique identifier of the PO that’s taken from your system. You must specify forceReadAll=true to return POs with an externalId. |
POST POST /api/v1/resources/pos
The Update PO endpoint updates specific properties on an existing PO related to your system. Use this endpoint when you don’t want to connect Tipalti directly to your system. Log in to the Tipalti Hub if you want to make any other changes to the PO that aren’t covered by this endpoint.
Request
Header
x-api-key: <api_token>
Body
| Property | Description |
|---|---|
| id, string |
The unique identifier of the PO in Tipalti. This must be the same ID field that is returned for the id parameter of the GET method for the GET POs endpoint |
| externalId, string | The PO’s ID in your ERP system |
|
erpStatus, string optional |
In case of PO rejection, you can populate this field with rejected. It’ll then be reflected in the Tipalti Hub for that PO. |
|
internalDocumentNumber, string optional |
This is another PO identifier that’s used with NetSuite. How it’s used with the externalId depends on how the API is implemented into each customer's PO and ERP flow. |
|
erpErrorMessage, string optional |
An error message that was returned by the ERP when the customer tried to add this PO to the ERP. If you send this field, the error message will be displayed in the Purchases View in the UI, making the error visible to the user. |
Example
Request
POST <<base_url>>/api/v1/resources/pos
Example of a call to Update PO endpoint after the PO is successfully inserted into the customer's ERP:
{
"id": "67149cd80d96ea001a990923",
"receival": {
"deliveredOn": "2024-10-20T06:55:10.915Z",
"quantity": 2,
"description": "Got 2 chairs today in good condition"
}
}
Example of a call to Update PO endpoint after the PO is successfully inserted into the customer's ERP:
{
"id": "67149cd80d96ea001a990923",
"receival": {
"deliveredOn": "2024-10-20T06:55:10.915Z",
"quantity": 2,
"description": "Got 2 chairs today in good condition"
}
}
Once updated successfully, when you run the GET method for the POs API with forceReadAll=true, the above sample request returns the externalId parameter with the value 9988 and internalDocumentNumber with value PO1001.
Success response
{ "status" : "ok" }.
Failed response
{ "status": "error", "message": "<some error message>" }
POST POST/ api/v1/resources/getUploadUrl
This endpoint lets you update your employee list in Tipalti.
Once the list is updated, payer admins can invite the employees via Procurement settings in the Tipalti Hub. If you’re using SSO, any employee can access the Tipalti Hub without an invite. They’re assigned employee role permissions.
Request
Header
x-api-key: <api_token>
The first endpoint getUploadUrl will return a URL that you’ll use to upload a CSV file.
The provided URL will be available for 60 seconds. After that, it expires, and you’ll need to call getUploadUrl again.
Example
POST <<base_url>>/api/v1/resources/getUploadUrl
Response
Example
{
"status": "ok",
"csvUrl": "SampleURL"
}
Open a terminal and go to the folder where your file is located and then run this command: curl -X PUT -T <File name>.csv -L <Provided URL>
- The maximum file size is 10 MB.
- You should either run this command manually from a terminal, or run an automatic equivalent from your system.
POST POST api/v1/resources/importEmployeesAsCsv
Run the update employees endpoint with your UploadCSV URL to import the employees in the CSV file.
If an error occurs when you run the upload, the response provides the details so you know how to fix it.
Request
Header
x-api-key: <api_token>
Example
POST <<base_url>>/api/v1/resources/importEmployeesAsCsv
{ "csvUrl" : "<Provided URL>" }
Success response
{
"status": "ok",
}
Error responses
{
"status": "error",
"message":
}
Error messages
| Error | Description |
|---|---|
| Incorrect URL |
The URL was sent incorrectly |
| Can’t find the file | The file was uploaded incorrectly, or there’s something wrong with the sent URL |
|
CSV file too large |
The uploaded file is over the maximum size of 10MB |
Example
Error response
Example of a response in case of errors in the CSV:
{
"heading": "The organization contains duplicate emails",
"body": "demo@approve.com",
"error_key": {
"message": "DUPLICATE_USER_ID_IN_FILE",
"payload": [
{
"email": "demo@approve.com",
"lines": [ 16, 17 ],
"byKey": "email"
}
]
}
}
Comments
0 comments
Please sign in to leave a comment.