Error Handling
Complete guide to handling API errors, HTTP status codes, and implementing retry logic.
HTTP Status Codes
SudoMock API uses standard HTTP status codes to indicate success or failure. All error responses include a JSON body with details.
Request successful. Response contains requested data.
Resource created successfully. Used for API key generation.
Request successful, no content returned. Used for delete operations.
Invalid request format, missing required fields, or malformed JSON.
Invalid or missing API key (X-API-KEY header) or Bearer token.
Resource not found. Check mockup_uuid, smart_object_uuid, or key_id.
Request body validation failed. Check field types and constraints.
Too many requests. Wait and retry with exponential backoff.
Unexpected server error. Safe to retry with backoff.
Error Response Format
Standard error responses (400, 401, 404, 500) follow this structure:
1{2 "success": false,3 "detail": "Human-readable error message"4}Validation errors (422) have a different structure with detailed field information:
1{2 "detail": [3 {4 "loc": ["body", "field_name"],5 "msg": "Error message describing the issue",6 "type": "error_type"7 }8 ]9}Error Examples by Endpoint
Upload PSD - POST /api/v1/psd/upload
400 Bad Request
Missing or invalid PSD file URL.
1// Request with invalid URL2POST /api/v1/psd/upload3{4 "psd_file_url": "not-a-valid-url"5}67// Response8{9 "success": false,10 "detail": "Invalid PSD file URL format"11}401 Unauthorized
Missing or invalid X-API-KEY header.
1// Request without API key2POST /api/v1/psd/upload3X-API-KEY: (missing or invalid)45// Response6{7 "success": false,8 "detail": "Invalid or missing API key"9}422 Validation Error
Request body validation failed.
1// Request missing required field2POST /api/v1/psd/upload3{4 "psd_name": "My Mockup"5 // Missing: psd_file_url (required)6}78// Response9{10 "detail": [11 {12 "loc": ["body", "psd_file_url"],13 "msg": "field required",14 "type": "value_error.missing"15 }16 ]17}Render Mockup - POST /api/v1/renders
400 Bad Request
Invalid smart object configuration or asset URL.
1// Request with invalid asset URL2POST /api/v1/renders3{4 "mockup_uuid": "valid-uuid",5 "smart_objects": [{6 "uuid": "so-uuid",7 "asset": { "url": "not-accessible-url" }8 }]9}1011// Response12{13 "success": false,14 "detail": "Unable to fetch asset from provided URL"15}404 Mockup Not Found
The specified mockup_uuid doesn't exist or doesn't belong to your account.
1// Request with invalid mockup_uuid2POST /api/v1/renders3{4 "mockup_uuid": "non-existent-uuid",5 "smart_objects": [...]6}78// Response9{10 "success": false,11 "detail": "Mockup not found"12}422 Validation Error
Invalid field types or constraint violations.
1// Request with invalid field type2POST /api/v1/renders3{4 "mockup_uuid": "valid-uuid",5 "smart_objects": "should-be-array"6}78// Response9{10 "detail": [11 {12 "loc": ["body", "smart_objects"],13 "msg": "value is not a valid list",14 "type": "type_error.list"15 }16 ]17}1819// Request with invalid export options20POST /api/v1/renders21{22 "mockup_uuid": "valid-uuid",23 "smart_objects": [...],24 "export_options": {25 "image_size": 10000, // Max is 800026 "quality": 150 // Max is 10027 }28}2930// Response31{32 "detail": [33 {34 "loc": ["body", "export_options", "image_size"],35 "msg": "ensure this value is less than or equal to 8000",36 "type": "value_error.number.not_le"37 },38 {39 "loc": ["body", "export_options", "quality"],40 "msg": "ensure this value is less than or equal to 100",41 "type": "value_error.number.not_le"42 }43 ]44}API Keys - /api/v1/api-keys
401 Unauthorized
Invalid or missing Bearer token (requires Supabase JWT).
1// Request without Bearer token2POST /api/v1/api-keys3Authorization: (missing)45// Response6{7 "success": false,8 "detail": "Invalid or missing Bearer token"9}404 API Key Not Found
When deleting, updating, or regenerating a non-existent key.
1// Request to delete non-existent key2DELETE /api/v1/api-keys/non-existent-id34// Response5{6 "success": false,7 "detail": "API key not found"8}422 Validation Error
Invalid API key name or expiration days.
1// Request with invalid expiration2POST /api/v1/api-keys3{4 "name": "My Key",5 "expires_in_days": 5000 // Max is 36506}78// Response9{10 "detail": [11 {12 "loc": ["body", "expires_in_days"],13 "msg": "ensure this value is less than or equal to 3650",14 "type": "value_error.number.not_le"15 }16 ]17}500 Internal Server Error
Server errors are rare but can occur. They are safe to retry.
1// Response on server error2{3 "success": false,4 "detail": "An unexpected error occurred. Please try again."5}Report Persistent Errors
Retry Strategy
Implement exponential backoff for failed requests:
1async function renderWithRetry(payload, maxRetries = 3) {2 for (let attempt = 0; attempt < maxRetries; attempt++) {3 try {4 const response = await fetch('https://api.sudomock.com/api/v1/renders', {5 method: 'POST',6 headers: {7 'X-API-KEY': process.env.SUDOMOCK_API_KEY,8 'Content-Type': 'application/json'9 },10 body: JSON.stringify(payload)11 });1213 // Success14 if (response.ok) {15 return response.json();16 }1718 // Rate limited - wait and retry19 if (response.status === 429) {20 const retryAfter = parseInt(response.headers.get('Retry-After') || '60');21 console.log(`Rate limited. Retrying in ${retryAfter}s...`);22 await sleep(retryAfter * 1000);23 continue;24 }2526 // Server error - exponential backoff27 if (response.status >= 500) {28 const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s29 console.log(`Server error. Retrying in ${delay}ms...`);30 await sleep(delay);31 continue;32 }3334 // Client error - don't retry, throw immediately35 const error = await response.json();36 throw new Error(error.detail || JSON.stringify(error));3738 } catch (networkError) {39 // Network error - retry with backoff40 if (attempt < maxRetries - 1) {41 const delay = Math.pow(2, attempt) * 1000;42 await sleep(delay);43 continue;44 }45 throw networkError;46 }47 }48 49 throw new Error('Max retries exceeded');50}5152function sleep(ms) {53 return new Promise(resolve => setTimeout(resolve, ms));54}When to Retry
- Always retry: 429, 500, 502, 503, 504, network errors
- Never retry: 400, 401, 404, 422 (fix the request first)
Handling Validation Errors
Parse 422 errors to identify exactly which field failed:
1async function handleRenderRequest(payload) {2 const response = await fetch('https://api.sudomock.com/api/v1/renders', {3 method: 'POST',4 headers: {5 'X-API-KEY': process.env.SUDOMOCK_API_KEY,6 'Content-Type': 'application/json'7 },8 body: JSON.stringify(payload)9 });1011 if (response.status === 422) {12 const error = await response.json();13 14 // Parse validation errors15 for (const err of error.detail) {16 const fieldPath = err.loc.join('.');17 console.error(`Validation error at ${fieldPath}: ${err.msg}`);18 19 // Example: "body.export_options.quality: ensure this value is less than or equal to 100"20 }21 22 throw new Error('Validation failed: ' + error.detail.map(e => e.msg).join(', '));23 }2425 if (!response.ok) {26 const error = await response.json();27 throw new Error(error.detail);28 }2930 return response.json();31}Rate Limits by Plan
| Plan | Per Minute | Per Hour | Concurrent |
|---|---|---|---|
| Free | 5 | 30 | 1 |
| Starter | 30 | 180 | 3 |
| Pro | 100 | 600 | 10 |
| Scale | 300 | 1,800 | 25 |
Field Constraints Reference
These are the validation constraints that can trigger 422 errors:
| Field | Type | Constraints |
|---|---|---|
| export_options.image_size | integer | 100 - 8000 |
| export_options.quality | integer | 1 - 100 |
| export_options.image_format | enum | png, jpg, webp |
| smart_objects[].asset.fit | enum | fill, contain, cover |
| smart_objects[].asset.rotate | integer | -360 to 360 |
| adjustment_layers.brightness | integer | -150 to 150 |
| adjustment_layers.contrast | integer | -100 to 100 |
| adjustment_layers.saturation | integer | -100 to 100 |
| adjustment_layers.vibrance | integer | -100 to 100 |
| adjustment_layers.opacity | integer | 0 - 100 |
| adjustment_layers.blur | integer | 0 - 100 |
| color.hex | string | Pattern: ^#[0-9A-Fa-f]{6}$ |
| api_key.name | string | 1 - 255 characters |
| api_key.expires_in_days | integer | 1 - 3650 (or null) |
Need Higher Limits?
Contact us for enterprise rate limits and dedicated support.