Error Handling

The Madless API uses conventional HTTP status codes and returns all errors in the RFC 7807 Problem Details format. Every error response includes a machine-readable type, a human-readable title, the HTTP status code, and a detailed description of what went wrong.

Error Shape

Every error response uses application/problem+json as the content type. The instance field echoes the request path for easier debugging.

{
  "type": "/errors#not_found",
  "title": "not found",
  "status": 404,
  "detail": "Concept cpt_abc123 not found.",
  "instance": "/api/v1/canvas/concepts/cpt_abc123"
}

Validation errors (400) include an additional issues array with per-field details from Zod schema validation.

Common Status Codes

CodeMeaning
200OK
201Created
204No Content
400Bad Request
401Unauthorized
403Forbidden
404Not Found
409Conflict
422Unprocessable Entity
429Rate Limited
500Server Error

Rate Limiting

When you exceed the rate limit for an endpoint, the API returns 429 Too Many Requests. Every response includes headers to help you manage your request budget:

HeaderDescription
Retry-AfterSeconds to wait before retrying the request.
X-RateLimit-LimitMaximum number of requests allowed per window.
X-RateLimit-RemainingRequests remaining in the current window.
X-RateLimit-ResetUnix timestamp when the current window resets.

Idempotency

All write endpoints (POST, PUT, PATCH) support idempotent requests. Include an Idempotency-Key header with a unique identifier (a UUID works well). If the server has already processed a request with the same key, it returns the original response without executing the operation again.

curl -X POST 'https://acme.madless.com/api/v1/canvas/concepts' \
  -H 'Authorization: Bearer mad_sk_abc123...' \
  -H 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Compound Intelligence",
    "notes": "A knowledge graph that compounds over time."
  }'

Keys expire after 24 hours. Using the same key with a different request body returns 409 Conflict.

Retry with backoff

For 429 and 5xx errors, use exponential backoff with jitter. Always respect the Retry-After header when present. Do not retry 4xx errors other than 429 — they indicate a problem with the request itself that must be fixed before retrying.