Requests & Responses
The Everee API is a set of modern, RESTful HTTP endpoints designed for a good developer experience when integrating. This article covers some useful details you should know about building an integration with Everee.
API domain
All requests should be made to the Everee API at https://api.everee.com, whether you're working in Sandbox or Production. Your tenant ID and API token decide which environment a request acts on. See Sandbox & Production.
Always send your tenant ID
Every request carries your API token and your company's tenant ID in two headers. See Authentication & API tokens.
Always specify JSON
All endpoints in the Everee API both receive and respond with data serialized as JSON. When you make requests to the Everee API, you should specify that the content type of your request body is JSON, and you expect to receive JSON back, with these HTTP headers:
content-type: application/json
accept: application/json
If you provide data to endpoints in formats other than JSON, you'll receive a 400-level HTTP error. If you specify an accept header other than JSON (as shown above), the operation may succeed or fail as normal, but you may not receive a useful error message. Always plan to receive JSON (and use the accept header) to ensure you receive useful error messages when failures occur.
Unique request ID
All responses from the Everee API include a unique ID for that request. It's available in the response headers under the name request_id. If you reach out to Everee Support for help with the API, please include the value of this header if you have it. It'll make it faster for us to help you. The header is X-Request-ID.
You can also use it yourself. The Request Log API keeps your recent calls for 30 days, and you can look one up by its request ID to see what Everee received and what it answered.
Errors
When a request fails, you get an HTTP status code and a JSON body that describes the error:
{
"timestamp": "2026-10-16T18:04:22.381Z",
"errorCode": "...",
"errorMessage": "...",
"errorCause": "...",
"path": "/integration/v1/..."
}Use errorMessage to understand what went wrong. If you need to see exactly what was sent, the Request Log API stores the request and the error response for each failed call; see Diagnosing a failed request. Handle the status code first, then the body. A 429 means you've hit a rate limit.
Status codes follow a consistent rule:
4xxmeans the request needs to change. Fix it usingerrorMessage; retrying the same request won't help.400and422both mean a field or the request's current state is invalid, so handle them the same way.401and403mean the credentials or scopes can't perform the operation,404means something the request refers to doesn't exist, and409means the request conflicts with the current state of a resource.5xxmeans a fault on Everee's side. Retry with backoff, and contact Everee Support with theX-Request-IDif it persists.
Errors in bulk requests
Add items to a payroll run always checks the whole request and reports every failure at once.
Create payables (bulk) and Update classified hours (bulk) also take many items in one call. By default they stop at the first item that can't be accepted. Everee can have them report every failure too. Contact [email protected] to have it turned on for your company.
A request that reports every failure returns 400 with the usual body, plus a list of every failure:
{
"timestamp": "2026-10-30T18:04:22.381Z",
"errorCode": "400",
"errorMessage": "2 errors found across 120 items in the request. No items were saved.",
"path": "/integration/v1/payables/bulk",
"errorCount": 2,
"truncated": false,
"errors": [
{
"index": 4,
"path": "payables[4]",
"ids": { "externalId": "pay-123", "externalWorkerId": "emp-1042" },
"errorCode": "PAYABLE_EXTERNAL_ID_NOT_UNIQUE",
"errorMessage": "A payable with 'externalId' value 'pay-123' already exists.",
"field": "externalId"
},
{
"index": 17,
"path": "payables[17]",
"ids": { "externalId": "pay-140", "externalWorkerId": "emp-9999" },
"errorCode": "WORKER_NOT_FOUND",
"errorMessage": "Unknown 'externalWorkerId' value: 'emp-9999'",
"field": "externalWorkerId"
}
]
}- Nothing is saved when any item fails. The request is all-or-nothing. Fix every error, then send the whole request again.
- Match errors to your data with
ids. It repeats the identifiers you sent for the item, under the names you sent them with:externalId,workerId, orexternalWorkerId.indexis the item's position in your array, starting at 0, andpathlocates it in the body:payables[4]for payables, anditems[4]for payroll run items. For classified hours, an error on one entry has a path likeclassifiedHoursPerWorker[2].classifiedHours[0]and includes that entry'sexternalIdwhen you sent one. - Branch on
errorCode, not the message. Codes are stable. The message is for people and may change. fieldnames the property in your request that caused the failure, when there is one.truncatedistruewhen there were more than 500 errors.errorCountis the full count, anderrorsholds the first 500.- A request that isn't valid JSON, or is missing the list of items, still fails with a single error.
- A few failures can only be found while saving, such as creating a cost center from a name that can't be used. These are reported alone, and still save nothing. Send the request again after fixing it.
errorCode | Meaning |
|---|---|
PAYABLE_EXTERNAL_ID_NOT_UNIQUE | A payable with this externalId already exists, or the request sends the same externalId more than once |
DUPLICATE_ENTRY_EXTERNAL_ID | The request sends the same time card entry externalId more than once |
ENTRY_EXTERNAL_ID_IN_USE | The entry externalId already belongs to an entry for a different worker or pay period |
PERIOD_ALREADY_FINALIZED | The worker's pay period is paid. Send the request with correction-authorized=true if a correction is intended |
PAYABLE_ALREADY_PAID | Payroll runs: the item with this externalId has been paid. Send the request with correction-authorized=true if a correction is intended |
PAYABLE_ON_ANOTHER_PAYMENT | Payroll runs: the item with this externalId is on another payment that hasn't been paid. Remove it there first |
PAYROLL_RUN_PAYMENT_CLOSED | Payroll runs: the worker's payment in the run was excluded, or is past calculation, so it can't take new items |
WORKER_NOT_FOUND | No worker matches the workerId or externalWorkerId |
VALIDATION_FAILED | A field has an invalid value, such as a workLocationId that isn't numeric |
INVALID_REQUEST | The item can't be applied for another reason. errorMessage says what to change |
Formats
- Dates are ISO 8601 calendar dates, like
2026-10-16. - Timestamps are either ISO 8601 or Unix epoch seconds. Each endpoint's reference says which.
- Money is an object with an
amount, as a decimal value, and an ISO 4217currency, like{ "amount": "22.50", "currency": "USD" }. - Durations are ISO 8601, like
PT30M.
Retrying safely
Only retry requests that are safe to repeat. Only payables have an idempotency key. Payable items take an externalId that makes creating them idempotent. No other create endpoint has an idempotency key, so a retry after a timeout could create a duplicate. Before retrying any other create, look the record up first.
Updated 5 days ago