TraktorAPI
Get API key

Plans and limits

Each plan's limits, and how the API meters requests and stream units against them.

Every key belongs to an account on a plan, and the plan sets how fast and how much the account may ask.

Plans

The table is read live from GET /v1/plans, which takes no key.

LimitFreePro
Price$0 a month$99 a month
Requests30 a minute600 a minute
Burst30600
REST units20,000 a month5,000,000 a month
Stream units60,000 a month1,000,000 a month
History60 min24 h
Sockets110
Subscriptions per socket250
Events delivered5 a second300 a second
Event burst251,500
Frames you send5 a second20 a second
Addresses per list1050
Replay windowNone: cannot resume120 s
Filter score10120
API keys220

The per-minute budget counts requests: each costs one, whatever its units. The monthly allowance counts units.

Stream units, per key and clock hour: ⌈connection seconds ÷ 60⌉ + ⌈filter-score seconds ÷ 60,000⌉ + ⌈events delivered ÷ 1,000⌉.

Upgrading

Pro is bought on the web, from the API tab of your Traktor profile, and only while that tab offers Upgrade to Pro: it opens Stripe Checkout, and the account moves to Pro once Stripe confirms the payment. An account Stripe bills changes its card, reads its invoices or cancels from Manage billing on the same tab, which opens Stripe's billing portal; a cancelled plan stays Pro until the period paid for ends. The Traktor app sells nothing.

Requests and units

Each route's cost in units is on its endpoint block. The per-minute budget and the monthly allowance belong to the account, so every key it holds draws on the same two. A 304 draws no units and still counts as a request. The alert, notification and Telegram routes draw no units; their per-account limit is on their endpoint blocks and under Every limit.

Limit headers

A metered route sets these headers on every answer to a request it admits, internal_error aside, and on a 429 from its budgets:

HeaderWhat it says
RateLimit-LimitThe per-minute budget, in requests.
RateLimit-RemainingRequests you can send now before the per-minute budget refuses one.
RateLimit-ResetSeconds until the per-minute budget is full again; on quota_exhausted, until the period's units return.
RateLimit-PolicyThe per-minute budget, its window and its burst. Its unit="rest-units" counts requests, not units.
X-Traktor-CostUnits the request drew: 0 when its budgets refused it or its units were refunded.
X-Traktor-Quota-RemainingUnits left this period; absent on a 429.
X-Traktor-PlanThe plan's id, as GET /v1/plans lists it.

A script in a browser can read every one but X-Traktor-Plan and RateLimit-Policy.

A refusal raised before admission carries none of these headers and draws on neither budget. One raised after admission counts against the per-minute budget, and its units come back: X-Traktor-Cost: 0. Where each refusal falls:

  • GET /v1/market and its views refuse every fault in the query before admission: a repeated key, the grammar's and paging's refusals, plan_forbids and route_not_found. What fails once the read starts comes after: filter_too_broad, data_unavailable, market_busy and market_fold_pending.

  • GET /v1/signals refuses a fault in its query before admission, and a cursor's refusals after: invalid_cursor, cursor_query_mismatch and cursor_expired.

  • An internal_error after admission gives its units back too, and its answer carries none of these headers.

When a budget runs out

  • 429 rate_limited: the per-minute budget is spent. Wait for Retry-After, then retry.

  • 429 quota_exhausted: the period's units are spent, or fewer remain than the request costs. details.resetsAt says when they return, and RateLimit-Reset counts down to it; waiting a minute will not help. The refusal still counts against the per-minute budget.

  • 503 rate_limit_unavailable: the limiter could not be asked. Retry after Retry-After.

Neither 429 draws units.

Stream units

The trade stream, and the market stream under a key, draw on the account's monthly allowance of stream units, counted per key and clock hour by the formula under the plans table. A keyed market socket's seconds open count as connection seconds, and each view it is sent as an event delivered. The count it is checked against is refreshed every 15 minutes, so it trails your use by up to that long. The trade stream checks it when you authenticate, when you resume with from, and every minute, the market stream before the upgrade and every minute, and each closes with 4006 quota_exhausted once the count passes the allowance.

Every limit

Each route's limits, as its endpoint block states them; routes with the same limits share a row. A route that takes an API key also draws on its account's per-minute budget and units, above.

RoutesLimits
GET /v1/plans
  • Requests, shared with GET /v1/meta/filters: 60 a minute, per IP
GET /v1/meta/filters
  • Requests, shared with GET /v1/plans: 60 a minute, per IP
GET /v1/public/market
  • Requests: 120 a minute, per IP
  • Reads waiting on a build: 64 at once, per server process
  • Reads waiting on a build: 8 at once, per IP
  • Reads with a sign-in, once enforced, every /v1/public/ route together: 1,000 a minute by default, per account
GET /v1/public/search
  • Searches: 60 a minute, per IP
  • Token directory lookups: 10 a minute, per IP
  • Searches building: 16 at once, per server process
  • Reads with a sign-in, once enforced, every /v1/public/ route together: 1,000 a minute by default, per account
GET /v1/stream/position
  • Invalid keys: 30 a minute, per IP
  • Trades the stream retains: 200,000 entries by default, per server process
GET /v1/usage, GET /v1/market/summary, GET /v1/market/tokens, GET /v1/market/series, GET /v1/market/wallets, GET /v1/tokens/{chain}/{address}, GET /v1/tokens/{chain}/{address}/signals, GET /v1/traders/directory, GET /v1/traders/{wallet}, GET /v1/traders/{wallet}/portfolio, GET /v1/stocks, GET /v1/stocks/registry, GET /v1/signals/board
  • Invalid keys: 30 a minute, per IP
GET /v1/market, GET /v1/market/tape, GET /v1/market/rotation, GET /v1/market/whales
  • Invalid keys: 30 a minute, per IP
  • Wallets a balance floor may select: 5,000 wallets, per request
GET /v1/signals
  • Invalid keys: 30 a minute, per IP
  • Events examined: 10,000 rows, per request
  • Cursor lifetime: 24 hours, per request
  • Newest arrivals an ascending page holds back: 15 seconds by default, per request
GET /v1/leaderboard
  • Invalid keys: 30 a minute, per IP
  • Accounts listed: 1,000 rows, per request
GET /v1/search
  • Invalid keys: 30 a minute, per IP
  • Token directory lookups on each server: 10 a minute, per account
  • Searches building: 4 at once, per account
POST /v1/browser-sessions/exchange
  • Exchanges: 10 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Session lifetime: 12 hours, per request
  • Live sessions: 10 kept; the oldest is revoked, per account
GET /v1/browser-sessions/current, DELETE /v1/browser-sessions/current, GET /v1/alerts, GET /v1/alerts/{id}, PATCH /v1/alerts/{id}, DELETE /v1/alerts/{id}, POST /v1/alerts/{id}/duplicate, GET /v1/notifications/unread-count, POST /v1/notifications/read, GET /v1/webhooks, DELETE /v1/webhooks/{id}, GET /v1/telegram/links, DELETE /v1/telegram/links/{chatId}
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
POST /v1/alerts
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Alerts: 100 kept, per account
POST /v1/alerts/{id}/test
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Alert tests: 6 a minute, a burst of 3, per account
POST /v1/alerts/preview
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Alert tests: 6 a minute, a burst of 3, shared with testing a saved alert, per account
GET /v1/notifications
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Detailed notifications: 300 a clock hour, per account
  • Kept for: 90 days, per account
POST /v1/webhooks
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Webhooks: 3 kept, per account
POST /v1/webhooks/{id}/test
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Webhook tests: 6 a minute, a burst of 3, per account
POST /v1/telegram/link-codes
  • Requests: 120 a minute, per account
  • Session checks: 120 a minute, per IP
  • Invalid keys: 30 a minute, per IP
  • Code lifetime: 10 minutes, per request
  • Live codes: 1 at once, per account
WS /v1/stream
  • Sockets not yet authenticated: 10 at once, per IP
  • Sockets not yet authenticated: 500 at once, per server process
  • Frames before auth: 5 frames, per connection
  • Time to finish auth: 5 seconds, per connection
  • Frame size before auth: 4,096 bytes, per connection
  • Frame you send: 65,536 bytes, per connection
  • Refused frames before close 4007: 100 in 10 seconds, per connection
  • Events queued: 4,096 events, per subscription
  • Unread buffer before close 4008: 30 seconds, per connection
  • Invalid keys: 30 a minute, per IP
  • Stream-unit count refreshed every: 15 minutes, per server process
WS /v1/market/stream
  • Connections without a key: 8 at once, per IP
  • Queries your connections without a key read: 32 at once by default, per IP
  • Connections: 256 at once, per server process
  • Subscriptions: 16 at once, per connection
  • Commands: 60 in 10 seconds, per connection
  • Frame you send: 16,384 bytes, per connection
  • Openings with a sign-in, once enforced: 60 a minute by default, per account
  • Invalid keys: 30 a minute, per IP
  • Stream-unit count refreshed every: 15 minutes, per server process

Every per-IP limit counts an IPv6 caller by its /64.

The per-IP limits of GET /v1/public/market and GET /v1/public/search, the market stream's keyless connections and the trade stream's sockets not yet authenticated are counted by each API server on its own, and the API runs on more than one, so a client past one of those limits can still be answered by a server whose count is below it. Each server refuses an IP once its own count passes the limit, so keep to the number in the table. Every other per-IP limit, invalid keys included, and every per-account one, is counted across all of them.

Those two reads count an IP's requests in a minute that starts at its first one, not a rolling minute, so up to twice the limit can be answered across the turn of a minute. Each server counts at most 10,000 IPs on each of them; while it holds that many, a request from an IP it is not counting yet takes the place of the IP whose minute started first, which starts a new minute at its next request.

Going past "Invalid keys" never answers 429: the refusal stays 401 invalid_key, even for a valid key the server has to look up again, until the budget refills (When a key is refused).

    Plans and limits · Traktor API