Errors
The HTTP status tells you what kind of failure it is; the code tells you which one. Branch on the code, never on the message text, which can change.
Error format
Endpoint errors carry an error object with a stable code and a human-readable message:
404 Not Found
{
"error": {
"code": "RUN_NOT_FOUND",
"message": "Workflow run wr_abc123xyz789 not found"
}
}A few errors carry a plain string instead, with no code: authentication failures, the per-key rate limit, an oversized body, malformed JSON on POST /workflow-runs/, and unexpected 500s.
403 Forbidden
{
"error": "Invalid or inactive API key."
}Read both forms the same way:
Python
error = response.json().get("error")
if isinstance(error, dict):
code, message = error["code"], error["message"]
else:
code, message = None, error # branch on response.status_codeEvery response carries an X-Request-ID header (req_...). Quote it when you contact support; the same ID appears in your API logs.
HTTP status codes
| Status | Meaning |
|---|---|
| 400 | The request is invalid: a missing or malformed parameter, or a document that cannot be read. Fix it before sending again. |
| 401 | No X-API-Key header. |
| 402 | The organization cannot be billed for this document: no credits left, or no active plan. |
| 403 | The key is invalid, inactive or expired, the caller's IP is not on the key's allow-list, or the organization may not use this endpoint. |
| 404 | The resource does not exist in your organization. |
| 405 | The method is not supported on this path. The Allow header lists the ones that are. |
| 409 | The resource is not in a state that allows the call, or a limit on the number of resources is reached. |
| 413 | The request body is over 100 MB. |
| 415 | A run or part PDF was requested for a source document that is not a PDF. |
| 429 | Over the per-key request rate (wait for Retry-After), or over the sandbox credit allowance. See limits. |
| 500 | Something failed on our side. Retry with backoff if the call is safe to repeat. |
Error codes
Every code, the status it comes with, and the endpoints that return it.
| HTTP | Code | Meaning | Returned by |
|---|---|---|---|
| 400 | APPLICATIONS_DISABLED | Dossiers are not enabled for your organization. | Create a workflow run, List dossiers, Create or update a dossier, List the organization's dossier configurations, One configuration's full contract |
| 400 | CONFLICTING_INPUT | Both document_b64 and document_pages_b64 were sent. | Create a workflow run |
| 400 | FIELDS_WITHOUT_PARTY | A role carries several participants and one of them has no party_ref. | Create or update a dossier |
| 400 | INVALID_CASE_ID | case_id is empty or longer than 255 characters. | Create a workflow run, Create or update a dossier |
| 400 | INVALID_CLONE_WORKFLOWS | clone_workflows is not a boolean. | Create a child organization |
| 400 | INVALID_DOCUMENT | The content is not valid base64, or not a PDF, office document or image Holofin reads. | Create a workflow run |
| 400 | INVALID_EVENTS | events is not a list, or names an event that cannot be subscribed to. | Register a webhook endpoint, Update a webhook endpoint |
| 400 | INVALID_EXTERNAL_REF | external_ref is not a string, or too long. | Create a child organization |
| 400 | INVALID_FILTER | A filter has a value outside the allowed set; the message lists them. | List workflow runs, List dossiers, Read a dossier's change trail |
| 400 | INVALID_INPUT_FIELD | A value in case_fields has the wrong shape for its field. | Create or update a dossier |
| 400 | INVALID_JSON | The body is not a JSON object. | Create or update a dossier, Register a webhook endpoint, Update a webhook endpoint, Create a child organization, Update a child organization |
| 400 | INVALID_NAME | name is missing, not a string, or too long. | Register a webhook endpoint, Update a webhook endpoint, Create a child organization, Update a child organization |
| 400 | INVALID_PARTY_REF | A participant reference is not a distinct, non-empty string of at most 255 characters. | Create a workflow run, Create or update a dossier |
| 400 | INVALID_PARTY_TYPE | party_type is not one of PM, PP, PPNS or BE. | Create or update a dossier |
| 400 | INVALID_STATUS | status is not one of the allowed values. | Update a webhook endpoint, Update a child organization |
| 400 | INVALID_URL | url is malformed or resolves to a private address. | Register a webhook endpoint, Update a webhook endpoint |
| 400 | INVALID_WEBHOOK_URL | webhook_url is malformed, not http(s), or resolves to a private address. | Create a workflow run |
| 400 | MISSING_CONFIG_ID | A new dossier needs a config_id. | Create or update a dossier |
| 400 | MISSING_DOCUMENT | Neither document_b64 nor document_pages_b64 was sent. | Create a workflow run |
| 400 | MISSING_URL | url is missing. | Register a webhook endpoint, Update a webhook endpoint |
| 400 | MISSING_WORKFLOW_ID | workflow_id is missing. | Create a workflow run |
| 400 | PAGE_LIMIT_EXCEEDED | The document has more than 200 pages. | Create a workflow run |
| 400 | PARTY_WITHOUT_CASE | party_refs was sent without case_id. | Create a workflow run |
| 400 | UNKNOWN_CASE_ID | case_id names no dossier. Create it with POST /cases/ first. | Create a workflow run |
| 400 | UNKNOWN_CONFIG | config_id names no case configuration. | Create or update a dossier |
| 400 | UNKNOWN_INPUT_FIELD | A key in case_fields that the configuration does not declare; the message lists them. | Create or update a dossier |
| 400 | UNKNOWN_PARAMETER | An unsupported query parameter; the message lists the supported ones. | List dossiers, Read a dossier's change trail, List the organization's dossier configurations, One configuration's full contract |
| 400 | UNKNOWN_PARTY_REF | A reference names no participant of the dossier; the message lists them. | Create a workflow run |
| 400 | UNKNOWN_ROLE | A participant role the configuration does not define; the message lists the allowed ones. | Create or update a dossier |
| 400 | UNSUPPORTED_FIELD | The body carries a key that belongs to another endpoint, such as case_fields on a run. | Create a workflow run, Create or update a dossier |
| 402 | INSUFFICIENT_CREDITS | No credits remaining. | Create a workflow run |
| 402 | NO_ACTIVE_SUBSCRIPTION | The organization has no active plan. | Create a workflow run |
| 402 | PLAN_NOT_PAID | The plan is not active yet. | Create a workflow run |
| 403 | NOT_ALLOWED | The key's organization may not use this endpoint. | List child organizations, Create a child organization, Get a child organization, Update a child organization |
| 404 | DOCUMENT_FILE_UNAVAILABLE | The document file is no longer stored, for example after its retention period. | Download the run's document, Download a document part |
| 404 | NOT_FOUND | No resource with this ID in your organization. | Read a dossier's status, requirements and gaps, Read a dossier's change trail, One configuration's full contract, Get a webhook endpoint, Update a webhook endpoint, Delete a webhook endpoint, Get a child organization, Update a child organization |
| 404 | PART_NOT_FOUND | No part with this key on the run. | Download a document part |
| 404 | RUN_NOT_FOUND | No run with this ID in your organization. | Get a workflow run, Download the run's document, Download a document part, List a run's node executions, Cancel a workflow run |
| 404 | WORKFLOW_NOT_FOUND | No workflow with this ID in your organization. | Create a workflow run |
| 405 | METHOD_NOT_ALLOWED | The method is not supported on this path; see the Allow header. | Create or update a dossier |
| 409 | CANNOT_CANCEL | The run is already completed, failed or cancelled. Treat it as success. | Cancel a workflow run |
| 409 | CONFIG_CONFLICT | The dossier exists under another configuration, which cannot change. Open a new dossier. | Create or update a dossier |
| 409 | LIMIT_REACHED | The maximum number of child organizations is reached. | Create a child organization |
| 409 | RUN_NOT_TERMINAL | A part PDF was requested before extraction finished. | Download a document part |
| 409 | WEBHOOK_LIMIT_REACHED | The organization already has 5 endpoints. | Register a webhook endpoint |
| 415 | UNSUPPORTED_DOCUMENT_TYPE | A PDF was requested for a source document that is not a PDF, such as a spreadsheet. | Download the run's document, Download a document part |
| 429 | SANDBOX_LIMIT_EXCEEDED | The document needs more sandbox credits than remain. Backing off does not help. | Create a workflow run |
| 500 | INTERNAL_ERROR | An unexpected error. | Any endpoint |
| 500 | PDF_RESOLUTION_FAILED | The run or part PDF could not be produced. | Download the run's document, Download a document part |