# Developers

> FirmTape's measurements from code: the levels API, the order ledger, POSITIONS, LAB, the archive, the dataset files and Geo, with keys, errors, limits, webhooks and MCP.

Source: https://firmtape.com/docs/developers

Read FirmTape's measurements from code: the live levels, the order ledger, your alerts as signed webhooks, the archive, LAB and Geo. Every reference page names the plan it needs and links back to the feature it serves.

Base URL https://firmtape.com. JSON over HTTPS. Times in ET. OpenAPI: https://firmtape.com/docs/developers/openapi.json

## Quickstart

1. Pick the product; each section below says which plan it needs. Finished sessions are free and need no key.
2. Make an API key on the account page, with the scope of that product. It is shown once.
3. Call it: `curl -H "Authorization: Bearer $FIRMTAPE_LIVE_KEY" "https://firmtape.com/api/v1/levels?sym=SPX,ES"`

## By product

### [LIVE: Levels API](https://firmtape.com/docs/developers/live)

FirmTape's levels as JSON, for chart plugins and scripts: the volume book's zero-gamma flip, call wall, put wall and net gamma, every second for SPX and ES and every five minutes for the tickers, NQ and RTY. Included in LIVE.

- [`GET /api/v1/levels`](https://firmtape.com/docs/developers/live/levels): Get levels
- [`GET /api/v1/gamma`](https://firmtape.com/docs/developers/live/gamma): Gamma by strike
- [`GET /api/v1/history`](https://firmtape.com/docs/developers/live/history): Level history of a day
- [`GET /api/v1/symbols`](https://firmtape.com/docs/developers/live/symbols): Every symbol
- [`GET /api/v1/expected_move`](https://firmtape.com/docs/developers/live/expected-move): Expected move and close odds
- [`GET /api/v1/levels.txt`](https://firmtape.com/docs/developers/live/levels-string): Levels string (FT1)
- [`GET /api/v1/bookmap.csv`](https://firmtape.com/docs/developers/live/bookmap-csv): Bookmap Cloud Notes sheet
- [`GET /api/v1/key`](https://firmtape.com/docs/developers/live/key): Check a key
- [Alert lines (session only)](https://firmtape.com/docs/developers/live/alert-lines)
- [Web push](https://firmtape.com/docs/developers/live/web-push)
- [Platform integrations](https://firmtape.com/docs/developers/live/integrations)
- [Webhook events](https://firmtape.com/docs/developers/live/events): flip_cross, wall_break, regime_change, wall_move, flip_move, level_near, price_alert, level_line, order, test

### [ORDERS: Orders API and POSITIONS API](https://firmtape.com/docs/developers/orders)

The order ledger and the POSITIONS check from code, with an `orders` key on the Orders API or Team plan. The same rows the ORDERS panel draws, and the same reading the POSITIONS panel shows.

- [`GET /orders/api/day`](https://firmtape.com/docs/developers/orders/day): One session's order ledger
- [`GET /orders/api/latest`](https://firmtape.com/docs/developers/orders/latest): The newest session's order ledger
- [`GET /orders/api/sessions`](https://firmtape.com/docs/developers/orders/sessions): Every day with a ledger
- [`GET /api/positions`](https://firmtape.com/docs/developers/orders/positions): Your positions
- [`POST /api/positions`](https://firmtape.com/docs/developers/orders/positions-change): Add, update or remove a position
- [`GET /api/positions/check`](https://firmtape.com/docs/developers/orders/positions-check): Check your positions at a minute
- [`GET /api/positions/track`](https://firmtape.com/docs/developers/orders/positions-track): A position's label track
- [`GET /api/positions/entries`](https://firmtape.com/docs/developers/orders/positions-entries): A position's entry log
- [Orders MCP server](https://firmtape.com/docs/developers/orders/mcp)
- [Webhook events](https://firmtape.com/docs/developers/orders/events): label_changed, opening_read, test

### [LAB: LAB API](https://firmtape.com/docs/developers/lab)

LAB from a script, with a `lab` key: the same conveyor the terminal drives, spending the same credits. Developing an idea is free; a backtest or an optimize pass is one credit, refunded on failure.

- [`POST /api/lab/chat`](https://firmtape.com/docs/developers/lab/chat): Develop or amend an idea
- [`POST /api/lab/run`](https://firmtape.com/docs/developers/lab/run): Backtest or optimize an idea
- [`GET /api/lab/state`](https://firmtape.com/docs/developers/lab/state): Ideas, conveyor and balance
- [`GET /api/lab/thread`](https://firmtape.com/docs/developers/lab/thread): An idea's chat thread
- [`POST /api/lab/idea`](https://firmtape.com/docs/developers/lab/idea): Desk actions on an idea
- [`GET /api/lab/vocabulary`](https://firmtape.com/docs/developers/lab/vocabulary): The LAB vocabulary
- [`POST /api/struct/run`](https://firmtape.com/docs/developers/lab/options-run): Test an options structure over the archive
- [`GET /api/struct/job`](https://firmtape.com/docs/developers/lab/options-job): Poll an options run
- [LAB over MCP](https://firmtape.com/docs/developers/lab/mcp)

### [REPLAY: Archive JSON and the free MCP server](https://firmtape.com/docs/developers/replay)

Every finished session is free: as JSON from the site with no key, and through the MCP server's free tools for an assistant.

- [`GET /api/days`](https://firmtape.com/docs/developers/replay/days): Every finished session
- [`GET /api/session/{day}`](https://firmtape.com/docs/developers/replay/session): One session's closing measurements
- [The free MCP server](https://firmtape.com/docs/developers/replay/mcp)

### [DATASET: Dataset files](https://firmtape.com/docs/developers/dataset)

The session archive as files: one gzipped JSON a finished day, minute series and per-strike ladders in all three books, a new day every evening. Every field's meaning, unit, book and first date is in the [data dictionary](https://firmtape.com/dataset/dictionary).

- [`GET /snapshots/{file}`](https://firmtape.com/docs/developers/dataset/files): A day file
- [The data dictionary](https://firmtape.com/docs/developers/dataset/dictionary)

### [GEO: Geo API](https://firmtape.com/docs/developers/geo)

Dated public records of world events, each with its source and time, over REST with a `geo` key, as signed webhooks and over MCP. The free JSON needs no key and covers 30 days. Context for a session, never a trading signal.

- [`GET /items`](https://firmtape.com/docs/developers/geo/free-items): Records, free
- [`GET /weeks`](https://firmtape.com/docs/developers/geo/free-weeks): Weeks with records, free
- [`GET /countries`](https://firmtape.com/docs/developers/geo/free-countries): Countries named, free
- [`GET /health`](https://firmtape.com/docs/developers/geo/free-sources): Feeds and their health, free
- [`GET /v1/items`](https://firmtape.com/docs/developers/geo/items): Records
- [`GET /v1/sources`](https://firmtape.com/docs/developers/geo/sources): Feeds
- [`GET /v1/usage`](https://firmtape.com/docs/developers/geo/usage): This month's usage
- [`GET /v1/export.csv`](https://firmtape.com/docs/developers/geo/export-csv): CSV export
- [Geo MCP server](https://firmtape.com/docs/developers/geo/mcp)
- [Webhook events](https://firmtape.com/docs/developers/geo/events): geo.record, geo.test

## API keys and scopes

One name, **API key**, for every key a program sends. A key carries a **scope**: the products it opens. The prefix names the scope, so a key pasted into a chart plugin is visibly not one that spends Lab credits. Send it as `Authorization: Bearer <key>`.

| Scope | Prefix | Opens | Plan | Made on |
| --- | --- | --- | --- | --- |
| `live` | `ftpl_` | The levels API (`/api/v1`), the platform integrations | LIVE | [Account, Integrations](https://firmtape.com/account#integrations) |
| `lab` | `labk_` | The LAB API (`/api/lab`, `/api/struct`), the MCP server's `lab_` tools | LAB | [Account, LAB](https://firmtape.com/account#lab) |
| `dataset` | `labk_` | The DATASET files (`/snapshots/<day>.json.gz`) and levels API history older than 90 days | DATASET | [Account, LAB](https://firmtape.com/account#lab) |
| `orders` | `ordk_` | The Orders API (`/orders/api`), the POSITIONS API (`/api/positions`), the Orders MCP server (`/orders/mcp`) | ORDERS | [Account, Orders](https://firmtape.com/account#orders-keys) |
| `geo` | `gk_` | The Geo API (`geo.firmtape.com/v1`), the Geo MCP server | GEO | [Account, Geo, Keys](https://firmtape.com/account#geo-keys) |

## Across products

- [Quickstart](https://firmtape.com/docs/developers/quickstart)
- [API keys and scopes](https://firmtape.com/docs/developers/keys)
- [Errors](https://firmtape.com/docs/developers/errors)
- [Rate limits](https://firmtape.com/docs/developers/limits)
- [Webhooks](https://firmtape.com/docs/developers/webhooks)
- [MCP](https://firmtape.com/docs/developers/mcp)
- [Versioning and changelog](https://firmtape.com/docs/developers/versioning)
- [For AI agents](https://firmtape.com/docs/developers/agents)

## Planned

- One webhook format: POSITIONS and Geo move to the alerts' envelope (`type`, `id`, `version`, `ts`), header set (`X-FirmTape-Event`, `X-FirmTape-Event-Id`, `X-FirmTape-Timestamp`, `X-FirmTape-Signature: sha256=`) and delivery policy (3 seconds, retries after 1 s and 4 s, switch-off after 10 failures). Plan: (1) send the new format beside the old one, each request carrying both header sets, for 30 days from the day it starts, announced on this page and by mail to every account with a webhook; (2) `event` stays in the body beside `type` for the same 30 days; (3) Geo's `t=,v1=` signature stays in its own header, `X-FirmTape-Signature-Geo`, for those 30 days; (4) then the old format stops. Not started; no live sender changes before the start is announced here.
- A key of its own for the dataset: The DATASET files open with a `dataset` scope key made on the account page, rather than the `lab` key. The `lab` key keeps working for the files for 30 days after the new key ships.
- A delivery log for the alerts webhook: Every delivery of the level alerts webhook in the account, with status, tries and a resend button, as Geo has.
- One error envelope: `{"error": {"code", "message", "docs"}}` on every API, LAB and Geo included, `docs` linking the code's row on the errors page.
- Alert lines from a key: `/api/alerts` stays session-only until a customer asks for it from code.
