Skip to main content

Error shape

Every error uses a standard HTTP status code and a consistent JSON envelope:
{ "error": { "code": "report_not_ready", "message": "Report is not available yet for this review." } }
Branch your integration on the stable error.code (a closed, documented set), not on the HTTP status alone (several distinct conditions can share a status) and never on the human-readable error.message (it is advisory and may change).

Error codes

codeHTTP statusMeaning
missing_api_key401No API key was sent. Add Authorization: Bearer <key>.
invalid_api_key401The API key is invalid, revoked, or expired.
org_unbound403The key is valid but not bound to an organization.
auth_unavailable503Authentication is temporarily unavailable; retry shortly.
review_not_found404The review does not exist or belongs to another organization.
report_not_ready404The review exists but has not finished; keep polling.
review_failed422The review failed (terminal); no report will exist.
document_required400No usable document was supplied (or a file was empty).
document_unsupported400A document, archive, or archive member has an unsupported type.
document_too_large413A single document exceeds the per-file size limit.
too_many_documents422More documents than the per-review limit.
documents_too_large422The documents exceed the aggregate per-review size limit.
duplicate_reference_id409A review with the same reference_id already exists.
all_documents_duplicate409Every submitted document duplicates one already on the review.
invalid_request400 / 422The request body or a field is malformed (bad JSON, failed validation, unfetchable source URL).
rate_limited429Rate limit exceeded; retry with exponential backoff.
webhook_endpoint_not_found404The webhook endpoint does not exist under your organization.
internal_error500An unexpected server error; retry later.

Review lifecycle & the failure contract

A review’s status moves through queuedprocessingcompleted or failed. Both completed and failed are terminal; stop polling once you see either. GET /reviews/{review_id}/report uses the status code to tell you what to do, so a failure is never mistaken for “still processing”:
Report statusMeaningWhat to do
200Review completed; report body follows.Use the report.
404Review not found, or not finished yet (queued/processing).Keep polling.
422Review failed (terminal). No report will ever exist.Stop polling; inspect the review and resubmit if appropriate.
Always confirm terminal state via GET /reviews/{review_id} (status is completed or failed) rather than inferring it from the report endpoint alone.

Rate limits

Requests are rate-limited per organization (the default ceiling is 60 requests/minute, enforced across our fleet). Exceeding it returns 429 Too Many Requests.

Response headers

Every rate-limited response carries the standard rate-limit headers so you can observe your remaining budget without waiting for a 429:
HeaderMeaning
X-RateLimit-LimitYour ceiling for the current window.
X-RateLimit-RemainingRequests left in the current window.
X-RateLimit-ResetUnix timestamp (seconds) when the window resets.
Retry-AfterSeconds to wait before retrying. Sent on a 429.
On a 429, honor Retry-After if present; otherwise retry with exponential backoff (e.g. 1s, 2s, 4s, … with jitter) rather than tight-looping. Watching X-RateLimit-Remaining lets you pace requests and avoid a 429 entirely. Webhooks let you avoid polling altogether and stay well under any limit. If your integration needs a higher ceiling, contact your Flightline representative.

Idempotency

Set reference_id to your own external identifier for the loan package. Creating a second review with a reference_id that already exists returns 409, so retries won’t create duplicate reviews.