Skip to main content
All DevHelm API errors return a consistent JSON structure with an HTTP status code, human-readable message, and timestamp.

Error response format

{
  "status": 400,
  "message": "Monitor name must not be blank",
  "timestamp": 1712956800000
}
FieldTypeDescription
statusintegerHTTP status code
messagestringHuman-readable error description
timestamplongUnix timestamp in milliseconds

HTTP status codes

StatusMeaningCommon causes
400Bad RequestValidation errors, malformed JSON, invalid parameters
401UnauthorizedMissing, invalid, or revoked API key
403ForbiddenValid key but insufficient permissions for the organization
404Not FoundResource doesn’t exist or isn’t accessible in the current organization
429Too Many RequestsRate limit exceeded (see Rate Limits)
500Internal Server ErrorUnexpected server error
502Bad GatewayBilling provider error
503Service UnavailableTemporary service disruption

Validation errors

When a request fails validation, the message field contains details about which fields are invalid:
{
  "status": 400,
  "message": "name: must not be blank; frequencySeconds: must be greater than 0",
  "timestamp": 1712956800000
}
Multiple validation errors are combined into a single message with semicolon separators.

Common error scenarios

Authentication errors

# Missing API key
curl https://api.devhelm.io/api/v1/monitors
# → 401: "Full authentication is required"

# Invalid key
curl https://api.devhelm.io/api/v1/monitors \
  -H "Authorization: Bearer dh_live_invalid"
# → 401: "Invalid or revoked API key"

Resource not found

curl https://api.devhelm.io/api/v1/monitors/nonexistent-id \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN"
# → 404: "Monitor not found"

Entitlement limits

# Exceeding monitor limit on your plan
curl -X POST https://api.devhelm.io/api/v1/monitors \
  -H "Authorization: Bearer $DEVHELM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
# → 400: "Monitor limit reached for your plan"

Handling errors in code

try {
  const monitor = await client.monitors.create({ ... });
} catch (error) {
  if (error.status === 429) {
    // Rate limited — retry after delay
    const retryAfter = error.headers.get("Retry-After");
    await sleep(parseInt(retryAfter) * 1000);
  } else if (error.status === 400) {
    // Validation error
    console.error("Invalid request:", error.message);
  }
}

Rate limit errors

429 responses include extra headers — see Rate Limits for details.