On this page
Rate Limits & Quotas
Artery resolves quota from the authenticated request's organization plan.
Each metered route is assigned a usage SKU such as api.request,
markets.read, portfolio.read, or pnl.read, and that SKU can have
per-minute and per-day limits.
API keys provide authentication and scopes; they do not select a separate monthly request tier. All keys in the same organization use the organization's effective plan quota.
Plan and SKU quotas
-1 in the plan configuration means unlimited. A dash means that the plan
does not set that window.
| Plan | api.request /min · /day | markets.read /min · /day | portfolio.read /min · /day | pnl.read /min · /day | ws.message /day | webhook.delivery /day |
|---|---|---|---|---|---|---|
free | 60 · 10,000 | 600 · 100,000 | 60 · 5,000 | 30 · 1,000 | 50,000 | 1,000 |
pro | 600 · 1,000,000 | 6,000 · 1,000,000 | 600 · 50,000 | 300 · 10,000 | 10,000,000 | 100,000 |
enterprise | 6,000 · unlimited | unlimited | unlimited | unlimited | unlimited | unlimited |
An organization can also have a subscription-level quota override. The override is merged on top of its plan per SKU and per window; this is how a custom enterprise contract can set explicit limits or mark a window unlimited.
The legacy rateLimitTier API-key field is deprecated and ignored for quota selection. Omit it
when creating keys. Use the organization's subscription plan as the source of truth.
Plans also gate features such as backtest, webhook.signing,
history.maxDays, and sso. A feature gate can reject a request even when
the relevant SKU still has quota remaining.
Response headers
Metered authenticated responses carry the effective SKU quota state:
httpX-Quota-Sku: pnl.read
X-Quota-Limit: 1000
X-Quota-Remaining: 999
X-Quota-Reset: 1780822653X-Quota-Reset is a Unix timestamp in seconds for the reported quota window.
When the effective window is unlimited, X-Quota-Limit and
X-Quota-Remaining report unlimited.
429 handling
When the effective SKU quota is exhausted:
httpHTTP/1.1 429 Too Many Requests
Retry-After: 60
X-Quota-Sku: pnl.read
X-Quota-Limit: 30
X-Quota-Remaining: 0
X-Quota-Reset: 1780822653
{
"error": {
"code": "quota_exceeded",
"message": "Quota exceeded for SKU 'pnl.read' (minute window: 30)",
"requestId": "req_..."
}
}Branch on error.code === "quota_exceeded". Retry-After is the number of
seconds to wait; X-Quota-Reset is the Unix-seconds reset timestamp.
WebSocket usage
Delivered WebSocket messages are metered as ws.message against the
organization plan. The stream gateway also limits a connection to 1,000 active
subscriptions; hitting that connection cap returns:
jsonc{ "type": "error", "error": "max 1000 subs/conn" }Upstream provider limits
Provider limits are independent of the organization's Artery quota. These
surface as code: upstream_rate_limited rather than quota_exceeded:
| Provider | Limit | Notes |
|---|---|---|
| Polymarket | ~600 req/min/IP | Cloudflare-level; aggressive |
| Kalshi | Token-bucket; 10 tokens/req | No Retry-After — Artery backs off automatically |
| Hyperliquid | 1200 req/min/IP for /info; 100 orders/sec/wallet | Trade-side is per master wallet |
Artery retries upstream_rate_limited on GET calls automatically —
see error handling.
See also
- Error code reference — 429 envelope details
- Rate limits concept — how plan quotas are applied
- Authentication — API keys and scopes