API ReferenceError 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

StatusMeaning
400Bad request — missing or invalid fields
401Unauthenticated — missing, invalid, or expired token
403Forbidden — valid token but insufficient permissions, or plan limit reached
404Resource not found
429Rate limited — back off and retry
500Internal server error — transient, retry with backoff
503Service unavailable — upstream dependency (e.g. OAuth provider) is down

Common error messages

MessageStatusWhat happened
"Authorization header missing or invalid"401No Authorization: Bearer <token> header
"Invalid or expired token"401Token has expired or been tampered with — re-authenticate
"Invalid API key"401The API key used to generate this token has been revoked
"Monitor not found"404No monitor with this ID exists in your team
"Your plan allows a maximum of N monitors"403Upgrade your plan to create more monitors
"Too many requests"429You have exceeded the rate limit — see the retry_after_seconds field
"Internal server error"500Transient 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.