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.
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.
| Code | Meaning | When |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource successfully created |
| 204 | No Content | Successful delete, no body returned |
| 400 | Bad Request | Invalid body or query parameters |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Insufficient scopes or entitlements |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Duplicate or conflicting state |
| 422 | Unprocessable Entity | Schema validation failure |
| 429 | Rate Limited | Too many requests in window |
| 500 | Server Error | Unexpected internal failure |
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:
| Header | Description |
|---|---|
| Retry-After | Seconds to wait before retrying the request. |
| X-RateLimit-Limit | Maximum number of requests allowed per window. |
| X-RateLimit-Remaining | Requests remaining in the current window. |
| X-RateLimit-Reset | Unix timestamp when the current window resets. |
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.
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.