RTFC API

Rate limits & spend caps

Two independent controls protect you and us: a rate limit on how fast you may call, and a spend cap on how much a billing period may cost. They are unrelated - you can be well under your rate limit and still hit your spend cap, and vice versa.

Rate limits

Requests are metered against a token bucket that refills continuously, so a short burst is fine and a sustained flood is not. Which bucket a request draws from depends on how much the endpoint costs us to serve:

BucketApplies to
defaultReads and ordinary writes. This is your plan's headline requests-per-minute.
expensiveEndpoints that dispatch real research spend: POST /claim, POST /media/probe, the upload-* endpoints, POST /session/start, POST /session/client-start. A small fraction of the same budget - pace these deliberately.
provision/provision/*. Its own, much tighter budget: creating accounts is not something a healthy integration does in a loop.

Every response tells you where you stand, so you never have to discover the limit by hitting it:

http
HTTP/1.1 200 OK
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 417
X-RateLimit-Reset: 1788306408

Over the limit you get 429 with Retry-After (whole seconds) and the same three headers:

json
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded - slow down and retry",
    "details": {
      "tier": "expensive",
      "limit_per_minute": 60,
      "retry_after_seconds": 4
    },
    "request_id": "req_82f93a9f45154f57a061e5ea8e2609c1"
  }
}

Retry-After is authoritative - honour it rather than retrying on a fixed schedule. X-RateLimit-Reset is a unix timestamp.

Need a higher limit? Rate limits are not self-service - contact us. An integrator running a device fleet or a high-volume backend can be granted a far higher ceiling (or exempted entirely) on their account alone, without changing anyone else's plan.

Spend cap

Your plan carries a maximum spend per billing period. You can read it, and how much of it you have used, at any time:

bash
curl -s $RTFC/spend-limit -H "X-Auth-Token: $TOKEN"
json
{
  "effective_cap_usd": 200.0,
  "cap_source": "self",
  "self_cap_usd": 200.0,
  "plan_cap_usd": 750.0,
  "period_start": "2026-09-01T00:00:00",
  "period_end": "2026-10-01T00:00:00",
  "spent_usd": 41.72,
  "remaining_usd": 158.28,
  "paused": false
}

You can also set your own, lower cap. This is the control to reach for if you are running an automated integration and want a guaranteed maximum for the month:

bash
curl -s -X PUT $RTFC/spend-limit -H "X-Auth-Token: $TOKEN" \
  -H 'Content-Type: application/json' -d '{"monthly_cap_usd": 200}'

# Remove it (back to your plan's own ceiling)
curl -s -X PUT $RTFC/spend-limit -H "X-Auth-Token: $TOKEN" \
  -H 'Content-Type: application/json' -d '{"monthly_cap_usd": null}'

A cap you set can only ever lower your ceiling - the limit in force is the smallest of your plan's and your own - so setting one can never grant you more budget. Asking for a value above your plan's cap returns 422 cap_above_plan_limit. cap_source in the response tells you which one is currently binding.

What happens at the cap

Reaching the cap is a hard stop, not a warning:

Everything resumes automatically - held claims are re-queued oldest first - when the billing period rolls over, when you raise or clear your own cap, or when your plan changes.

Other ceilings

LimitBehaviour
Concurrent debates402 concurrency_limit when starting a session or media ingest beyond your plan's maximum. Stop a session or wait.
Live (SSE) connections429 past your plan's maximum concurrent streams. Close streams you no longer read - one per debate you are actually watching.
Media probes per hour429 with Retry-After. A probe is a real fetch of the platform's page, so it is metered separately from the rate limit.
Video durationPOST /media/probe returns reject_reason: "too_long" and an upload returns 422 too_long. Check the probe before uploading and you will never hit this mid-flow.
Machine users402 machine_user_limit when a provisioner account is at its maximum. It counts active accounts, so deleting a device frees a slot.

Queueing is fair, not first-come-first-served. Claims are dispatched with a per-account cap and a round-robin release, so a large batch ingest never blocks another account's work - and never blocks its own later claims indefinitely either. A burst is queued and released as capacity frees; nothing is dropped.

Handling limits well

Read X-RateLimit-Remaining and slow down before it reaches zero rather than retrying into a wall. On a 429, wait exactly Retry-After seconds. On a 402, stop and surface it - retrying will not help until the period rolls over or the cap changes, and the details object tells you when that is. Branch on error.code, never on the status alone.