跳转到内容

Rate Limiting

此内容尚不支持你的语言。

This page lists every rate limit currently enforced by the Wetel API, sourced directly from the API’s throttling configuration (last reconciled against the deployed code on 2026-09-17). Anything not listed here has no enforced limit today — see No limit today below before relying on that in production.

Every GraphQL rate limit below is keyed by the calling client’s IP address — not by API key, tenant, or user. Two consequences worth designing for:

  • If your backend proxies many end users through one server, all of them share that server’s bucket. Apply your own per-user fairness limiter in front if that matters to you.
  • Conversely, one abusive caller cannot exhaust a tenant’s budget for everyone else — which is the reason sdkStart is limited this way rather than per tenant.

The window is fixed per operation (mostly 60 seconds). Exceeding a limit returns a GraphQL error with HTTP 429 semantics; back off and retry after the window.

All throttled GraphQL operations require the standard x-huat-platform: customer header alongside your normal authentication — see Authentication.

OperationLimitWindow
sdkStart30 requestsper 60 seconds, per client IP
refreshAvatarToken10 requestsper 60 seconds, per client IP

sdkStart: added 2026-09-08. Every sdkStart creates a session and fires a metered opening-greeting LLM call, so an unthrottled endpoint would let anyone holding a leaked API key inflate a tenant’s bill. Thirty per minute is far above any real embed’s start rate; if you legitimately need more (e.g. a load test), run it from more than one source IP.

refreshAvatarToken: added 2026-09-14. This is the one operation that deliberately accepts an already-expired credential (within its grace window — see refreshAvatarToken), so the rate limit is the only thing capping brute-force attempts against the token signature. One session legitimately needs about one refresh per hour, so ten per minute leaves very large headroom. Keyed per client IP rather than per tenant on purpose: a tenant-keyed bucket would let one abusive caller lock that tenant’s real embeds out of refreshing at all.

OperationLimitWindow
embed (text embedding query)10 requestsper 60 seconds, per client IP
requestKnowledgeDocumentUpload (step 1 of document upload)10 requestsper 60 seconds, per client IP
ingestDocumentFromUrl10 requestsper 60 seconds, per client IP

embed also caps texts at 100 entries per call. The embeddings limit is documented in context at Embeddings Integration.

Example request against a throttled operation:

Terminal window
curl -X POST https://api.wetel.dev/graphql \
-H "Content-Type: application/json" \
-H "X-Api-Key: <key>" \
-H "x-huat-platform: customer" \
-d '{"query":"query { embed(texts: [\"hello\"]) { vectors } }"}'
OperationLimitWindow
createCustomAction10 requestsper 60 seconds, per client IP
updateCustomAction10 requestsper 60 seconds, per client IP
deleteCustomAction10 requestsper 60 seconds, per client IP
OperationLimitWindow
aiGenerateWorkflow (LLM-assisted workflow graph generation)5 requestsper 60 seconds, per client IP
generateWorkflowDiff (LLM-assisted incremental edit)20 requestsper 60 seconds, per client IP

aiGenerateWorkflow is tighter than the others because each call triggers a full-graph LLM generation, not a simple CRUD write. generateWorkflowDiff is looser because it’s designed for an interactive co-pilot loop.

Added 2026-09-21.

OperationLimitWindow
runWorkflowTask60 requestsper 60 seconds, per client IP

runWorkflowTask can fan out into LLM calls and outbound partner requests, so an unthrottled endpoint would let anyone holding a leaked API key inflate a tenant’s bill (and hammer a partner’s API) — the same reasoning as sdkStart. The ceiling is deliberately looser than sdkStart’s 30/min because a machine orchestrator legitimately bursts (a queue drain, a retry sweep) where a human-driven embed does not. Keyed per client IP, like everything else here: a tenant-keyed bucket would let one abusive caller lock a tenant’s real orchestrator out of its own endpoint.

OperationLimitWindow
generateText10 requestsper 60 seconds, per client IP
startTextGeneration10 requestsper 60 seconds, per client IP

See LLM API for the request shapes (including the 4,000-character prompt cap).

OperationLimitWindow
testLlmProvider10 requestsper 60 seconds, per client IP
transcribeSpeech10 requestsper 60 seconds, per client IP

Added 2026-09-08 (see the changelog).

OperationLimitWindow
login10 requestsper 60 seconds, per client IP
loginWithWebbyxOne10 requestsper 60 seconds, per client IP
register5 requestsper 60 seconds, per client IP
isRegisterable5 requestsper 60 seconds, per client IP
refreshToken20 requestsper 60 seconds, per client IP
generateOTP3 requestsper 5 minutes, per client IP
validateSecuredToken5 requestsper 60 seconds, per client IP
forgotPasswordWithOTP5 requestsper 15 minutes, per client IP
resetUserPasswordWithUrl5 requestsper 15 minutes, per client IP

Avatar service (TTS / STT / avatar sessions)

Section titled “Avatar service (TTS / STT / avatar sessions)”

The avatar service’s REST endpoints (POST /tts, POST /tts/google, POST /stt, POST /avatar-session) carry their own throttles, separate from the GraphQL API above. Exact limits and request/response shapes are documented at Avatar Service REST Reference — not repeated here to avoid the two pages drifting out of sync.

Added 2026-09-17: each of those four routes is now governed by two independent limits that must both pass — a per-client-IP ceiling (unchanged, same numbers as before) and a new, higher per-tenant ceiling shared across every caller authenticated with that tenant’s avatar tokens. An unauthenticated or invalid-token request is governed by the IP limit alone; the tenant limit only ever applies once a valid avatarToken resolves a tenant. See the REST reference page for the exact numbers per route.

These apply to every request regardless of rate:

  • Query depth ≤ 7 and query complexity ≤ 50 — see Request limits.
  • sendMessage / sdkSendMessage text ≤ 10,000 characters — rejected, not truncated.
  • ingestDocument inline text ≤ 500,000 characters; uploaded files ≤ 20 MB, PDF, DOCX, Markdown, CSV, or XLSX (Markdown/CSV/XLSX support added 2026-09-17 — see Knowledge Base (RAG): File upload).

The following core session operations have no enforced rate limit as of this writing:

  • sdkSendMessage
  • sdkEndSession
  • sendMessage, startSession, endSession

Any other GraphQL operation not listed in the tables above is also currently unthrottled.

This is a deliberate current state, not a guarantee. Treat anything not explicitly listed on this page as subject to change without notice, and design your integration (including any headless / channel-connector integration) with your own backoff and retry handling regardless of whether a limit is currently enforced server-side — especially for any integration that fans a single external event (e.g. a busy group chat) into many sdkSendMessage calls in a short window.