Skip to main content
On success, every export endpoint returns the standard envelope { code, message, body, errors }code mirrors the HTTP status, body carries the payload, and errors is an empty array. Error responses use a different, smaller envelope. They are returned as:
{
  "success": false,
  "message": "<human-readable reason>",
  "requestId": "<correlation id>"
}
Include the requestId whenever you contact support — it lets us locate the exact request in our logs.
The export endpoints do not perform dedicated input validation that returns 400. A malformed cursor is not rejected with a 400; it surfaces as a 500 (see Invalid cursor below). Malformed since/until values are likewise not separately validated. Treat the cursor as opaque and send ISO-8601 timestamps to avoid these cases.

Status code overview

CodeWhenRetry?
200Page returned (may be empty rows)n/a
401Authorization header missing or not Bearer …No — attach a token
401JWT invalid or expiredYes, after re-auth
401Lender record not found or inactive in the main DBNo — contact support
403lenderPublicId in the URL does not match lenderId in the JWTNo
404Unknown section code (e.g. /S9/D01)No
404Unknown dataset code (e.g. /S1/D99)No
404Dataset listed in the catalog but available: false (reserved)No — revisit later
500Lender database_name missing on the LenderAccount recordNo — contact support
500Invalid / corrupted cursorNo — fix client
500Other internal server errorYes, after backoff
504Gateway timeout — query exceeded the proxy limit (large high-volume via datasets)Yes — narrow with a time window, lower limit, then retry

Error reference

Trigger: The Authorization header is absent or does not start with Bearer .
{
  "success": false,
  "message": "Access denied. No token provided.",
  "requestId": "req_8f2a1c9e4b7d"
}
Recovery: Attach a valid Bearer token obtained from the Lender Login endpoint.
Trigger: The token fails signature verification or has expired. Both cases are reported identically.
{
  "success": false,
  "message": "Access denied. Invalid token.",
  "requestId": "req_3d5b8a0f1e62"
}
Recovery: Obtain a fresh token using the Refresh Token endpoint, or re-authenticate via Lender Login.
Trigger: The token is well-formed and matches the URL, but the lender record cannot be found in the main database or is not active.
{
  "success": false,
  "message": "Lender not found or inactive",
  "requestId": "req_a1c4e7d09b32"
}
Recovery: This usually indicates an account state issue rather than a client bug. Capture the requestId and contact support.
Trigger: The lenderPublicId in the URL path does not equal the lenderId encoded in the JWT. This strict check (requireLenderMatch) runs on every export request.
{
  "success": false,
  "message": "Lender ID mismatch",
  "requestId": "req_6b2f9d3a7c14"
}
Recovery: Re-authenticate with the correct lender and use the matching lenderPublicId in the path.
Trigger: The sectionCode in the path is not one of S1S5 (e.g. /exports/S9/D01).
{
  "success": false,
  "message": "Unknown section",
  "requestId": "req_c8e1a5f2b903"
}
Recovery: Call the catalog endpoint to discover valid section codes.
Trigger: The section exists but the datasetCode does not exist within it (e.g. /exports/S1/D99).
{
  "success": false,
  "message": "Unknown dataset",
  "requestId": "req_47d9b0c3e1a8"
}
Recovery: Call the catalog endpoint to discover valid dataset codes for each section.
Trigger: The dataset exists in the catalog but ships with available: false (reserved — currently D04, D06, D10, D11, D13, D24). The message names the dataset code.
{
  "success": false,
  "message": "Dataset D04 is listed in the catalog but not available for export at this time.",
  "requestId": "req_92a4c7e0d3b1"
}
Recovery: The dataset has not been activated yet. Check the available flag in the catalog and contact support to schedule activation.
Trigger: The lender record was found but has no database_name, so the tenant connection cannot be resolved.
{
  "success": false,
  "message": "Lender database not configured",
  "requestId": "req_0e3b8d6a2f59"
}
Recovery: This is a server-side configuration issue. Capture the requestId and contact support.
Trigger: The cursor query value is malformed or corrupted and cannot be decoded. Because cursor decoding is not surfaced as a validation error, it is returned as a generic internal error rather than a 400.
{
  "success": false,
  "message": "Internal server error",
  "requestId": "req_5a9c2e7b4d80"
}
Recovery: Never modify a cursor. Drop the bad cursor and restart from the last known-good nextCursor, or from the beginning of the dataset.
Trigger: Any other unexpected server-side failure.
{
  "success": false,
  "message": "Internal server error",
  "requestId": "req_e1b7d4a9c062"
}
Recovery: Retry after a short backoff. If it persists, capture the request URL, the response body, and the time, then contact support.
Trigger: The query took longer than the API gateway’s timeout to return. This happens on the highest-volume via (TIER 2) datasets — most notably D23 Manual Communication Logs (tens of millions of rows) — when a page is requested without a time window, so the scan/sort spans the entire collection.Because the timeout is raised by the gateway (not the application), the response is not the standard JSON error envelope — it’s a plain gateway 504 with no requestId.Recovery:
  • Always bound large via pulls with a since (and optionally until) window — pull in slices (e.g. month-by-month) rather than one unbounded scan.
  • Lower the limit (e.g. 200500) so each page does less work.
  • Retry the same windowed request after a short backoff.
  • ?includeTotal=true on a via dataset also requires a time window (it returns totalNote: "window_required" otherwise); add since/until before requesting a total.
If a windowed, small-limit request still times out, capture the full request URL and time, then contact support.

Common debugging hints

  • Unexpected 401? Your token most likely expired. Refresh it via /admin/auth/{lender}/refresh-token and retry.
  • 403? The JWT was issued for a different lender than the one in the URL path. Re-authenticate with the correct lender subdomain.
  • 404 on a dataset that appears in the catalog? Check its available flag. If false, the dataset has not been activated for your tenant yet — contact support to schedule it.
  • Unexpected 500? Capture the request URL, the response body (including requestId), and the time, then contact support.
  • 504 on a large dataset (e.g. D23)? The query is scanning too much. Add a since/until window and pull in smaller time slices, and consider lowering limit. See the 504 — Gateway timeout guidance above.