Errors
The Docyard API uses conventional HTTP status codes to indicate success or failure. Codes in the 2xx range indicate success. Codes in the 4xx range indicate a client error. Codes in the 5xx range indicate a server error.
All error responses follow this structure:
{
"statusCode": 400,
"message": "Domain 'example.com' is already registered to another dock",
"error": "Bad Request"
}
| Field | Type | Description |
|---|
statusCode | integer | HTTP status code |
message | string | Human-readable explanation of the error |
error | string | HTTP status text |
HTTP Status Codes
Success Codes
| Code | Meaning |
|---|
200 | Request succeeded |
201 | Resource created successfully |
Client Error Codes
| Code | Meaning | Common Causes |
|---|
400 | Bad Request | Validation failure, duplicate domain, invalid field format |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | Key lacks permission for this dock or resource |
404 | Not Found | Dock, artifact, recipient, policy, or job does not exist |
409 | Conflict | Resource already exists (e.g., duplicate email in dock) |
422 | Unprocessable Entity | Request is well-formed but semantically invalid |
429 | Too Many Requests | Rate limit exceeded — check Retry-After header |
Server Error Codes
| Code | Meaning |
|---|
500 | Internal Server Error |
503 | Service Unavailable |
Validation Errors
When request body validation fails, the message field contains an array of specific validation errors:
{
"statusCode": 400,
"message": [
"name must be a string",
"email must be an email"
],
"error": "Bad Request"
}
The API uses a whitelist validation strategy. Unknown fields in the request body are silently stripped — they do not cause errors, but they are not stored.
Handling Errors
Implement idempotent retry logic for transient failures (5xx, 429):
async function docyardRequest(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.ok) return response.json();
if (response.status === 429 || response.status >= 500) {
const retryAfter = response.headers.get('Retry-After') || 2 ** attempt;
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
// Client errors — do not retry
const error = await response.json();
throw new Error(`${error.statusCode}: ${error.message}`);
}
throw new Error('Max retries exceeded');
}
Never retry 4xx errors (except 429). These indicate a problem with your request that retrying will not fix.