Reference

Errors & rate limits

Every failure comes back as JSON in one shape, with a status code that tells you the category and a message that tells you the fix. Nothing throws HTML at you — the API surface always negotiates JSON.

The error envelope

422 with field errors json
{
  "error": {
    "type": "invalid_request_error",
    "message": "The amount field must be a non-zero integer.",
    "fields": {
      "amount": ["The amount field must be a non-zero integer."]
    }
  }
}

type and message are always present. fields appears only on validation errors (422) and maps each rejected field to its messages.

Status codes

CodeTypeMeaning
202Event accepted and queued (ingest and /v1/events).
200 / 201Read succeeded; resource created.
204No content (e.g. participant erasure).
401authentication_errorMissing, unrecognised, invalid or revoked credential.
403permission_errorValid key without the required ability, or a blocked IP.
404not_found_errorUnknown resource or inactive ingest endpoint.
422invalid_request_errorMalformed or failing validation.
429Rate limit exceeded.

X-Request-Id

Every response carries an X-Request-Id. If you send one, it's echoed back; otherwise Flyhalf generates one. Log it and quote it in support requests — it's the fast path to the exact request in our logs.

Rate limits

SurfaceLimitKeyed by
Ingest1,200 / minPer endpoint key
Authenticated API300 / minPer API key

Ingest is deliberately generous — accept-and-queue must never be the bottleneck — and keyed per endpoint so one flooding integration can't starve another. Exceeding a limit returns 429; back off and retry. Because ingest is idempotent, a retried event after a 429 is safe.

Monthly quotas

On top of per-minute rate limits, each plan has monthly quotas. Metered dimensions are events, messages, ai_generations and exports. You get a soft warning at 80% and a hard cap at 100%.

PlanEvents / moMessagesAI generations
Starter10,00050050
Growth250,00010,000500
ScaleCustomCustomCustom

Sandbox doesn't count against quota

Only live events are metered — events sent with a fh_test_ key or ?sandbox=1 are free. Load-test your flows in sandbox without spending your monthly allowance. See Sandbox mode.