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:

  • 4xx means the request needs to change. Fix it using errorMessage; retrying the same request won't help. 400 and 422 both mean a field or the request's current state is invalid, so handle them the same way. 401 and 403 mean the credentials or scopes can't perform the operation, 404 means something the request refers to doesn't exist, and 409 means the request conflicts with the current state of a resource.
  • 5xx means a fault on Everee's side. Retry with backoff, and contact Everee Support with the X-Request-ID if 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, or externalWorkerId. index is the item's position in your array, starting at 0, and path locates it in the body: payables[4] for payables, and items[4] for payroll run items. For classified hours, an error on one entry has a path like classifiedHoursPerWorker[2].classifiedHours[0] and includes that entry's externalId when you sent one.
  • Branch on errorCode, not the message. Codes are stable. The message is for people and may change.
  • field names the property in your request that caused the failure, when there is one.
  • truncated is true when there were more than 500 errors. errorCount is the full count, and errors holds 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.
errorCodeMeaning
PAYABLE_EXTERNAL_ID_NOT_UNIQUEA payable with this externalId already exists, or the request sends the same externalId more than once
DUPLICATE_ENTRY_EXTERNAL_IDThe request sends the same time card entry externalId more than once
ENTRY_EXTERNAL_ID_IN_USEThe entry externalId already belongs to an entry for a different worker or pay period
PERIOD_ALREADY_FINALIZEDThe worker's pay period is paid. Send the request with correction-authorized=true if a correction is intended
PAYABLE_ALREADY_PAIDPayroll runs: the item with this externalId has been paid. Send the request with correction-authorized=true if a correction is intended
PAYABLE_ON_ANOTHER_PAYMENTPayroll runs: the item with this externalId is on another payment that hasn't been paid. Remove it there first
PAYROLL_RUN_PAYMENT_CLOSEDPayroll runs: the worker's payment in the run was excluded, or is past calculation, so it can't take new items
WORKER_NOT_FOUNDNo worker matches the workerId or externalWorkerId
VALIDATION_FAILEDA field has an invalid value, such as a workLocationId that isn't numeric
INVALID_REQUESTThe 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 4217 currency, 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.


Did this page help you?