Skip to content

API reference

Rate limits

Per-agent requests per minute, widget limits per key and per visitor, workflow limits, the X-RateLimit headers and how to retry.

Reference1 min readUpdated 23 October 2026

Limits protect your credits and the service from runaway loops. They are checked before a credit is spent, so a rejected request costs nothing.

The limits

WhatLimitScope
Chat requests60 a minute for new agentsPer agent, a fixed one-minute window, shared by the API, the widget and workflow Agent steps
Widget, per key120 a minutePer publishable key
Widget, per visitor12 a minutePer visitor IP address on that key (stored hashed)
Workflow runs30 a minute, 5 at oncePer account
Workflow webhook triggers60 a minutePer workflow
Workflow emails100 a dayPer account

The agent limit is shown read-only on the agent's Settings tab. It isn't a plan limit; if you need a higher one, email support.

Headers

HeaderMeaning
X-RateLimit-LimitRequests allowed per minute for this agent
X-RateLimit-RemainingRequests left in the current window
X-RateLimit-ResetSeconds until the current window resets

Chat responses carry these on success and on 429. A chat 429 has no Retry-After: wait the number of seconds in X-RateLimit-Reset. Workflow 429s do send Retry-After (10 seconds for TOO_MANY_RUNNING).

Retrying well

  • Retry 429 after the reset, with a cap on attempts. Don't retry in a tight loop.
  • Don't retry 400, 401, 402, 403, 404 or 422: they won't succeed until something changes.
  • Retry LLM_UNAVAILABLE and TIMEOUT once or twice with a growing pause.
  • If you fan out many requests, queue them so you stay under the agent's per-minute limit.
Retry on 429
async function chatWithRetry(body, attempt = 0) {  const res = await fetch("https://api.sentientone.ai/v1/chat/stream", {    method: "POST",    headers: {      "Content-Type": "application/json",      "X-Api-Key": process.env.SENTIENTONE_API_KEY,      "X-Agent-Id": process.env.AGENT_ID,    },    body: JSON.stringify(body),  })  if (res.status === 429 && attempt < 3) {    // Chat 429s carry X-RateLimit-Reset, the seconds until the window resets (no Retry-After)    const reset = Number(res.headers.get("X-RateLimit-Reset"))    const waitMs = Number.isFinite(reset) && reset > 0 ? reset * 1000 : 2000 * (attempt + 1)    await new Promise((r) => setTimeout(r, Math.min(waitMs, 60_000)))    return chatWithRetry(body, attempt + 1)  }  return res}

Still stuck?

Email us with what you tried and any request id. A person replies.

support@sentientone.ai