Skip to main content

Public API conventions

These rules apply to every route. The API reference gives the details for each one.

Requests and responses​

  • HTTPS only, TLS 1.2 or later.
  • JSON bodies in UTF-8, with Content-Type: application/json. The token URL is the exception: it takes a form.
  • Field names are camelCase. IDs are UUIDs.
  • Dates are YYYY-MM-DD. Times are ISO 8601 with an offset, for example 2026-11-15T09:30:00Z.
  • A field is only returned if the reference lists it. Still, ignore fields you don't recognise, so your integration keeps working if one is added in a later version.

Paging​

List routes return one page at a time:

{ "items": [ ... ], "nextCursor": "eyJpZCI6..." }
ParameterMeaning
limitItems per page, 1 to 200. Default 50
cursorThe nextCursor value from the previous page. Leave it out for the first page

Keep requesting pages while nextCursor isn't null. Treat the cursor as an opaque value: don't build or change one.

To keep a copy of employees up to date, do one full read, then pass updatedSince with the time of your previous run to GET /v1/employees to get only employees changed since.

Rate limits​

LimitApplies to
120 requests a minuteEach client, across all API routes
30 requests a minuteThe token URL, per source address

API responses include X-RateLimit-Remaining, the calls left in the current minute. Over a limit, the API returns 429 with Retry-After, the number of seconds to wait. Wait at least that long before retrying, and slow down rather than retrying straight away. A first full sync of a large tenant is the usual cause: spread it out over a few minutes.

Retries and idempotency​

Reads can be retried safely.

POST /v1/employees and POST /v1/attendance/punches need an Idempotency-Key header: a unique value of 16 to 128 characters, such as a UUID, for each operation.

  • If a call times out or fails with a network error, send it again with the same key and the same body. You get the first result, and nothing is created twice.
  • Use a new key for each new operation.
  • Keys are kept for 24 hours.
  • The same key with a different body, or while the first request is still running, returns 409.

If an employee create gets no answer at all, look the employee up before trying again with a new key, because it may have been created.

Errors​

API errors use problem details (RFC 9457), with Content-Type: application/problem+json. detail, when present, explains what was wrong:

{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.4",
"title": "Forbidden",
"status": 403,
"traceId": "00-bcf0593eaf9aa9f5a16985260520ba34-a4a8d507048989ac-00"
}
StatusMeaning
400The request is malformed or a value is invalid. detail says which
401The access token is missing, expired or invalid
403The token doesn't hold the scope this route needs
404The record doesn't exist or belongs to another tenant, or the route isn't part of the API
409An Idempotency-Key conflict
429A rate limit. See Retry-After
5xxA problem on our side. Retry later, with the same Idempotency-Key for writes

Include traceId whenever you contact HCM Cafe about an error. Some 403, 404 and 429 responses come from the network edge before the API, and those aren't problem details.

Versioning​

The version is in the path, currently /v1. Within a version, changes are additive only: new routes, new optional fields and new optional parameters. A change that could break an integration goes into a new version, announced in advance, with the old version kept running during a transition period.