>_
SudoMock
API Reference

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.

200OK

Request successful. Response contains requested data.

201Created

Resource created successfully. Used for API key generation.

204No Content

Request successful, no content returned. Used for delete operations.

400Bad Request

Invalid request format, missing required fields, or malformed JSON.

401Unauthorized

Invalid or missing API key (X-API-KEY header) or Bearer token.

404Not Found

Resource not found. Check mockup_uuid, smart_object_uuid, or key_id.

422Validation Error

Request body validation failed. Check field types and constraints.

429Rate Limited

Too many requests. Wait and retry with exponential backoff.

500Internal Server Error

Unexpected server error. Safe to retry with backoff.

Error Response Format

Standard error responses (400, 401, 404, 500) follow this structure:

ErrorResponse Schema
1
{
2
"success": false,
3
"detail": "Human-readable error message"
4
}

Validation errors (422) have a different structure with detailed field information:

HTTPValidationError Schema (422)
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.

400 Bad Request - Upload
1
// Request with invalid URL
2
POST /api/v1/psd/upload
3
{
4
"psd_file_url": "not-a-valid-url"
5
}
6
7
// Response
8
{
9
"success": false,
10
"detail": "Invalid PSD file URL format"
11
}

401 Unauthorized

Missing or invalid X-API-KEY header.

401 Unauthorized
1
// Request without API key
2
POST /api/v1/psd/upload
3
X-API-KEY: (missing or invalid)
4
5
// Response
6
{
7
"success": false,
8
"detail": "Invalid or missing API key"
9
}

422 Validation Error

Request body validation failed.

422 Validation Error - Missing Field
1
// Request missing required field
2
POST /api/v1/psd/upload
3
{
4
"psd_name": "My Mockup"
5
// Missing: psd_file_url (required)
6
}
7
8
// Response
9
{
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.

400 Bad Request - Render
1
// Request with invalid asset URL
2
POST /api/v1/renders
3
{
4
"mockup_uuid": "valid-uuid",
5
"smart_objects": [{
6
"uuid": "so-uuid",
7
"asset": { "url": "not-accessible-url" }
8
}]
9
}
10
11
// Response
12
{
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.

404 Mockup Not Found
1
// Request with invalid mockup_uuid
2
POST /api/v1/renders
3
{
4
"mockup_uuid": "non-existent-uuid",
5
"smart_objects": [...]
6
}
7
8
// Response
9
{
10
"success": false,
11
"detail": "Mockup not found"
12
}

422 Validation Error

Invalid field types or constraint violations.

422 Validation Error - Invalid Values
1
// Request with invalid field type
2
POST /api/v1/renders
3
{
4
"mockup_uuid": "valid-uuid",
5
"smart_objects": "should-be-array"
6
}
7
8
// Response
9
{
10
"detail": [
11
{
12
"loc": ["body", "smart_objects"],
13
"msg": "value is not a valid list",
14
"type": "type_error.list"
15
}
16
]
17
}
18
19
// Request with invalid export options
20
POST /api/v1/renders
21
{
22
"mockup_uuid": "valid-uuid",
23
"smart_objects": [...],
24
"export_options": {
25
"image_size": 10000, // Max is 8000
26
"quality": 150 // Max is 100
27
}
28
}
29
30
// Response
31
{
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).

401 Unauthorized - Bearer Token
1
// Request without Bearer token
2
POST /api/v1/api-keys
3
Authorization: (missing)
4
5
// Response
6
{
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.

404 API Key Not Found
1
// Request to delete non-existent key
2
DELETE /api/v1/api-keys/non-existent-id
3
4
// Response
5
{
6
"success": false,
7
"detail": "API key not found"
8
}

422 Validation Error

Invalid API key name or expiration days.

422 Validation Error - API Key
1
// Request with invalid expiration
2
POST /api/v1/api-keys
3
{
4
"name": "My Key",
5
"expires_in_days": 5000 // Max is 3650
6
}
7
8
// Response
9
{
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.

500 Internal Server Error
1
// Response on server error
2
{
3
"success": false,
4
"detail": "An unexpected error occurred. Please try again."
5
}

Report Persistent Errors

If you encounter repeated 500 errors, please contact us at [email protected] with your request details.

Retry Strategy

Implement exponential backoff for failed requests:

Retry with Exponential Backoff
1
async 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
});
12
13
// Success
14
if (response.ok) {
15
return response.json();
16
}
17
18
// Rate limited - wait and retry
19
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
}
25
26
// Server error - exponential backoff
27
if (response.status >= 500) {
28
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
29
console.log(`Server error. Retrying in ${delay}ms...`);
30
await sleep(delay);
31
continue;
32
}
33
34
// Client error - don't retry, throw immediately
35
const error = await response.json();
36
throw new Error(error.detail || JSON.stringify(error));
37
38
} catch (networkError) {
39
// Network error - retry with backoff
40
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
}
51
52
function 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:

Parsing Validation Errors
1
async 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
});
10
11
if (response.status === 422) {
12
const error = await response.json();
13
14
// Parse validation errors
15
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
}
24
25
if (!response.ok) {
26
const error = await response.json();
27
throw new Error(error.detail);
28
}
29
30
return response.json();
31
}

Rate Limits by Plan

PlanPer MinutePer HourConcurrent
Free5301
Starter301803
Pro10060010
Scale3001,80025

Field Constraints Reference

These are the validation constraints that can trigger 422 errors:

FieldTypeConstraints
export_options.image_sizeinteger100 - 8000
export_options.qualityinteger1 - 100
export_options.image_formatenumpng, jpg, webp
smart_objects[].asset.fitenumfill, contain, cover
smart_objects[].asset.rotateinteger-360 to 360
adjustment_layers.brightnessinteger-150 to 150
adjustment_layers.contrastinteger-100 to 100
adjustment_layers.saturationinteger-100 to 100
adjustment_layers.vibranceinteger-100 to 100
adjustment_layers.opacityinteger0 - 100
adjustment_layers.blurinteger0 - 100
color.hexstringPattern: ^#[0-9A-Fa-f]{6}$
api_key.namestring1 - 255 characters
api_key.expires_in_daysinteger1 - 3650 (or null)

Need Higher Limits?

Contact us for enterprise rate limits and dedicated support.