Error Code Reference
Every non-2xx response from the Ocriva API returns a consistent JSON error object. This page lists all status codes, their causes, and how to resolve them.
Error Response Format
All API errors share the same JSON envelope:
{
"statusCode": 400,
"message": "Validation failed: templateId must be a non-empty string",
"error": "Bad Request"
}| Field | Type | Description |
|---|---|---|
statusCode | number | HTTP status code (mirrors the response status) |
message | string | Human-readable description of what went wrong |
error | string | Short error classification matching the HTTP reason phrase |
Some endpoints that return field-level validation errors extend message into an array:
{
"statusCode": 400,
"message": [
"templateId must be a non-empty string",
"projectId must be a UUID"
],
"error": "Bad Request"
}Quick Reference
| Status Code | Name | One-liner |
|---|---|---|
400 | Bad Request | Missing field, wrong type, or failed validation |
401 | Unauthorized | API key absent, invalid, or expired |
403 | Forbidden | Valid key but insufficient permissions or IP not allowed |
404 | Not Found | Resource does not exist or belongs to a different project |
409 | Conflict | Duplicate resource or concurrent modification detected |
413 | Payload Too Large | File exceeds the size limit for your plan |
429 | Too Many Requests | Rate limit exceeded; back off and retry |
500 | Internal Server Error | Unexpected server-side failure |
400 Bad Request
The request was malformed — a required field is missing, a value has the wrong type, or a parameter failed a format check.
Common triggers:
- Missing
templateIdorprojectIdin an upload request - Sending
pageRangeas a string instead of an object - Providing an
organizationIdthat is not a valid ObjectId
Example — missing required field:
POST /api/upload
{
"projectId": "proj_abc123"
# templateId omitted
}Response:
{
"statusCode": 400,
"message": "Validation failed: templateId must be a non-empty string",
"error": "Bad Request"
}Fix: Check the request body against the API Reference. All required parameters must be present and correctly typed. Use the message field — it names the exact field that failed.
401 Unauthorized
The request could not be authenticated. This means the API key is missing, malformed, revoked, or does not have access to the resource being requested.
Common triggers:
X-API-Keyheader is absent- The token has been deleted or regenerated since the request was built
- Using an organization-level token against a project that belongs to a different organization
Example:
GET /api/processing-history
# X-API-Key header missingResponse:
{
"statusCode": 401,
"message": "Invalid or missing API key",
"error": "Unauthorized"
}Fix: Ensure every request includes the X-API-Key header with a valid token. Tokens are created under Organization → API Tokens or Project → API Tokens and are shown only once at creation time. If the token is lost, create a new one.
NOTE
For SDK users, a 401 maps to AuthenticationError. See SDK Error Handling for typed catching.
403 Forbidden
The API key is valid but does not have permission to perform the requested action.
Common triggers:
- Using a project-scoped token to access a different project's resources
- Your organization's source IP is not in the webhook endpoint's allowlist
- Attempting an admin action (for example, deleting an organization) with a standard member token
Example:
DELETE /api/organizations/org_xyz
# Token belongs to a member role, not an ownerResponse:
{
"statusCode": 403,
"message": "You do not have permission to delete this organization",
"error": "Forbidden"
}Fix: Use a token that has the required scope. For organization-level operations use an organization token from an owner account. For project isolation, ensure the token's project matches the resource you are querying.
404 Not Found
The requested resource does not exist, or it exists but belongs to a different project or organization than the one the token is scoped to.
Common triggers:
- Typo in the record ID (e.g.,
hist_prefix for processing history records) - Querying a resource with a project-scoped token when the resource belongs to a different project
- The resource was deleted before the request arrived
Example:
GET /api/processing-history/hist_does_not_exist?projectId=proj_abc123Response:
{
"statusCode": 404,
"message": "Processing history record not found",
"error": "Not Found"
}Fix: Verify the ID against Processing History in the dashboard. If using the API, confirm the projectId query parameter matches the project the record belongs to.
409 Conflict
The request conflicts with existing data or with a concurrent operation.
Common triggers:
- Creating a template with a name that already exists in the project
- Two simultaneous requests attempting to deduct credits from the same balance (optimistic locking violation)
Example — duplicate template name:
{
"statusCode": 409,
"message": "A template named 'Invoice Extractor' already exists in this project",
"error": "Conflict"
}Example — concurrent credit update:
{
"statusCode": 409,
"message": "Credit was modified by another process. Please retry.",
"error": "Conflict"
}Fix: For duplicate name conflicts, choose a unique name or update the existing resource. For credit concurrency conflicts, the system retries automatically up to three times — if the error surfaces persistently, reduce concurrent processing requests or contact support.
413 Payload Too Large
The uploaded file exceeds the size limit enforced for your organization's subscription plan.
Response:
{
"statusCode": 413,
"message": "File size exceeds the maximum allowed limit of 20 MB",
"error": "Payload Too Large"
}Fix: Compress or split the file before uploading. Current per-file limits are visible at Organization → Limits. As a general guideline, files up to 20 MB are supported on standard plans. Upgrading your subscription increases the limit.
429 Too Many Requests
Your API key has exceeded the rate limit for the current time window.
Response:
{
"statusCode": 429,
"message": "Rate limit exceeded. Retry after 32 seconds.",
"error": "Too Many Requests"
}The response includes a Retry-After header with the number of seconds to wait:
Retry-After: 32Fix: Wait for the window to reset before sending additional requests. The SDK handles this automatically — it reads the Retry-After header and pauses before retrying (up to maxRetries times). For bulk workloads, use the Batch Processing endpoint to group many files into a single API call rather than uploading them one by one.
See SDK Error Handling — Rate Limiting for retry configuration options.
500 Internal Server Error
An unexpected error occurred on the server. This is not caused by your request.
Response:
{
"statusCode": 500,
"message": "An unexpected error occurred. Please try again later.",
"error": "Internal Server Error"
}When to retry: Transient 500 errors (for example, a momentary database hiccup) often resolve on their own. The SDK automatically retries 5xx responses with exponential backoff.
When to contact support: If the error recurs across multiple retries or persists over several minutes, open a support ticket at Support → Tickets. Include:
- The
requestIdoreventIdfrom the response headers (see Debugging Tips below) - The endpoint and request body (with secrets redacted)
- The timestamp of the failing request
SDK Error Mapping
The @ocriva/sdk maps HTTP status codes to typed error classes so you can use instanceof checks instead of comparing raw status numbers:
| Status Code | SDK Error Class | Notes |
|---|---|---|
401 | AuthenticationError | Extends ApiError |
404 | NotFoundError | Extends ApiError |
429 | RateLimitError | Has retryAfter property; auto-retried |
400, 403, 409, 413, 500 | ApiError | Check error.statusCode for the specific code |
| Network / timeout | OcrivaError | Base class; not an HTTP error |
See SDK Error Handling for the full error hierarchy, property reference, and code examples.
Webhook Error Codes
Webhook delivery and signature verification have their own failure modes that appear in the Webhooks → Delivery Logs section of the dashboard.
Delivery Failures
| Failure | Description |
|---|---|
DELIVERY_TIMEOUT | Your endpoint did not respond within 10 seconds |
DELIVERY_HTTP_ERROR | Your endpoint returned a non-2xx status code |
DELIVERY_CONNECTION_REFUSED | The endpoint URL was unreachable |
MAX_RETRIES_EXCEEDED | All automatic retry attempts exhausted (up to 5 retries with backoff) |
Ocriva retries failed deliveries automatically. Each retry is logged with its own status. If all retries fail, the event is marked as permanently failed and you can manually trigger a replay from the delivery log.
Signature Verification Failures
If your endpoint rejects the X-OCR-Signature header, verify:
- You are using the signing secret shown at endpoint creation time (it is only displayed once).
- You are computing the HMAC-SHA256 over the raw request body bytes — not a parsed/re-serialized JSON string.
- The
Content-Typeheader on incoming requests isapplication/json.
See Webhooks Guide for the full verification code sample.
Tips for Debugging
Use requestId and eventId
Every API response includes a requestId header. Every webhook payload includes an eventId field. Include these identifiers when opening a support ticket — they allow the Ocriva team to trace the exact request through server logs.
# Extract requestId from a curl response
curl -si https://api.ocriva.com/api/processing-history \
-H "X-API-Key: $OCRIVA_API_KEY" \
| grep -i x-request-idCheck Processing History
The Processing History page logs the outcome of every document — including failures. Click any record to expand it and read the exact error message returned by the AI provider or the internal processing pipeline. Use the ID filter to jump directly to a specific record by its hist_ ID.
Reproduce with a Minimal Request
Strip your request down to the minimum required fields and add fields back one at a time. This isolates which parameter is triggering a 400 validation error.
Consult Related Guides
- FAQ & Troubleshooting — common error scenarios with step-by-step solutions
- SDK Error Handling — typed errors, automatic retries, and rate limit backoff
- Webhooks Guide — delivery retries and signature verification
