Errors
The HanDl API uses conventional HTTP status codes and returns structured error responses to help you handle issues gracefully.
Error Response Format
All errors follow the same structure:
{
"error": {
"type": "invalid_request_error",
"code": "missing_required_field",
"message": "The 'name' field is required when creating a product.",
"param": "name",
"doc_url": "https://docs.handl-ng.com/errors#missing_required_field"
}
}| Field | Description |
|---|---|
| type | Error category (see below) |
| code | Machine-readable error code for programmatic handling |
| message | Human-readable description of what went wrong |
| param | The parameter that caused the error (if applicable) |
| doc_url | Link to the relevant docs section |
HTTP Status Codes
Error Types
invalid_request_error
You sent an invalid request — missing fields, wrong types, or bad formatting. Fix the request and retry.
authentication_error
Your API key is missing, invalid, or revoked. Check that you're using the right key and that it hasn't been deleted.
permission_error
Your key doesn't have permission for this action. Publishable keys (pk_) are read-only. Switch to a secret key (sk_) for write operations.
not_found_error
The resource you requested doesn't exist or has been deleted. Double-check the ID.
rate_limit_error
You've exceeded your plan's rate limit. Wait for the duration specified in the Retry-After header, then retry.
api_error
An error on HanDl's side. These are automatically reported. If persistent, contact support.
Handling Errors
Here's a recommended pattern for handling API errors:
async function callHanDl(path, options = {}) {
const res = await fetch(`https://api.handl-ng.com/v1${path}`, {
...options,
headers: {
'Authorization': 'Bearer sk_live_...',
'Content-Type': 'application/json',
...options.headers,
},
});
const body = await res.json();
if (!res.ok) {
const { error } = body;
switch (error.type) {
case 'authentication_error':
throw new Error('Invalid API key — check your credentials');
case 'rate_limit_error':
const retryAfter = res.headers.get('Retry-After');
await new Promise(r => setTimeout(r, retryAfter * 1000));
return callHanDl(path, options); // Retry
case 'invalid_request_error':
throw new Error(`Bad request: ${error.message}`);
default:
throw new Error(`HanDl API error: ${error.message}`);
}
}
return body;
}Idempotency
For POST requests, you can include an Idempotency-Key header to safely retry requests without creating duplicates:
curl -X POST https://api.handl-ng.com/v1/orders \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: unique-request-id-123" \
-H "Content-Type: application/json" \
-d '{ ... }'Idempotency keys expire after 24 hours. If the same key is reused within that window, HanDl returns the original response without creating a new resource.