Skip to main content

Errors

The Silent Witness API uses conventional HTTP response codes. Codes in the 2xx range indicate success, 4xx codes indicate client errors, and 5xx codes indicate server errors.

Error Response Format

Every error returns a consistent JSON envelope:

{
"success": false,
"error": "Human-readable error message",
"error_code": "specific_error_code",
"error_type": "invalid_request_error",
"error_param": "field_name",
"request_id": "req_abc123"
}
FieldTypeDescription
successbooleanAlways false on error responses
errorstringHuman-readable message safe to show end users. Wording may change — do not pattern-match on it
error_codestringStable machine-readable identifier. Switch on this field in your code
error_typestringCoarse category for generic handling (see below)
error_paramstringPresent when the error relates to a specific input field (e.g., "case_id", "occupants")
request_idstringUnique per-request ID (format: req_<hex>). Include when contacting support

Error Types

TypeDescription
invalid_request_error4xx — the request was invalid, caller can fix and retry
authentication_error401 — bad or missing credentials
permission_error403 — authenticated but denied
rate_limit_error429 — too many requests
api_error5xx — server fault, retry with backoff

Client-supplied Request IDs

Send your own X-Request-ID header for tracing — the API will use it as-is and echo it back. If you don't send one, a req_<hex> value is generated automatically.

Error Code Catalog

File Upload

error_codeHTTPMeaning
case_id_missing400The case_id form field was not provided
file_missing400No file form field in the multipart upload
file_empty400The uploaded file is 0 bytes
file_too_large400File exceeds the 50MB limit
unsupported_file_type400Detected content type is not JPEG, PNG, GIF, WebP, or PDF. The message includes the detected MIME type
vehicle_index_not_allowed400vehicle_role was sent with file_category=tcr_document. TCR is case-level — remove vehicle_role

Cases

error_codeHTTPMeaning
case_not_found404Case does not exist or belongs to a different account
case_access_denied403Authenticated but not authorized for this case

Occupants

error_codeHTTPMeaning
occupant_field_required400An occupant is missing required fields. The error message lists which fields. error_param is "occupants"
occupants_missing422Report creation for accident_injury case but no occupants exist. Add occupants before creating the report

Reports

error_codeHTTPMeaning
unprocessable_entity422Missing crash data — no vehicles, photos, or EDR on the case
tcr_extraction_failed422Traffic Collision Report PDF could not be parsed. Re-upload a cleaner scan
tcr_extraction_timeout504TCR extraction exceeded its time budget. Retry after a short delay

Organizations

error_codeHTTPMeaning
org_field_required400A required field is missing. error_param identifies which one
org_invalid_body400The request body is not valid JSON
org_not_found404Organization does not exist
org_access_denied403Organization belongs to a different account

Generic

error_codeHTTPMeaning
internal_error500Unexpected server failure. Include request_id when reporting to support

When a handler has not been migrated to a specific code, error_code is derived from the HTTP status: bad_request, unauthorized, forbidden, not_found, conflict, unprocessable_entity, too_many_requests, gateway_timeout, internal_error.

Report Generation Errors

Report generation is asynchronous. Pre-flight validation errors (422) are returned immediately when calling POST /api/reports. Runtime errors appear when polling the report status:

ScenarioResponseResolution
No crash data422 (immediate)Upload damage photos or EDR before creating a report
No occupants (accident_injury)422 (immediate)Add occupants with all required fields
TCR extraction failed422 (immediate)Re-upload a cleaner scan of the police report
Delta-V calculation failedstatus: "failed" (async)Upload clearer damage photos and retry
Report timeoutstatus: "failed" (async)Retry — usually transient

To retry after an async failure, create a new report on the same case. You don't need to re-upload files.

Troubleshooting

Authentication errors with a valid API key
  • Verify key starts with sk- and is 64 characters
  • Check environment variable is set (no extra spaces)
  • Test with a fresh key from the dashboard
File upload returns "unsupported file type"

The server detects file type from the file's bytes, not the Content-Type header. A .txt file renamed to photo.jpg is rejected because its bytes are plain text. The error message includes the detected MIME type.

Report creation returns 422
  • unprocessable_entity: Upload damage photos or EDR to the plaintiff vehicle
  • occupants_missing: Add at least one occupant with all 7 required fields
  • tcr_extraction_failed: The police report PDF is unreadable — re-upload
Intermittent 500 errors
  • These are usually transient — retry after a few seconds with backoff
  • Include the request_id when contacting support