API Errors Reference
A practical reference for every error code REST API v1 can return, what it means and how to fix it. All responses use a consistent envelope format.
Standard error envelope
{
"error": {
"code": "rate_limited",
"message": "Rate limit of 100 requests per minute exceeded.",
"status": 429
}
}
validation_failed also returns field-level details:
{
"error": { "code": "validation_failed", "message": "...", "status": 422 },
"errors": {
"email": { "code": "invalid_email", "message": "email must be a valid email address." },
"department": { "code": "too_long", "message": "department must be at most 50 characters." }
},
"fields": ["email", "department"]
}
Transport / Auth errors
Errors returned when the request reaches the API layer but before it reaches the resource.
Request is missing the Authorization: Bearer <api_key> header.
Fix: Named the API key header to every request. You can generate a key from /api_keys.php in the panel.
Bearer token does not start with tdk_ or is shorter than 40 characters.
Fix: Copy the full key and send it as Authorization: Bearer tdk_....
API key was not found in the database or hash did not match.
Fix: Verify the key is still active in the panel. A deleted key cannot be recreated — generate a new key.
Key has been revoked by an admin.
Fix: Generate a new key and update the old integration.
Tenant is not active (trial expired or suspended by an admin).
Fix: Contact your account manager or renew your subscription.
Could not connect to the tenant database.
Fix: This may be a transient infrastructure issue. Retry after respecting the Retry-After header. If the problem persists, check the status page.
Key does not have the required scope for this endpoint or HTTP method.
Fix: Ensure you selected the correct scope (e.g. customers:write) when creating the key.
The rate limit of 100 requests per minute has been exceeded.
Fix: Wait for the duration specified in the Retry-After: 60 header. Spread requests at a steady rate instead of bursting; monitor with X-RateLimit-Remaining.
This HTTP method is not supported for the endpoint.
Fix: Use one of the methods returned in the Allow header. See the OpenAPI reference.
Request body is not valid JSON.
Fix: Send a Content-Type: application/json header with a valid JSON body. No trailing commas; double quotes required.
Resource errors
Errors returned after accessing the endpoint resource.
No record found with the specified ID.
Fix: Verify the ID is correct and belongs to the active tenant. A deleted record returns 404.
PUT/DELETE request is missing ?id=N in the query string.
Fix: Named the target record's ID as a query parameter.
No valid updatable fields found in the request body.
Fix: Include at least one updatable field in the PUT body. Read-only fields (id, created_at) are ignored.
General request error — missing or invalid parameter.
Fix: Read the hint in the error message. Check the required fields for the endpoint in the OpenAPI spec.
Field-level validation errors (required, format, enum, length).
Fix: Each field has its own code + message in the errors object of the response. Fix all of them and resubmit.
The specified customer_id does not exist.
Fix: Create the customer first (POST /customers.php), then add the employee.
The specified employee_id does not exist.
Fix: Ensure the employee record exists before assigning hardware to them.
Delete request was rejected due to a foreign key constraint (related records exist).
Fix: Delete or reassign the dependent records (employees, hardware, etc.) first. The DB error message is returned in the details field.
Validation field codes
validation_failed sub-codes returned per field:
| Code | Meaning |
|---|---|
required |
Required field is empty. |
invalid_email |
Invalid email format. |
invalid_int |
An integer was expected. |
invalid_date |
Must be in YYYY-MM-DD format. |
invalid_bool |
A boolean (true/false, 1/0) was expected. |
too_long |
Maximum character limit exceeded. |
too_short |
Below the minimum character limit. |
not_in_list |
Value is not one of the allowed enum values. |
Rate limit headers
Three headers returned on all successful responses and on rate_limited errors:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1718983261
Retry-After: 60 # only on 429
Production integrations should monitor Remaining and avoid bursting until the Reset epoch.
Idempotency
Named an Idempotency-Key: <uuid> to POST/PUT/DELETE requests. A second request with the same key returns the original response (24-hour window) — no risk of duplicate records on network retries.
Source: api/v1/_bootstrap.php (transport) + each endpoint file (resource). This page is updated when a new error code is added. The error code list is also available in the OpenAPI spec.