Skip to content

Errors and pagination

Problem documents, machine-readable codes, and cursor pagination.

2 min read

Errors

Every error is an RFC 9457 problem document:

json
{
  "type": "https://docs.nexuscrm.com/api/problems/validation_failed",
  "title": "The request was invalid.",
  "status": 422,
  "detail": "The phone number is not a valid Indian mobile number.",
  "code": "validation_failed",
  "request_id": "01KYM97KCJK416C465Y2A8AN3N",
  "errors": { "phone": ["The phone number is not a valid Indian mobile number."] }
}

Branch on code, never on title or detail. The human-readable strings may be reworded at any time; the code is a contract.

StatusCodeMeaning
401unauthenticatedMissing, malformed or revoked token
403forbiddenAuthenticated, but the token lacks the ability
404not_foundNo such record — or it is outside your data scope
409conflictA duplicate, or a state that forbids the change
422validation_failedSee errors for per-field detail
429rate_limitedBack off; see Retry-After
503service_unavailableRetry with backoff
Note
A record that exists but sits outside your token's data scope returns 404, not 403. Confirming that a record exists but is off-limits is itself a disclosure.

Responses never contain a stack trace, a SQL fragment or an internal database id. Quote request_id to support and we can find the exact request in our logs.

Pagination

Cursor-based throughout. There are no page numbers.

http
GET /api/v1/leads?page[size]=50
json
{
  "data": [],
  "links": { "next": "/api/v1/leads?page[size]=50&page[after]=01H8XGJ..." },
  "meta": { "has_more": true }
}

Follow links.next until it is null:

js
let url = '/api/v1/leads?page[size]=100';

while (url) {
  const page = await get(url);
  process(page.data);
  url = page.links.next;
}

Why there is no page=2

OFFSET 40000 makes the database walk forty thousand rows in order to discard them, so deep pages get progressively slower until an export times out. A cursor is a WHERE on an indexed column — page 500 costs the same as page 1.

It is also stable. With offset pagination, a row inserted while you iterate shifts everything down by one and you read the same record twice. A cursor cannot do that, because it remembers a position in the data rather than a count.

Stuck on a response you did not expect? Send us the request_id from the error body and we can trace the exact call — contact support.

Errors and pagination — API reference — atomcrm.ai