TraktorAPI
Get API key

Errors

Every error code, over HTTP and on both sockets, with the shape each arrives in.

An error carries a stable code, and the code is the only thing to branch on.

The error envelope

Every REST route answers an error with an HTTP status and this body, except the routes the next section names:

{
  "error": {
    "code": "invalid_parameter",
    "message": "polygon is not a chain",
    "requestId": "req_01m40t5ceg7k2q9xv4ra",
    "details": { "parameter": "chains", "value": "polygon" },
    "docs": "https://traktor.fun/docs/errors#invalid_parameter"
  }
}
  • code names the failure; the tables below list every one.

  • message is for a person, and may change.

  • requestId is also the X-Request-Id header. Send your own X-Request-Id of 1 to 128 letters, digits, _ and -, and the answer carries it in both places.

  • details holds the code's specifics, such as parameter, value, conflictsWith or allowed, and is {} when there are none.

  • docs is the code's row on this page, https://traktor.fun/docs/errors#<code>.

An error is never a 200.

Where the envelope is shorter

GET /v1/public/market and GET /v1/public/search answer an error with code and message only, and no requestId, details or docs:

{ "error": { "code": "invalid_query", "message": "This market query is not supported." } }

Stripe's webhook, and a path outside /v1/ that no route serves, answer the same shape.

A request body over 2 MiB, to any path, is refused with 413 and no body before any route reads it: the status is the answer. A body under that but over a route's own limit gets body_too_large.

The sockets refuse an upgrade in shapes of their own; each socket's endpoint block lists its refusals.

  • The market stream refuses a handshake that does not offer traktor.market.v1, or that carries a query string, with 400 and { "error": { "code": "invalid_market_handshake", "protocol": "traktor.market.v1" } }, which has no message. Under a key, its refusals carry an error holding code, message and, where there are any, details, at the status its endpoint block lists: a refused key, a spent allowance, a full set of the account's sockets, and try_later at 503, with Retry-After, when the key could not be checked. Its 429, and its 400 for a request that offers the subprotocol, has no query string and is not an upgrade, have no body: the status is the answer.

  • The trade stream's refusals hold the code as a string, such as { "error": "try_later" }. Its refusal of an unsupported subprotocol adds supported, the subprotocols it speaks.

HTTP codes

CodeStatusMeaningWhat to do
invalid_parameter400A parameter's value is not one this route accepts, a chain or platform is outside the vocabulary (details.value), or one filter key came under both its spellings (details.conflictsWith); details.parameter names it.Fix the value, or send one spelling; details says what was expected.
unknown_parameter400The query names a key this route does not read.Remove it; details.parameter names it. On the market routes details.accepts lists the keys they read, and a token-paging key sent without views=tokens carries details.requires instead.
screen_conflict400A floor sits above its own ceiling, such as minUsd over maxUsd.Swap or correct the two bounds.
window_out_of_range400windowMinutes is not a window this route serves.Use a window from the route's parameter table.
limit_out_of_range400limit is not an integer from 1 to the route's maximum.Send an integer from 1 to details.limit.
too_many_addresses400A list names more addresses or tickers than the grammar allows.Split the list across requests or subscriptions; in an alert rule, across alerts.
filter_version_unsupported400The filter declares a grammar version this API does not speak.Send v=1, or leave v out.
invalid_cursor400The cursor is malformed, or its signature does not match.Start again without a cursor.
cursor_query_mismatch400The cursor was minted for another filter or another order.Send the filter and order the cursor came from.
key_in_query400A credential-shaped query parameter was sent, such as key, api_key or token.Send the key in Authorization: Bearer, and rotate it: it may now be in proxy logs.
invalid_api_key400The body's apiKey is missing or is not a string of 1 to 256 characters.Send { "apiKey": "tk_live_…" }.
invalid_json400The body is not valid JSON.Send a JSON object.
invalid_body400The body is JSON but not an object.Send a JSON object.
unknown_field400The body carries a field this route does not take; details.pointer names it.Remove the field.
invalid_alert_name400The alert's name is not a string of 1 to 80 characters.Send a shorter, non-empty name.
invalid_alert_enabled400enabled is not a boolean.Send true or false.
invalid_alert_patch400The PATCH names none of name, rule or enabled; one that repeats their current values is accepted and bumps the revision.Send name, rule or enabled with the revision.
invalid_alert_revision400revision is not a positive integer.Send the revision you last read.
alert_rule_unsupported400The stored rule uses a window, field or match alerts no longer support, so it cannot be enabled as it is.Edit the rule, then enable it.
invalid_notification_ids400ids must hold 1 to 100 notification ids.Send between 1 and 100 ids, or all: true.
invalid_notification_bound400through must be a notification's createdAt and id, and goes only with all: true.Send through from a listed notification, beside all: true.
invalid_webhook_url400url is not an https:// address on port 443, without credentials, whose host is on the public internet.Send the endpoint's public https URL.
invalid_unread_filter400unread is neither true nor false.Send unread=true, unread=false, or leave it out.
invalid_alert400alert is not an alert id.Send the id of one of the account's alerts, or leave it out.
duplicate_query_parameter400A query parameter appears more than once; details.parameter names it.Send each parameter once, several values comma-separated in one: ?chains=bnb,base.
unknown_query_parameter400The query names a parameter this route does not read; details.parameter names it.Remove the parameter.
invalid_limit400limit is not an integer from 1 to 100.Send a limit from 1 to 100.
invalid_query400The public market or search query is malformed or names a key its resource does not take.Fix the query against the resource's keys.
invalid_rule400The alert rule, or a part of it, is not an object; details.pointer names it.Fix that part so it is a JSON object.
invalid_scope400The rule's scope names something the alert grammar does not take; details.pointer names it.Fix the scope against GET /v1/alert-capabilities.
invalid_condition400A condition is malformed: a missing metric, an unsupported operator, a bound that is not a number.Fix the condition at details.pointer.
unknown_metric400A condition names a metric the alert grammar does not know.Use a metric from GET /v1/alert-capabilities.
unknown_signal400A signal condition names a signal the feed does not emit.Use a signal from GET /v1/alert-capabilities.
metric_source_mismatch400The metric exists, but not on this rule's source.Use a metric the rule's source offers.
invalid_trigger400The trigger's mode, cooldown or hysteresis is outside what alerts support.Fix the trigger at details.pointer.
invalid_source400source is not flow, token_window or signal.Send one of the three sources.
invalid_window400The rule's windowMinutes is not an alert window, or a signal rule names one.Use a window from GET /v1/alert-capabilities; leave it out on a signal rule.
invalid_match400match needs op of all or any and at least one condition, and a signal rule's all names one signal.Fix match.
alert_version_unsupported400The rule's v is missing or is not 1.Send v: 1.
too_many_conditions400The rule holds more conditions than alerts take; details.limit says how many.Split the rule into two alerts.
missing_credentials401No bearer token was sent.Send Authorization: Bearer $TRAKTOR_API_KEY.
invalid_key401The key is malformed or unknown (the two answer alike), or it is valid but the caller's IP has spent its refused-key budget and the key is not cached yet.Check the key; if it is right, wait a minute and retry.
key_revoked401The key was revoked or has expired, or its account was closed.Use another key.
session_required401This route takes a browser session (trk_session_…), and another credential was sent.Exchange a key at POST /v1/browser-sessions/exchange and send that session.
session_expired401The browser session is unknown, expired or revoked, or what opened it is gone: its key was revoked or expired, its Telegram unlinked, or its account made inactive.Exchange a key for a new session.
sign_in_required401The Traktor sign-in is unknown, expired or revoked, or its account is suspended or closed. While market data needs a sign-in, which it does not yet, a public market read or a keyless market socket with no sign-in answers it too.Sign in to Traktor again; a suspended or closed account stays refused. By code, read the market with an API key on the paid routes.
subscription_inactive402The account is suspended.Nothing in the API lifts a suspension.
plan_forbids403The request reaches further back than the plan reads; details.maxHistoryMinutes says how far it can.Shorten windowMinutes, or move to a plan with more history.
account_inactive403The account is suspended or closed, so it cannot open a browser session.Nothing in the API lifts a suspension or a closure.
web_sign_in_required403This credential may not do this: only Traktor's own sign-in on the web may link a group, manage API keys, read the account's usage or billing, open checkout or the billing portal, or connect a Telegram, and only Traktor's own sign-in, on the web or in the app, may read or change the account's saved tokens or the phones its alerts are pushed to.Do it from traktor.fun or the Traktor app, signed in.
insufficient_scope403An AI agent's connection was not granted the scope this route reads, such as market:read.Connect the agent again and grant the scope.
route_not_found404No route lives at this path.Check the path against the reference.
alert_not_found404No alert with this id on your account.List your alerts for their ids.
webhook_not_found404No webhook with this id on your account.List your webhooks for their ids.
method_not_allowed405The route does not serve this method; the Allow header lists those it does, except on the keyless public market and search routes, which send none and read with GET and HEAD.Use a method the route serves.
alert_limit_reached409The account holds as many alerts as it may keep.Delete an alert first.
alert_revision_conflict409The alert changed since you read it.Read it again and resend with its new revision.
alert_once_completed409This one-shot alert has already fired.Duplicate it, or change its rule to arm it again.
webhook_limit_reached409The account holds as many webhooks as it may keep.Delete a webhook first.
cursor_expired410The cursor is past its life: details.reason is age.Start again without a cursor.
body_too_large413The body is over the route's size limit; details.maxBytes says it.Send a smaller body.
filter_too_broad422A balance floor would select too many wallets for the views to read.Raise the floor: minWalletBalanceUsd on the metered routes, where details holds the numbers and details.parameter names it; minBalance on the public market.
rate_limited429A budget is spent: a per-minute one (the plan's, an IP's or the account's), or, on the keyless public market and search, the server's cap on reads or searches in progress at once or on the IPs it tracks.Wait for Retry-After, then retry.
quota_exhausted429The month's REST units are spent, or fewer remain than this request costs; waiting within the period will not help.Wait for details.resetsAt, or move to a larger plan.
preview_rate_limited429Too many alert tests in a short time.Wait for Retry-After, then retry.
stream_capacity429The public market gateway is at capacity.Retry after Retry-After.
internal_error500Something failed on Traktor's side.Retry; quote requestId if it persists.
data_unavailable503The data behind the answer is warming up or could not be built; on the metered routes details.reason says which.Retry after Retry-After.
market_busy503The server is already holding as many market reads waiting on a build, or running as many builds, as it allows.Retry shortly.
market_fold_pending503A committed batch of trades is still being folded into the market read.Retry shortly, backing off if it persists.
market_warming503The public market view has not been built yet.Retry after Retry-After.
market_unavailable503The public market read failed, or its resource is switched off on this service.Retry after Retry-After; a switched-off resource sends none, and a retry will not change that.
server_draining503The server that took this public market read is shutting down for an update, and it closes the connection with this answer.Retry after Retry-After, on a new connection.
rate_limit_unavailable503The rate limiter could not be asked.Retry after Retry-After.
sign_in_unavailable503While market data needs a sign-in, the sign-in could not be checked: a store behind the check did not answer.Retry after Retry-After.
telegram_not_configured503This service runs without a Telegram bot.Telegram delivery is unavailable; there is nothing to change on your side.

Codes Traktor's own apps answer with

These come only from the profile's key routes, Traktor's Telegram Mini App, the alert worker and Stripe's webhook, so a request made with an API key never meets them.

CodeStatusMeaningWhere it comes from
invalid_alert_batch400An alert worker batch failed its own validation.Raised inside the alert worker, which no client calls.
invalid_saved_tokens400add or remove is not a list of at most 200 strings; details.pointer names it.Only Traktor's own site and app call the route that raises it, to keep the account's saved tokens in step.
invalid_followed_traders400add or remove is not a list of at most 100 strings, or merge is not a boolean; details.pointer names it.Only Traktor's own site and app call the route that raises it, to keep the traders the account follows in step.
invalid_push_token400token is not an Expo push token.Only the Traktor app calls the routes that raise it, to turn alert push notifications on or off for a phone.
invalid_push_platform400platform is neither ios nor android.Only the Traktor app calls the routes that raise it, to turn alert push notifications on or off for a phone.
invalid_push_install400install is not the key an install of the app makes for itself: 64 lowercase hex characters.Only the Traktor app calls the routes that raise it, to turn alert push notifications on or off for a phone.
invalid_key_name400A key's name is not a string of 1 to 64 characters, or it holds a control character.Only the API tab on traktor.fun calls the routes that raise it.
invalid_settings400A bot setting is outside what the bot reads, or the change names none.Only Traktor's Telegram Mini App calls the routes that raise it.
invalid_init_data400, 401Telegram's signed init data is missing, expired or not signed for this bot.Only Traktor's Telegram Mini App calls the routes that raise it.
invalid_agent_client400client_id names no client registered at POST /oauth/register.Only Traktor's consent page for connecting an AI agent, traktor.fun/connect, calls the route that raises it.
invalid_agent_redirect400redirect_uri is not one the client registered, so the page sends nobody there.Only Traktor's consent page for connecting an AI agent, traktor.fun/connect, calls the route that raises it.
invalid_agent_request400The authorization request is malformed; details.error is the OAuth error the page sends back to the agent, at details.redirectTo.Only Traktor's consent page for connecting an AI agent, traktor.fun/connect, calls the route that raises it.
invalid_signature400The Stripe-Signature header is missing, malformed, outside its time tolerance, or does not verify against the endpoint's signing secret.Raised only by Stripe's subscription webhook, POST /v1/stripe/webhook, which no client calls.
telegram_not_linked403This Telegram is not linked to a Traktor account.Only Traktor's Telegram Mini App calls the routes that raise it.
telegram_reader_not_found404The bot has no chat with this Telegram user yet.Only Traktor's Telegram Mini App calls the routes that raise it.
agent_connection_not_found404No live connection with this id on the account.Only the connected apps list in Traktor's profile calls the routes that raise it.
key_not_found404No live key with this id on the account.Only the API tab on traktor.fun calls the routes that raise it.
push_device_not_found404No phone with this id takes the account's push notifications.Only the Traktor app calls the routes that raise it, to turn alert push notifications on or off for a phone.
alert_checkpoint_conflict409The worker's checkpoint moved under a batch.Raised inside the alert worker, which no client calls.
alert_continuation_pending409The worker has a fan-out to finish first.Raised inside the alert worker, which no client calls.
key_name_taken409A live key on the account already has this name.Only the API tab on traktor.fun calls the routes that raise it.
agent_limit_reached409The account holds as many connected apps as it may, ten.Only Traktor's consent page for connecting an AI agent, traktor.fun/connect, calls the route that raises it.
key_limit_reached409The account holds as many keys as its plan allows.Only the API tab on traktor.fun calls the routes that raise it.
already_subscribed409The account is on a paid plan or holds a subscription, so checkout has nothing to sell it.Only the API tab on traktor.fun calls the routes that raise it.
billing_not_started409The account has never been through checkout, so the billing portal has nothing to show.Only the API tab on traktor.fun calls the routes that raise it.
push_token_taken409Another account takes this phone's push notifications, and the request came from another install of the app than the one that turned them on.Only the Traktor app calls the routes that raise it, to turn alert push notifications on or off for a phone.
agent_connect_off503Connecting AI agents is switched off on this server.Only Traktor's consent page for connecting an AI agent, traktor.fun/connect, calls the route that raises it.
billing_unavailable503Checkout and the billing portal are not open on this server, or Stripe could not be reached.Only the API tab on traktor.fun calls the routes that raise it.
push_not_configured503This server pushes no alerts to phones yet.Only the Traktor app calls the routes that raise it, to turn alert push notifications on or off for a phone.
alert_evaluation_batch_too_large503A batch would evaluate more rules than the worker's safety bound.Raised inside the alert worker, which no client calls.

Stream codes

An error frame on the stream answers one frame and never closes the socket. A fault that closes the socket is a close code instead, listed under close codes.

CodeRetryableMeaningWhat to do
bad_jsonThe frame is not JSON.Send one JSON object per frame.
bad_frameThe frame is not a JSON object, or carries an unknown field, a bad value, or a from this service did not mint or one past the newest event in the feed; detail.pointer names the field where there is one.Fix the frame; for /from, subscribe again without it.
missing_idThe frame has no id of 1 to 64 characters from A-Z a-z 0-9 _ . : -.Give every frame an id.
unknown_opThe op is not one of the client ops.Use a client op.
not_authenticatedretryableA frame other than auth or bye arrived before auth.Send auth first.
already_authenticatedauth arrived on a connection that already has an account.Send auth once per connection.
unknown_subunsubscribe named a subscription the connection does not hold; nothing was removed.List subscriptions with subs.
sub_existsA subscription with this name is already open.Choose another name, or unsubscribe first.
sub_limitThe connection holds as many subscriptions as the plan allows; detail has limit and inUse.Close a subscription, or open another socket.
filter_invalidThe filter fails the flow grammar: an unknown field, a value out of bounds or outside its vocabulary, one key under both its spellings, or a minimum above its maximum; detail.pointer names the field, except that a minimum above its maximum leaves it a bare /filter/.Fix the filter; send one spelling of each key.
filter_too_largeA tokens or wallets list within the grammar's bound is longer than the plan's wsAllowListMax; detail has limit and got.Shorten the list.
filter_too_broadThe connection's filters would score past the plan's wsFilterScoreMax; detail has score, inUse and limit.Narrow a filter, or close a subscription.
channel_deniedThe frame asks for a channel other than flows.Leave channel out, or send flows.
rate_limitedretryableFrames arrived faster than the plan's inbound rate, or while a burst of them was still waiting on a key check or a replay; detail.retryAfterMs says when to send again.Send fewer frames; persistent flooding closes the socket with 4007.
internalretryableThe server failed while handling the frame.Retry the frame; reconnect if it repeats.

Market stream codes

An error frame on the market stream answers one command, with its code and, when the command carried a valid one, its id, except a stream_capacity naming a subscription the server closed to make room, which answers none. The socket's closes are listed under close codes.

CodeRetryableMeaningWhat to do
bad_frameThe frame is not a JSON object, names an op this socket does not have, or carries a field its op does not take.Send { op, id, … } with that op's fields only.
invalid_idid is not 1 to 64 characters from A-Z a-z 0-9 _ . : -.Give the frame a valid id.
unknown_subscriptionunsubscribe named a subscription the connection does not hold.Check the sub.
subscription_existsA subscription with this id is already open.Use a new id.
subscription_limitThe connection holds as many subscriptions as it may, the server's cap or under a key the plan's. Without a key, also: your IP's connections without a key already read their share of the server's queries, and this one would count toward it.Unsubscribe from one first.
invalid_queryThe query is not a { resource, params } object, or names a resource, a key or a value the public market does not take, or repeats a key. Under a key it is also a resource the paid API does not read, or a chain, app, DEX signal, launchpad or signal type name the grammar does not know, which the keyless socket drops. While market data needs a sign-in, which it does not yet, a socket with no API key, ticket or sign-in is also refused anything but the front door's three reads (FRONT_DOOR_MARKET_READS).Fix the query against the resource's keys.
market_unavailableThe resource is switched off on this service.Use another resource.
stream_capacityretryableThe gateway holds as many market queries as it can. Sent for a subscription you did not just open, it closed that subscription to make room for another reader's new query: your IP, or under a key your account, read at least as many queries as that reader allowed: its whole share for an HTTP read, two for a metered REST read under a key, two more than another IP's or account's connection. A query only you read goes first; a query others read too is closed only when every reader of it reads that many, and then for every one of them.Retry shortly.
    Errors · Traktor API