Rate limits
Per-workspace request limits for each plan, separate windows for decisions and reads, the X-RateLimit headers on every call, Retry-After on 429 and how to back off.
The public API limits how many requests a workspace can make per minute. The limit comes from the workspace's plan:
| Plan | Requests per minute |
|---|---|
| Genesis | 60 |
| Developer | 300 |
| Growth | 2,000 |
| Enterprise | 10,000 |
The API Keys page in the app shows your current limit, and GET /v1/me returns it as plan.rate_limit_per_minute.
How the limit is counted
- Per workspace, not per key. All API keys of a workspace share one budget; creating more keys doesn't add capacity.
- Decisions and reads have separate windows.
POST /v1/decisions/{slug}counts in one window; the read endpoints,GET /v1/decisions,GET /v1/meandGET /v1/executions, in another with the same per-minute limit — so polling them never slows down your decisions. Calls to a decision's webhook URL have a third window of their own (same limit, shared by the workspace's webhooks), so a leaked URL can't slow down your API keys. Every request to the MCP server (initialize,tools/list, any tool call) counts with reads, andrun_decisionalso counts with decisions. Webhook calls with a wrong signature or secret don't touch these windows: they have their own budget of 30 a minute per webhook (then429). - Fixed one-minute windows. A window opens with the first request and lasts 60 seconds; the next request after that opens a new one.
- Every authenticated request counts — successful calls, errors and idempotent replays alike. Requests with an invalid key are rejected before the limit and don't count.
Headers
Every authenticated response carries the state of its window — the decision window or the read window:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 12
X-RateLimit-Reset: 1791195060| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed per window for your workspace. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | When the current window ends, in Unix seconds. |
When you hit the limit
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1791195060{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Slow down and retry after the reset time.",
"request_id": "req_Tz6Kq1mW8vLp3Xc9Rn4D"
}
}Wait Retry-After seconds, then retry. Requests sent before that keep failing — and keep counting.
async function decide(slug, state) {
for (let attempt = 0; attempt < 3; attempt++) {
const response = await fetch(`https://api.dcision.io/v1/decisions/${slug}`, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DCISION_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ state }),
});
if (response.status !== 429) return response;
const wait = Number(response.headers.get("Retry-After") ?? "1");
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
}
throw new Error("Still rate limited after 3 attempts");
}Staying under the limit
- Watch
X-RateLimit-Remainingand slow down before it reaches 0. - Smooth bursts with a queue or a token bucket on your side instead of sending them at once.
- Don't spread load over more keys — they share the workspace budget.
- Need more? Upgrade your plan, or talk to sales@dcision.io about Enterprise.
Playground limits
Playground runs have their own ceiling, separate from the API: 30 runs per minute and 2,000 runs per day per workspace. Above it the Playground answers 429 RATE_LIMITED; use an API key for volume.
Engine throughput
The engine provider has limits of its own, in requests and tokens per second. On Dcision's engine key they are shared by every workspace, so Dcision smooths bursts: a decision waits for a free slot within its timeoutMs instead of failing at once. If none frees up in time, the call fails with 503 ENGINE_RATE_LIMITED — an engine error, retryable with backoff, not your workspace's 429 RATE_LIMITED. With your own provider key, your provider account's limits apply. See Engines and BYOK.
Errors
The error format and every error code with its HTTP status, what it means and what to do about it — plus which errors are safe to retry.
Idempotency
Retry safely with the Idempotency-Key header — keys reserved before the run, replays of successful calls for 24 hours, the Idempotent-Replayed header and IDEMPOTENCY_CONFLICT.