WatchFor
API

Errors & rate limits

The error envelope, every error code, and how per-key rate limiting works.

Error envelope

Errors always return the same JSON shape — switch on the machine-readable code, show the message to humans:

{
  "error": {
    "code": "not_found",
    "message": "Monitor not found"
  }
}
HTTPcodeWhen
400invalid_requestMalformed JSON, failed validation, bad cursor
401unauthorizedMissing, unknown, revoked or expired API key
403forbiddenKey lacks the write scope, or the plan has no API access
404not_foundResource doesn't exist (or belongs to another organization)
409conflictInvalid state transition, or an Idempotency-Key reused with a different request
405method_not_allowedHTTP method not supported on this endpoint (see the Allow header)
429rate_limitedRequest budget exhausted
500internal_errorSomething broke on our side — safe to retry
501not_implementedEndpoint is on the roadmap but not available yet

Validation errors put the field path in the message:

{
  "error": {
    "code": "invalid_request",
    "message": "durationMinutes: Number must be greater than or equal to 5"
  }
}

Idempotency & safe retries

Every endpoint is safe to retry:

  • GET / DELETE / PATCH are idempotent by nature — repeating them yields the same end state (a repeated DELETE returns 404, which your retry logic can treat as success).
  • POST actions (pause, resume, acknowledge, resolve) are idempotent no-ops when the resource is already in the target state — they return 200 with the current object instead of erroring.
  • POST creates accept an optional Idempotency-Key header (any unique string up to 255 chars, e.g. a UUID). If a request with the same key already succeeded within 24 hours, the stored response is replayed with an Idempotency-Replay: true header and no duplicate resource is created. Reusing a key with a different request body returns 409.
curl -X POST https://watchfor.io/api/v1/maintenance-windows \
  -H "Authorization: Bearer wf_live_YOUR_KEY" \
  -H "Idempotency-Key: 3f7a2c9e-retry-safe" \
  -H "Content-Type: application/json" \
  -d '{ "name": "DB upgrade", "…": "…" }'

Rate limits

Each API key has a per-minute request budget determined by your plan (sliding window). Every response reports where you stand:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42

When the budget is exhausted you get 429 with a Retry-After header (seconds). Back off at least that long — ideally exponentially with jitter, and never retry a 429 immediately.

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded — slow down"
  }
}

On this page