Errors
Errors are returned as application/problem+json (RFC 9457). Branch on code, never on title — titles are for people and may be reworded. Every response, success or error, carries anX-Request-Id; include it when you contact support.
{
"type": "https://ahlanhamad.com/developers/errors#insufficient_scope",
"title": "This key does not have the payroll:read scope",
"status": 403,
"code": "insufficient_scope",
"request_id": "req_01J9…"
}| Code | Status | Meaning | What to do |
|---|---|---|---|
invalid_request | 400 | A query parameter, the JSON body or the cursor is malformed. | Fix the request. Retrying unchanged will fail the same way. |
unauthenticated | 401 | The key is missing, malformed, revoked, or the wrong kind for the company (an ah_test_ key on a live company or the reverse). | Check the Authorization header and the key's mode. Ask the customer for a new key if it was revoked. |
insufficient_scope | 403 | The key is valid but was not granted the scope this endpoint needs. | Ask the customer to create a key with the scope named in the error title. |
api_not_enabled | 403 | The Partner API is not enabled for this company yet (it opens to companies in stages). | Build against a sandbox company, and contact support to enable a pilot customer. |
not_found | 404 | No such resource in this company, or it is not visible to partners (a draft payroll run, for example), or no such endpoint. | Check the id and path. |
conflict | 409 | The request conflicts with the current state — for example redelivering to a disabled webhook endpoint. | Resolve the state (re-enable the endpoint) and retry. |
payload_too_large | 413 | More than 500 events in one request, or a body over 1 MB. | Split the batch. |
validation_failed | 422 | The body is well-formed JSON but fails validation; errors[] lists each field. | Fix the fields listed in errors[]. |
rate_limited | 429 | Too many requests for this key (600 per minute by default). | Wait for Retry-After seconds, then retry. Watch X-RateLimit-Remaining. |
internal_error | 5xx | Something failed on our side. | Retry with backoff. If it persists, email support with the request_id. |