Docs
On this page
Last updated 2026-07-07 API version v1

Rate Limits & Quotas

InvesTeam rate-limits programmatic (hfk_) keys on the routes that spend work — the submits. Reads are not the throttled surface, but you should still poll at a sane cadence. This page covers what is limited, how to handle a 429, and how fast to poll.

What are InvesTeam's rate limits?

Two limits apply per API key, both on the spend-triggering submit routes — POST /api/v1/briefs, POST /api/v1/briefs/{id}/answers, and POST /api/v1/orchestrations:

  • A submit rate limit (a token bucket) on every mutating route.
  • A daily kickoff quota, drawn down by all three write routes — so an answer submit also consumes from the same daily allowance as a brief create or a convene.

Exceeding either returns 429 rate_limited (retryable: true) with a Retry-After header in integer seconds. Firebase (browser) users are not subject to these per-key limits.

The exact numeric defaults (rate, burst, daily cap) are configuration, not a published contract, and the limiter is per-instance — so treat the Retry-After header as the source of truth for back-off timing, not a hard-coded number.

How do I handle a 429?

Wait the advertised Retry-After interval, then retry — do not retry immediately, and do not tighten your loop. A 429 is retryable: true, so a well-behaved client backs off and continues.

python
import time
import requests

def submit_with_backoff(url, headers, json):
    while True:
        resp = requests.post(url, headers=headers, json=json)
        if resp.status_code != 429:
            return resp
        wait = int(resp.headers.get("Retry-After", "5"))
        time.sleep(wait)

Read the error envelope to distinguish a rate_limited 429 from other failures — only retryable: true errors should back off and retry.

How fast can I poll?

Poll the read routes every two to three seconds — that is the cadence the product uses and it is well within limits. Reads are not the throttled surface, but relentless sub-second polling wastes your budget and the shared poll paths for no benefit, since results arrive on the order of seconds, not milliseconds.

Two poll disciplines keep it cheap:

  • Advance the transcript cursor forward only. Pass the returned latest_seq as the next after; never re-read consumed turns. See the Transcript reference.
  • Drain then stop. Once an execution is terminal, do one final transcript read and stop polling — a terminal stage produces nothing new.

Where next?

For the full error catalog and the meaning of retryable, see the Error Reference. For the submit-then-poll pattern that shapes your call volume, see the async model.