Skip to main content

Errors

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

Error Response Format

All errors return a consistent JSON structure:

{
"success": false,
"error": "Human-readable error message"
}

For validation errors, additional details may be included:

{
"success": false,
"error": "Validation failed",
"details": {
"field": "case_id",
"message": "case_id is required"
}
}

HTTP Status Codes

Success Codes

CodeDescription
200Request succeeded
201Resource created successfully
204Request succeeded, no content returned

Client Error Codes

CodeDescription
400Bad Request - Invalid parameters or missing required fields
401Unauthorized - Invalid or missing API key
403Forbidden - Valid API key but insufficient permissions
404Not Found - Resource doesn't exist
409Conflict - Resource already exists or state conflict
422Unprocessable Entity - Validation error
429Too Many Requests - Rate limit exceeded

Server Error Codes

CodeDescription
500Internal Server Error - Something went wrong on our end
502Bad Gateway - Upstream service unavailable
503Service Unavailable - Temporary overload or maintenance
504Gateway Timeout - Upstream service timeout

Common Error Scenarios

Authentication Errors (401)

Missing API Key

{
"success": false,
"error": "API key is required"
}

Invalid API Key

{
"success": false,
"error": "Invalid API key"
}

Resolution: Verify your API key is correct and included in the X-API-Key header.

Validation Errors (400)

Missing Required Field

{
"success": false,
"error": "case_id is required"
}

Invalid Field Value

{
"success": false,
"error": "Invalid report type: invalid_type. Supported types: technical_report"
}

Resolution: Check the API documentation for required fields and valid values.

Not Found Errors (404)

Case Not Found

{
"success": false,
"error": "Case not found"
}

Report Not Found

{
"success": true,
"data": null
}

Note: Some endpoints return null data instead of 404 (Stripe-style behavior).

Resolution: Verify the resource ID is correct and you have access to it.

Permission Errors (403)

Access Denied

{
"success": false,
"error": "Access denied to this resource"
}

Resolution: Ensure your API key has access to the organization that owns the resource.

Rate Limit Errors (429)

Rate Limit Exceeded

{
"success": false,
"error": "Rate limit exceeded. Please retry after 60 seconds."
}

Resolution: Implement exponential backoff and respect the Retry-After header.

Report Prerequisite Errors (422)

Missing Crash Data

{
"success": false,
"error": "Unable to generate report: no crash analysis data available. No vehicles found on this case. Please add at least one vehicle with either an EDR report (PDF) or damage photos."
}

Resolution: Upload vehicle damage photos or an EDR report (PDF) to the plaintiff vehicle before creating a report. See the Create Report prerequisites.

File Upload Errors (400)

File Too Large

{
"success": false,
"error": "File size exceeds maximum limit of 50MB"
}

Empty File

{
"success": false,
"error": "Empty files are not allowed"
}

Resolution: Ensure files are under 50MB and not empty.

Error Handling Best Practices

1. Check Response Status

const response = await fetch('/api/cases', {
method: 'POST',
headers: { 'X-API-Key': apiKey },
body: JSON.stringify(data)
});

if (!response.ok) {
const error = await response.json();
console.error('API Error:', error.error);
// Handle specific error types
}

2. Implement Retry Logic

For transient errors (5xx, 429), implement exponential backoff:

async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);

if (response.ok) return response;

// Don't retry client errors (except 429)
if (response.status < 500 && response.status !== 429) {
throw new Error(`Client error: ${response.status}`);
}

// Exponential backoff
const delay = Math.pow(2, i) * 1000;
await new Promise(r => setTimeout(r, delay));
}

throw new Error('Max retries exceeded');
}

3. Handle Rate Limits Gracefully

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
console.log(`Rate limited. Retrying after ${retryAfter} seconds`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
// Retry the request
}

4. Log Errors for Debugging

Include request details when logging errors:

console.error('API Error:', {
endpoint: '/api/cases',
method: 'POST',
status: response.status,
error: errorBody.error,
requestId: response.headers.get('X-Request-ID')
});

Report Generation Errors

Report generation can fail for various reasons:

ErrorCodeDescriptionResolution
no crash analysis data available422Pre-check: no vehicles, photos, or EDR data foundUpload vehicle damage photos or an EDR report before creating a report
Biomechanics failed500Occupant data incompleteEnsure occupants have age, gender, and position
Delta-V calculation failed500ML inference errorCheck image quality and try again
Report timeout500Generation took too longRetry the report creation

Check report status for error details:

curl "https://api.silentwitness.ai/api/reports/rpt_xyz789" \
-H "X-API-Key: $API_KEY"
{
"success": true,
"data": {
"id": "rpt_xyz789",
"status": "failed",
"progress": {
"message": "Delta-V calculation failed: insufficient image quality"
}
}
}