Docs/Errors

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:

json
{
  "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"
  }
}
FieldDescription
typeError category (see below)
codeMachine-readable error code for programmatic handling
messageHuman-readable description of what went wrong
paramThe parameter that caused the error (if applicable)
doc_urlLink to the relevant docs section

HTTP Status Codes

200OK
Request succeeded.
201Created
Resource created successfully.
400Bad Request
Invalid parameters or missing required fields.
401Unauthorized
Missing or invalid API key.
403Forbidden
Valid key but insufficient permissions (e.g., publishable key trying to write).
404Not Found
The requested resource does not exist.
409Conflict
The request conflicts with the current state (e.g., duplicate idempotency key).
422Unprocessable
Syntactically valid but semantically incorrect (e.g., negative price).
429Too Many Requests
Rate limit exceeded. Check the Retry-After header.
500Server Error
Something went wrong on our end. These are rare and automatically reported.

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:

javascript
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;
}
💡
Implement exponential backoff for 429 and 500 errors. For 400 errors, fix the request — retrying won't help.

Idempotency

For POST requests, you can include an Idempotency-Key header to safely retry requests without creating duplicates:

curl
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.