Skip to content
AM

Rate limits per surface

Rate limits are attached to individual platform surfaces. There is no source-backed universal per-tenant rate, burst multiplier, tier multiplier, or response-header set across all APIs.

Published limits

SurfaceScopeDefault limit
Commerce storefront, general routesClient IP and SDK key plus route class100 requests/minute at each layer
Commerce storefront, authentication routesClient IP and SDK key10 requests/minute at each layer
Reporting APIClient IP120 requests/minute
External-agent signupClient IP20 requests/hour
External-agent signupAuthenticated owner3 signups/day
Agentic Commerce, Core or unknown tierResolved request scope100/minute and 1,000/hour
Agentic Commerce, GrowthResolved request scope300/minute and 5,000/hour
Agentic Commerce, Scale, Enterprise, or PracticeResolved request scope1,000/minute and 20,000/hour

The reporting limit can be changed with REPORTING_RATE_LIMIT_PER_MINUTE. External-agent owner limits can be changed with EXTERNAL_AGENT_SIGNUP_DAILY_LIMIT. Agentic Commerce defaults can be changed with the AGENTIC_RATE_LIMIT_* configuration variables.

Shared per-IP limiter

Reporting and the Commerce storefront IP layer use shared/middleware.NewRateLimiter, an in-process sliding-window limiter. It keys on X-Forwarded-For when present and otherwise uses the request remote address.

When exhausted, it returns:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
{"error":"rate limit exceeded"}

The shared implementation does not emit X-RateLimit-Remaining or X-RateLimit-Reset.

Storefront SDK-key limiter

Commerce also limits each SDK key and route class. It uses a Redis fixed window when Redis is available and an in-memory sliding-window fallback otherwise.

An exhausted SDK-key budget returns 429 with error code sdk_key_rate_limited and a computed Retry-After. A Redis failure returns 503 with rate_limiter_unavailable rather than allowing the request without enforcement.

Both storefront layers apply, so a request must have capacity in its client-IP budget and its SDK-key budget.

GraphQL fields

GraphQL does not have one global request limit. Selected fields declare @rateLimit(max: ..., window: ...) in their schema. Examples include Accounting AI fields, Commerce mutations and Studio storefront builds.

Use the GraphQL operation reference for the exact directives on each current operation.

MCP actions

The public MCP runtime does not publish a global requests-per-second contract. Its policy can enforce a tenant’s daily T3-action budget; an exhausted budget is returned as INBLACK_RATE_LIMITED. See Tool errors for the MCP error shape.

Retry guidance

  1. Honor Retry-After when it is present.
  2. Apply exponential backoff with jitter when a surface does not provide an exact retry delay.
  3. Bound retries and preserve idempotency keys for writes.
  4. Treat 503 rate_limiter_unavailable as a transient infrastructure failure, not as available quota.