The numeric limits below are operational guidance, not contractual.
Future Demand adjusts them per partner. Confirm the current limits
with your account contact if your integration needs sustained
high-throughput.
What the platform does internally
Future Demand’s internal services retry transient failures across the stack — this is useful context when designing your own retry policy:| Aspect | Internal behaviour |
|---|---|
| Retry attempts | 5 |
| Retryable status codes | 500, 502, 503, 504, 429 |
| Request timeout (selected upstreams, e.g. recommender) | 5 s |
| All-retries-failed | Internal alert posted to Future Demand’s Teams channel |
Detecting a rate limit
Retry-After is missing (it often is), default to 5–10 seconds.
Exponential backoff with jitter
Client-side rate limiting
For workloads that walk many resources (e.g. “for each event, fetch the benchmark”), throttle yourself rather than rely on retry. Use a simple semaphore:What gets rate-limited
| Endpoint family | Notes |
|---|---|
/auth/* | The tightest budget. Don’t sign in on every request — cache the session. |
Bulk reads (/events/, /campaigns/, …) | Pagination is fine. Don’t ask for limit=10000. |
Writes (/setup_processes/*, /campaigns_setup, …) | Debounce autosaves (the reference webapp uses 1s debounce + AbortController). |
| Status polls | Stay at 3s+ intervals; for task state polling, retry only after a PUT, not in a continuous loop. |
Common mistakes
Polling task state on a 200ms timer
Polling task state on a 200ms timer
Tight loops hit the limiter and don’t make the task complete any faster.
Use 2s with backoff.
Refreshing tokens reactively on every 401
Refreshing tokens reactively on every 401
A burst of failed requests creates a burst of refresh attempts. Use
single-flight refresh (see Token refresh).
Walking the full event list without throttling
Walking the full event list without throttling
for (const e of events) await fetchDetail(e.id) looks innocent but
sustained at 100ms-per-request hits the limit in 6 seconds. Use the
semaphore pattern above.Retrying on POST/PUT with the same idempotency assumption
Retrying on POST/PUT with the same idempotency assumption
POST /campaigns/, POST /setup_processes/{eid} are not idempotent.
Retrying after a 429 is fine — but make sure the previous call really
didn’t succeed (check status) before re-issuing the same write.