Conventions & Errors

Pagination, tenancy headers and error shapes.

Every endpoint follows the same conventions, which keeps client code small and predictable.

Base URL and tenancy

Base URL
https://api.introzen.com/api/

Workspace-scoped endpoints require the X-Tenant-ID header. The value only selects a workspace — membership is verified server-side before any query runs.

Header
-H "X-Tenant-ID: 42"

Pagination

List endpoints use DRF limit/offset pagination with a default page size of 20.

FieldTypeDescription
limitintegerMaximum records to return.
offsetintegerRecords to skip.
Paginated response
{
  "count": 137,
  "next": "https://api.introzen.com/api/pipeline/pipelines/?limit=20&offset=20",
  "previous": null,
  "results": []
}

Timestamps

All timestamps are ISO-8601 in UTC, with the timezone in USE_TZ enabled. Convert to local time for display.

Example
{ "started_at": "2026-10-04T09:12:44.512Z" }

Error envelope

Every failure - validation, authentication, permission, throttling, a missing record, or an unexpected server exception - is rendered into one stable envelope. Branch on error.code; never parse the prose in error.message.

Canonical error envelope
{
  "error": {
    "code": "validation_error",
    "message": "Enter a valid email address.",
    "fields": { "email": ["Enter a valid email address."] },
    "request_id": "b1f0c4d5e6a7483192c3d4e5f6071829"
  }
}

Envelope fields

FieldTypeDescription
codestringStable machine-readable identifier. Always present. This is the only value you should branch on.
messagestringHuman copy, safe to show verbatim in a toast or an inline hint.
fieldsobjectField-keyed arrays keyed by serializer field name. Present only when the failure is field-scoped, so forms can highlight the offending input.
request_idstringCorrelates this response with the server log line. See Request correlation.
retry_afterintegerSeconds to wait before retrying. Present on 429 and 503 responses only.

Error codes

Codes are grouped by intent. Request codes describe a failure in the call itself; domain codes describe a business rule the call violated and each one has a known recovery path.

Request codes

FieldTypeDescription
validation_error400A serializer rejected the payload. Inspect fields.
bad_request400The request was malformed in a way no field describes.
parse_error400The body could not be parsed as JSON or multipart.
not_authenticated401No usable session. Refresh once, then sign in.
authentication_failed401Credentials were present but rejected.
permission_denied403Authenticated, but not permitted for this resource.
not_found404No such record, or no dataset has been produced yet.
method_not_allowed405The route exists but not for this HTTP method.
conflict409The request collided with the current state.
payment_required402The active plan does not entitle this capability.
throttled429Rate limited. Honour retry_after.
internal_error500Unexpected server fault. Quote request_id to support.
service_unavailable503A dependency (broker, cache or database) is down. Honour retry_after.
database_unavailable503The database is unreachable or unhealthy. Transient: retry after retry_after seconds.
dependency_unavailable503A transport-level dependency failed (cache, broker, object store, upstream HTTP). Retry after retry_after seconds.

Domain codes

FieldTypeDescription
invalid_workspace400X-Tenant-ID was missing or not a number.
workspace_unresolved400No workspace could be resolved for the session.
workspace_access_denied403The session is not a member of that workspace.
workspace_not_found404The workspace does not exist or is not visible to you.
member_not_found404No such workspace member.
member_already_owner400The requested member already owns the workspace.
plan_not_found404The plan identifier does not exist.
paid_plan_provisioned409A paid plan is already active; change it instead of re-subscribing.
unsupported_fields400Read-only fields were sent on a write.
pipeline_already_running409A run for this pipeline is already in flight.
execution_not_cancellable409The run already reached a terminal state.
no_successful_execution404Charts and reports need at least one successful run.
dataset_unavailable410The stored result was pruned. Re-run the pipeline.
invalid_pagination400limit or offset was not a positive integer.
file_required400A multipart upload arrived with no file part.
unsupported_file_type400Only .csv, .xlsx and .xls are accepted.
file_unreadable400The file was corrupt, encrypted or password protected.
account_not_found404Staff-only: no such account.
self_deactivation400Staff-only: you cannot deactivate your own account.
refresh_token_missing401The refresh cookie was absent.
refresh_token_invalid401The refresh token was expired, reused or revoked.
invalid_reset_token400The password-reset link is invalid or has expired.

Request correlation

Every response carries an X-Request-ID header, and the same value is echoed as error.request_id. A sane X-Request-ID you send is reused, so a correlation id can span the browser, the API and your own gateway.

Response headers
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
X-Request-ID: b1f0c4d5e6a7483192c3d4e5f6071829

Status codes

FieldTypeDescription
200stringSuccess.
201stringCreated.
400stringValidation failed. Inspect the body.
401stringMissing or expired session. Refresh and retry once.
403stringAuthenticated but not permitted for this workspace.
404stringNot found, or no dataset exists yet.
429stringRate limited. Back off and retry.
503stringUpstream dependency (database or broker) unavailable.

Last reviewed October 2026.