Developers menu

Errors

Branch on the status first, then on code. Retry only what the table marks retry: a 429 after Retry-After, a 5xx with backoff. Everything else needs a change on your side.

The shape

ProductsBody
LIVE, ORDERS{ "error": { "code": "<code>", "message": "<words>" } }The levels API, the Orders API and the POSITIONS API. Extra fields ride beside code where a table names them (retry_after_s, oldest, pricing, live).
LAB{ "error": "<words>" }The LAB API answers with the status and a sentence; extra fields beside it (buy, holder, refunded).
GEO{ "error": "<words>" }The Geo API, the same way.

The levels API's levels answers 200 for the whole call; a symbol that fails carries its own error object (unknown_symbol, no_data, no_basis, contract_not_live) and the others still answer.

A platform that cannot read an HTTP status adds errors=200 to a levels API call: an error then answers 200 with the same body and the real status in X-FirmTape-Status.

Every code

StatusCodeRetry?ProductsMeaningWhat to do
400missing_symnoLIVENo sym was given.Pass sym, one symbol or a comma list.
400too_many_symbolsnoLIVEMore symbols than the call takes (20 a levels call, 8 a levels string).Split the list over two calls.
400bad_booknoLIVEbook is not vol or oi.Send book=vol or book=oi.
400bad_gnoLIVEg is not a whole number from 0 to 30.Send g between 0 and 30.
400bad_daynoLIVE, ORDERSday is not YYYY-MM-DD.Send the ET trading day as YYYY-MM-DD.
400bad_timenoLIVE, ORDERStime (levels API, 09:31 to 15:59) or t (POSITIONS) is not an ET minute HH:MM of the session.Send a minute of the session.
400not_finishednoLIVEA past session was asked for with today's date or later.Leave day out for today.
400spx_onlynoLIVEThe expected move is measured for SPX only.Send sym=SPX or leave it out.
400bad_jsonnoORDERSThe body is not JSON.Send Content-Type: application/json and a JSON object.
400bad_opnoORDERSop is not add, update or remove.Send one of the three.
400invalidnoORDERSThe position cannot be checked as sent; message says what to fix, in words.Correct the field the message names.
401no_keynoLIVE, ORDERSNo key was sent (Orders: no key, or one that is unknown or revoked).Send Authorization: Bearer <key> with a key of the product's scope.
401bad_keynoLIVEThe key is unknown or revoked.Make a new key on Account, Integrations.
403live_requirednoLIVEThe key is real; its account holds no active LIVE plan.Start or renew LIVE; pricing names the page.
403history_too_oldnoLIVEThe day is older than 90 days and the account holds no DATASET licence.Ask for a day from oldest on, or add the DATASET licence.
403plannoORDERSThe key is real; the account is not on the Orders API or Team plan.Move to the Orders API or Team plan.
404not_foundnoLIVE, ORDERSNo such endpoint (levels API), or no position with this id on this account (POSITIONS).Check the path or the id.
404no_routenoORDERSNo such endpoint under /orders/api.Use day, latest or sessions.
404unknown_symbolnoLIVEFirmTape has no book for that symbol.Pick one from GET /api/v1/symbols.
404no_datayesLIVENo reading for that symbol or day yet (before the first book of a session, or a day not in the archive).Ask again after next_update_s, or pick another day.
404no_basisyesLIVENo ES, NQ or RTY basis measured for that day yet; the index levels exist, the offset does not.Ask the index (SPX, NDX, RUT) or wait for the first basis pass.
404contract_not_livenoLIVEThat dated futures contract is not measured that day; live lists the ones that are.Ask the front contract or one named in live.
405method_not_allowednoLIVEThe levels API answers GET and HEAD only.Send a GET.
405methodnoORDERSThe POSITIONS API takes GET or POST.Send a GET or a POST.
429rate_limitedyesLIVEMore than 120 requests in a minute on one key.Wait Retry-After seconds; poll with If-None-Match, a 304 is free.
429too_many_placesnoLIVEA live key answered from 3 client addresses this hour; a fourth is refused while the others keep working.Make one key per machine.
429rateyesORDERSThe account's calls for the day are spent.Wait for midnight ET, when the count resets.
500internalyesLIVEAn error on FirmTape's side.Retry with backoff; write to support if it lasts.
503unavailableyesLIVEThe account store did not answer while the key was checked.Retry shortly.
401noLABNo key, or an unknown or revoked one.Send a lab key.
402noLABNo credits: {"error": "no credits", "buy": "lab"}. Developing an idea also needs a positive balance.Buy credits on the LAB page.
404noLABNo such idea or job, or not this account's.Check the id.
409noLABAnother idea holds the conveyor (holder names it), or a step came out of order.Finish or drop the holder; run the steps in order.
422noLABThe rule could not be compiled or the engine refused it (the credit is refunded).Change the rule.
502yesLABThe engine failed (the credit is refunded).Retry.
400noGEOA parameter is wrong; no call is counted.Fix the parameter error names.
401noGEONo key, an unknown key or a revoked one.Send a geo key.
403noGEONo active Geo API or Team plan, or a key beyond the plan's key count.Check the plan on the account page.
429yesGEOThe month's calls are used.Wait for Retry-After, the start of the next UTC month.

The single error envelope for every API is planned.

Measurements of dealer positioning, never a forecast or a trade call. This page is built from FirmTape's public contract, the same files the OpenAPI document is built from; the tests hold them against the route code. Markdown: /docs/developers/errors.md.