Response format
Every successful response from leadx-api goes through one helper, so the envelope is the same everywhere.
Single resource
GET /lead/:id, POST /contact, PUT /tag/:id — anything returning one document:
{
"ok": true,
"success": true,
"message": "Lead created successfully.",
"data": { "_id": "665f...", "stage": "New" }
}
| Field | Type | Meaning |
|---|---|---|
ok | boolean | Always true on success. |
success | boolean | Always true on success. Duplicate of ok; both are always sent. |
message | string | null | Human-readable result. null when the endpoint declares no message. |
data | object | null | The resource. |
The HTTP status comes from the named response message — commonly 200, or 201 for creates.
Collection
Every list endpoint returns the array in data alongside pagination metadata at the top level:
{
"ok": true,
"success": true,
"message": null,
"data": [ { "_id": "665f..." }, { "_id": "6660..." } ],
"totalCount": 1284,
"n": 25,
"p": 1,
"nextCursor": null,
"cursorPagination": false,
"sortBy": "createdAt",
"sortOrder": "desc"
}
| Field | Type | Meaning |
|---|---|---|
data | array | The page of documents. |
totalCount | number | Total matching the filter, ignoring pagination. |
p | number | null | Page echoed back. null when unpaginated. |
n | number | null | Page size echoed back. |
nextCursor | string | null | Opaque cursor for the next page, when cursor pagination is on. |
cursorPagination | boolean | Whether this response used cursor mode. |
sortBy / sortOrder | string | Sort actually applied. |
:::tip Read totalCount, not data.length
data.length is the size of the page. totalCount is the size of the result set — use it to decide whether to keep paging.
:::
Errors
Errors do not use the ok/success: true envelope:
{
"status": "fail",
"success": false,
"message": "Lead not found.",
"warning": ""
}
| Field | Type | Meaning |
|---|---|---|
status | "fail" | "error" | "fail" for 4xx, "error" for 5xx. |
success | boolean | Always false. |
message | string | What went wrong. |
warning | string | Usually empty; occasionally carries a non-fatal note. |
stack | string | Development only — never present in production. |
Detecting success reliably
Branch on the HTTP status code, not on the body. Both shapes carry success, so body.success === true also works, but the status is what your HTTP client already gives you:
const res = await fetch(url, { headers: { apikey } });
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.message}`);
return body.data;
A note on data for lists
The single-resource and collection shapes both use data, but a collection sets it to an array and adds sibling metadata keys. Code that assumes data is an object will break on list endpoints, and vice versa. The rule is simple: GET on a collection path returns an array; everything else returns an object.