A read-only HTTP API exposing the worker's live auction context for the futures scan universe: key levels (POC / value area / IB / naked POCs / poor highs & lows) and market-structure alerts. JSON over HTTPS. Educational context, not financial advice.
Base URL
https://<your-deployment>/apiAuthentication
Every request needs an API key in the x-api-key header, never a query string. A query string leaks the key into logs and referrers. Generate and revoke keys self-serve on the Account page.
curl -H "x-api-key: aift_xxxxxxxxxxxx" \
"https://<your-deployment>/api/levels?symbol=ES"Rate limits & tiers
Limits are per key, per minute. Every response carries X-RateLimit-Limit and X-Api-Tier. Exceeding the limit returns 429.
| Tier | Requests / min |
|---|---|
| free | 30 |
| pro | 120 |
| admin | 600 |
Data source and freshness
Every /api/levels response names the session it describes, because a program cannot read a caveat in prose. Branch on these three fields before anything else.
| Field | Values | Meaning |
|---|---|---|
| dataSource | "personal" | "shared" | "delayed" | Which feed produced this answer. personal means your own broker connection; delayed means the most recent completed session. |
| live | true | false | Whether the numbers describe the session open right now. false is the normal state until you connect a broker. |
| asOf | "YYYY-MM-DD" | null | The session date a delayed answer describes. null when live is true, because the open session has no closing date yet. |
When live is false, every field derived from the open session is null rather than quietly stale: lastPrice, bias, overnight, playbook and updatedAt. prior, nakedPocs, poorHighs and poorLows carry the completed session. developing is null on a delayed response, because there is no session in progress to describe: it is populated only once a broker is connected. Write your client against the delayed shape first, and null-check developing: an Elite key starts delayed and stays that way until a broker is connected on the Account page.
Endpoints
/api/levels?symbol=ESKey levels for one symbol. symbol accepts the full-size display ticker (ES, NQ, GC, CL) or the raw executable key.
Delayed, which is what a new key receives until a broker is connected:
{
"symbol": "ES",
"dataSource": "delayed",
"live": false,
"asOf": "2026-07-16",
"updatedAt": null,
"lastPrice": null,
"bias": null,
"developing": null,
"prior": { "poc": 5601, "vah": 5610, "val": 5590 },
"overnight": null,
"nakedPocs":[ { "price": 5588, "date": "2026-07-15" } ],
"poorHighs":[], "poorLows":[],
"playbook": null
}Live, once your own broker connection is supplying the feed:
{
"symbol": "ES",
"dataSource": "personal",
"live": true,
"asOf": null,
"updatedAt": "2026-07-17T14:03:11.402Z",
"lastPrice": 5623.25,
"bias": "trend_up",
"developing": { "poc": 5620, "vah": 5628, "val": 5612,
"vpoc": 5621, "ibHigh": 5626, "ibLow": 5610,
"high": 5631, "low": 5608 },
"prior": { "poc": 5601, "vah": 5610, "val": 5590 },
"overnight":{ "high": 5629, "low": 5605 },
"nakedPocs":[ { "price": 5588, "date": "2026-07-15" } ],
"poorHighs":[], "poorLows":[],
"playbook": { "bias": "trend_up", "levels": [ ... ], "scenarios": [ ... ] }
}/api/alertsLive market-structure alerts across the scan universe. Optional ?symbol=ES filter. Each alert carries a severity (info / warn / critical).
{
"updatedAt": "2026-07-17T14:03:11.402Z",
"count": 2,
"alerts": [
{ "symbol": "ES", "type": "va-reject-high", "severity": "critical",
"price": 5628, "ref": "prior-VAH", "message": "ES rejected prior VAH 5628" },
{ "symbol": "NQ", "type": "naked-poc", "severity": "warn",
"price": 20110, "ref": "2026-07-15", "message": "NQ testing naked POC 20110" }
]
}Alert types & severity
| Type | Severity | Meaning |
|---|---|---|
| va-reject-high / -low | critical | Price rejected prior value-area edge |
| ib-break-up / -down | critical | Initial-balance breakout |
| va-accept-above / -below | warn | Acceptance outside prior value |
| naked-poc | warn | Testing an untouched (virgin) POC |
| va-test-high / -low | info | Touching prior value-area edge |
| poor-high / poor-low | info | Revisiting an unfinished auction extreme |
Webhooks
Instead of polling /api/alerts, subscribe a Discord / Telegram / generic endpoint or an email digest on the Account page. Each subscription can filter by symbol and minimum severity; the worker pushes matching alerts as they fire.
Generic endpoint payload
A generic endpoint receives an HTTPS POST with a JSON body: version, a human-readable text summary, and the structured alerts array an automation should switch on (type, severity, price, params). Endpoints must be public HTTPS (private and loopback address space is refused). Use the Send test button on the Account page to fire this exact shape at your endpoint before relying on it.
{
"version": 2,
"text": "• TEST alert from TPOChart. This webhook is wired up correctly: real market-structure alerts will arrive here looking exactly like this card. Nothing to trade.",
"alerts": [
{
"kind": "structure",
"key": "ES:webhook-test:1767627000000",
"symbol": "ES",
"type": "webhook-test",
"severity": "info",
"session": "rth",
"price": 1234.25,
"ref": "delivery check, not a signal",
"message": "TEST alert from TPOChart. This webhook is wired up correctly: real market-structure alerts will arrive here looking exactly like this card. Nothing to trade.",
"params": null,
"url": "https://trade.aifutures.dev/alerts"
}
]
}Errors
401 missing/invalid key · 404 unknown symbol · 409 no completed session is licensed to this key yet (code no_licensed_source; the body carries a fix object pointing at /account and /broker-guide) · 429 rate limit · 502 upstream store unavailable.
Branch on code, never on the message text: refusal wording is written in the reader's language and changes with it, while code does not.