API Reference›Error Handling
Error Handling
Error format
Most API errors return a JSON object with a single error string. This reference covers HTTP status codes, validation messages, retry guidance, and how to surface failures from webhook handlers.
{ "error": "Monitor not found" }
Some errors include additional fields:
Rate limit errors (429) include a retry_after_seconds field:
{
"error": "Too many requests",
"retry_after_seconds": 60
}
OAuth token errors follow RFC 6749 and include an error_description:
{
"error": "invalid_client",
"error_description": "Invalid client credentials"
}
HTTP status codes
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid fields |
401 | Unauthenticated — missing, invalid, or expired token |
403 | Forbidden — valid token but insufficient permissions, or plan limit reached |
404 | Resource not found |
429 | Rate limited — back off and retry |
500 | Internal server error — transient, retry with backoff |
503 | Service unavailable — upstream dependency (e.g. OAuth provider) is down |
Common error messages
| Message | Status | What happened |
|---|---|---|
"Authorization header missing or invalid" | 401 | No Authorization: Bearer <token> header |
"Invalid or expired token" | 401 | Token has expired or been tampered with — re-authenticate |
"Invalid API key" | 401 | The API key used to generate this token has been revoked |
"Monitor not found" | 404 | No monitor with this ID exists in your team |
"Your plan allows a maximum of N monitors" | 403 | Upgrade your plan to create more monitors |
"Too many requests" | 429 | You have exceeded the rate limit — see the retry_after_seconds field |
"Internal server error" | 500 | Transient server error — retry with exponential backoff |
Handling errors in code
const res = await fetch('https://www.diffhook.com/api/monitors', {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
if (!res.ok) {
const body = await res.json()
const message = body.error
if (res.status === 429) {
const retryAfter = body.retry_after_seconds ?? 60
// wait and retry
} else if (res.status === 401) {
// re-authenticate with POST /api/oauth/token
} else {
console.error(message)
}
}
5xx errors
Server errors are transient. Retry with exponential backoff — most resolve within seconds. If a 500 or 503 persists for more than a few minutes, check our status page or email support@diffhook.com.