API Rate Limits

Overview

ET Ducky enforces rate limits at two layers. Transport limits are applied by the API's built-in rate limiter, per policy, to groups of endpoints. Application limits are domain-specific caps (e.g. shell-command execution) enforced in service code. Exceeding either returns HTTP 429 Too Many Requests. All limits are partitioned (per IP, per organization, or per user+org as noted) so one tenant's traffic cannot consume another tenant's allowance.

Transport rate-limit policies

PolicyLimitWindowPartitionQueueApplies to
fixed100 requests1 minuteglobal10AI / analysis endpoints (e.g. Analysis, Data Explorer)
sliding200 requests5 minutes (5 segments)global20Endpoints on the sliding-window policy
discovery-per-ip10 requests1 minutesource IPnoneAnonymous agent discovery / registration-token endpoints (brute-force protection)
oob-commands-per-org60 requests1 minuteorganizationnoneOut-of-band gateway REST & command endpoints
contact-report-per-ip5 requests1 minutesource IPnonePublic contact form & status-page issue reporter

The rejection status for all policies is 429.

Application limits

LimitValueScope
Shell command execution30 commandsper hour, per user, per organization
AI query quotaplan-based monthly quotaper organization (resets each billing period)

The AI quota is a monthly quota, not a sliding rate limit — it resets per billing period rather than per time window. Exhaustion returns 429 (or 402 where a plan upgrade resolves it) with a descriptive message.

Response headers on 429

When a request is rejected for exceeding a transport limit, the API returns standard rate-limit headers so clients can back off correctly:

HeaderMeaning
Retry-AfterSeconds until the limited window resets.
X-RateLimit-LimitThe rejecting policy's permit limit.
X-RateLimit-Remaining0 — the request was just rejected.
X-RateLimit-ResetSeconds until reset (mirrors Retry-After).

These header names are exposed via CORS so cross-origin API clients can read them. They are emitted on 429 responses; the built-in limiter does not surface a per-request remaining count on successful responses.

Client guidance

On a 429, wait for the window to reset before retrying and respect the Retry-After header. The discovery, out-of-band, and contact policies have no queue, so excess requests are rejected immediately rather than delayed. Tenants on subdomains share their organization's partitioned allowances.