Agent integration · Grounded market state

Bring your own model. We bring the facts.

A flat, typed, 19-key record per symbol — verdict, scores, category directions, the conditions that fired and the raw readings behind them. It drops into a tool result with no reshaping, and because every sentence is assembled from measured values rather than sampled, nothing in it can be invented.

19 keys per record 26 series read 2 free whole-market surfaces
tool_result · get_market_state 200 OK
GET /v1/summary?symbol=EURUSD&timeframe=H1
what the model receives
19 keys
5× per turn
classificationbias · bias_strength
numeric features4 scores
grounding text3 signal arrays
raw readings13 values
model in the pathnone
determinismtotal
strip before renderrecommendations
staleness keyupdated_at
{
  "symbol": "EURUSD", "timeframe": "H1",
  "bias": "bullish",          // lowercase here
  "bias_strength": "normal",  // separate field
  "confidence": 0.55,
  "trend_score": 3.0, "momentum_score": -0.5,
  "volatility_score": 0.48,
  "signals": { "trend": "bullish", "momentum": "neutral",
               "volatility": "normal", "volume": "bullish" },
  "key_levels": { "resistance": [1.0861], "support": [1.0819] },
  "bullish_signals": ["Price above 200 SMA (long-term uptrend)", …],
  "bearish_signals": ["RSI bearish at 38.7"],
  "neutral_signals": ["ADX 21.4 (weak/ranging market)"],
  "volatility_info": […], "volume_info": […],
  "summary": "EURUSD on H1: Overall bias is BULLISH (confidence: 55%).
             Bullish factors: …"   // "factors", not "signals",
  "recommendations": […],   // strip before showing a user
  "key_values": { "bid": 1.08432, "rsi_14": 38.7,
                 "macd_hist": 0.00012, … },  // macd_hist, not macd_histogram
  "updated_at": 1774620183
}
19Keys in one record
26Series behind it
0×Cost of the market-wide view
7Timeframes
Straight answer

There is no model in the request path.

Every sentence these endpoints return is built by string templates from values that were measured, against thresholds that are constants in the source. That is a deliberate design for agent work, and it is worth being precise about, because it decides what you can safely put in front of a user.

WHAT YOU GET

Grounded, deterministic state

Fixed conditions over cached indicator values, fixed weights, a closed-form confidence and a templated paragraph. Two calls on the same cached values return the same record, byte for byte — so a disagreement between runs is a data change, never a sampling artefact.

  • Nothing sampled ⇒ no invented prices
  • Reproducible from two signed scores
  • Every sentence carries its triggering number
WHAT YOU BRING

The reasoning layer

Your model decides what the state means, how it combines with everything else you know, and how to say it. TickAtlas is the retrieval half of that loop — the part that has to be right, cheap and boring.

  • Tool result = response body, unreshaped
  • Enumerable inputs: symbol, timeframe
  • Predictable per-turn cost

One field needs handling before a user sees it. recommendations is a short list of generated advice-shaped strings selected by the bias band, and its leading entry is also appended to the summary paragraph. TickAtlas publishes market data and computed analytics for software use, not personalised investment advice — drop the field, and truncate the paragraph, in any surface an end user reads.

Agent-ready surfaces

Five tools, two of them free.

An agent loop lives or dies on cost per turn. Two of these surfaces are outside the metered /v1/ namespace entirely, which makes the standard pattern obvious: let the model look at everything for nothing, then pay only for what it chose.

Surface Cost per turn Breadth Record Why an agent wants it
GET /v1/summary 5 requests One symbol, one timeframe 19 keys, flat The richest single record: a verdict, two signed scores, four category directions, three arrays of readable conditions and 13 raw readings. Computed on the request, so it reflects the latest cached values.
GET /api/market-insights/cards/{timeframe} no quota cost Every symbol, one timeframe 16 keys per card Whole-market context for free, already sorted with the biggest movers first. The cheapest way to let an agent pick which symbol deserves a paid look.
GET /api/market-insights/overview no quota cost Market-wide aggregate Counts plus four top-five lists Sentiment counts and percentages, top gainers and losers, strongest trends by ADX and most volatile by ATR. One object, no iteration needed.
GET /v1/screener 2 requests Every symbol, one series {symbol, value, bid} rows Lets the agent express its own condition rather than accepting a pre-scored bias. One indicator, an optional min/max band, sorted and paged.
POST /api/market-insights/unlock $0.01 + 1 request One symbol, one timeframe 25 keys, cached The snapshot equivalent of a summary, charged in credit rather than quota. Re-unlocking the same symbol and timeframe inside 7 hours is free — the Redis key carries a 7-hour TTL.
1

Look wide, for free

Pull the cached card set for a timeframe. Every symbol, with bias, confidence, RSI, ADX, spread and the two signal counts already attached, sorted with the biggest movers first.

GET /api/market-insights/cards/H4
2

Let the model choose

Hand it the shortlist and the aggregate. The decision of which symbols are worth a closer look is exactly the judgement call a model is good at — and it costs nothing to be wrong.

GET /api/market-insights/overview
3

Spend on the survivors

One live summary per chosen symbol, at 5 requests each. Fresh, complete and with the full derivation, so the model's final answer can cite the condition that drove it.

GET /v1/summary?symbol=…
Field mapping

What each field is for — and how it bites.

The record is flat and typed, so most of the integration is deciding what to keep. These are the fields an agent touches, with the mistake each one invites.

Field Type Use What to watch
bias string Primary classification. LOWERCASE on /v1/summary: bullish, bearish, neutral. The cached cards use UPPERCASE with five values including STRONGLY BULLISH and STRONGLY BEARISH. Normalise before comparing across the two surfaces.
bias_strength string Qualifier for the bias. strong or normal. A separate field, not a prefix — an agent looking for "STRONGLY BULLISH" in /v1/summary will never find it.
confidence number Ranking between symbols. Bounded 0.4 to 0.9 by the score ladder. It is a closed-form function of the score, not a probability and not calibrated against outcomes. Do not present it to an end user as a likelihood.
trend_score number Numeric feature. Signed, one decimal. Added to momentum_score, this is the entire input to the bias — so the verdict is reproducible from two numbers.
momentum_score number Numeric feature. The other half of the same sum.
signals object Four category lights. trend, momentum, volatility, volume. volatility is hard-coded to "normal" and never varies, so an agent that reasons over it is reasoning over a constant.
bullish_signals string[] Grounding text. Readable sentences with the triggering number inlined. Ideal as model context; poor as a state key, because the wording shifts on a rounding change.
bearish_signals string[] Grounding text. Independent of the bullish array — both are routinely non-empty at once.
key_values object Raw numbers for a second opinion. 13 readings: bid, ask, rsi_14, macd_hist, adx, atr_14, sma_20, sma_50, sma_200, bb_upper, bb_lower, stochastic_k, mfi_14. Note macd_hist, not macd_histogram, and bid, not current_price. Any of them can be null.
key_levels object Reference levels. resistance and support, each an array. Populated from BB_upper and BB_lower only — they are band edges, not detected structure, and each array is empty when the band is unavailable.
summary string Pre-written paragraph. Templated, not generated by a model. It ends with the leading entry of recommendations, so anything that renders it verbatim in a user-facing surface renders that clause too.
recommendations string[] — Generated strings selected by the bias band. Documented by name and type; TickAtlas does not reproduce their wording. Strip or ignore this field in any user-facing agent output.
updated_at number Cache key / staleness check. Epoch timestamp of the last cache refresh behind the response. Two calls with the same value returned the same numbers and both cost 5×.
Request pattern

A tool definition and twelve lines.

The response body is already the tool result. There is no parsing step, no field renaming and no unit conversion — the only work worth doing in the handler is dropping the generated-advice field and keeping the staleness key.

  • Constrain timeframe with an enum in the schema.
  • Drop recommendations in the handler, not the prompt.
  • Cache on updated_at — a repeat still costs 5×.
  • Key needs the indicators permission scope.
# A tool definition. The record is already flat and typed, so the
# tool result is the response body - there is no reshaping step.
{
  "name": "get_market_state",
  "description": "Measured market state for one symbol on one timeframe.",
  "input_schema": {
    "type": "object",
    "properties": {
      "symbol":    { "type": "string" },
      "timeframe": { "type": "string",
                      "enum": ["M1", "M5", "M15", "M30", "H1", "H4", "D1"] }
    },
    "required": ["symbol"]
  }
}
# The handler. Two things worth doing before the model sees it:
#   1. drop recommendations - generated advice strings
#   2. keep updated_at - it is your staleness and dedupe key
def get_market_state(symbol, timeframe="H1"):
    r = requests.get("https://tickatlas.com/v1/summary",
                     headers={"X-API-Key": KEY},
                     params={"symbol": symbol, "timeframe": timeframe},
                     timeout=10)
    r.raise_for_status()
    d = r.json()["data"]
    d.pop("recommendations", None)
    return d                      # 5x quota per call

# Cheap first, expensive second. The cached cards cost NOTHING and
# cover every symbol, so let the agent shortlist there and spend
# the 5x call only on what it picked.
cards = requests.get("https://tickatlas.com/api/market-insights/cards/H4",
                     headers={"X-API-Key": KEY}).json()["cards"]
shortlist = [c["symbol"] for c in cards[:5]]   # already sorted by |daily change|
one tool result
19 keys · flat · typed · no nested parsing
deterministic
Classifybias · bias_strength · confidence
Quantifytrend · momentum · volatility scores
Groundbullish · bearish · neutral sentences
Verifykey_values — 13 raw readings
Built for a context window

Classification, number and explanation in one object.

A model given only a label has to be trusted. A model given the label, the score it came from and the sentence naming the condition that moved it can be checked — by you, in the log, after the fact. That is the difference between an agent you can ship and one you keep watching.

Timeframes

7 live, 4 pre-computed.

The live summary accepts M1, M5, M15, M30, H1, H4, D1 and defaults to H1. The cached snapshot surface covers M30, H1, H4, D1 — the four the background job computes. Put the right enum in each tool schema: an out-of-set value returns a 400 with the valid list, which costs your agent a turn to discover.

  • M1 — 1 Minute (live summary only)
  • M5 — 5 Minutes (live summary only)
  • M15 — 15 Minutes (live summary only)
  • M30 — 30 Minutes (also pre-computed)
  • H1 — 1 Hour (also pre-computed)
  • H4 — 4 Hours (also pre-computed)
  • D1 — Daily (also pre-computed)

Highlighted pills are the four the snapshot job also caches. It runs at 00:05, 06:05, 12:05, 18:05 UTC and stamps its rows on the hour, so a card read at 05:30 carries the 00:00 snapshot. snapshot_time on a card and updated_at on a live summary are how you tell which surface a number came from.

Developer-first behavior

The properties an agent loop actually needs.

Not "smart" — predictable. An autonomous loop is only as safe as the worst behaviour of its cheapest dependency, so these are the guarantees worth designing around.

REPRODUCIBLE

Same input, same record

Fixed thresholds and constant weights mean a replay produces the identical object. You can regression-test an agent against a captured response and the fixture will not rot underneath you.

  • No sampling, no temperature
BOUNDED

Cost per turn is a constant

5× for a summary, 2× for a scan, 1× for a single series, 0× for the cached market view. A loop's budget is the sum of known integers, not an estimate.

  • Quota, not tokens, is the meter
SELF-DATING

Every record says when

updated_at on live surfaces, snapshot_time on cached ones. An agent can refuse to act on a stale reading instead of assuming freshness it was never promised.

  • Also the natural dedupe key
FAIL-LOUD

Wrong input is an error, not a guess

A bad timeframe is a 400 carrying the valid set; a bad symbol is a 404 pointing at /v1/symbols. Nothing is silently coerced into a plausible-looking answer.

  • Machine-readable error codes
Developer API pricing

Agent budgets are integers here.

Quota is metered per request with a fixed multiplier per endpoint, so the cost of a loop is arithmetic rather than an estimate. Pay-as-you-go counts as paid for endpoint access, so an agent can run on the starting credit from day one.

There is no free tier and no self-serve trial. Every account starts on pay-as-you-go with $2.50 of prepaid credit, no card and no overage — monthly plans lift the starting quota.
Pay as you go
$0 to start 200 requests/day · 30/min until you top up
  • $2.50 of credit included
  • Every REST endpoint except raw ticks
  • No card required, no overage
  • 10 API keys
Start free
Starter
$29/mo 10,000 requests · 120/min
  • Every REST endpoint except raw ticks
  • WebSocket streaming, 5 symbols
  • Released calendar actuals
  • Email support
  • 3 API keys
View plan
Enterprise
$349/mo 1,000,000 requests · 6000/min
  • Everything in Pro
  • Dedicated support
  • 100 API keys
  • Custom indicators
  • SLA guarantee
  • On-premise option
Contact sales
Common software patterns

Cheap breadth, paid depth.

Three shapes cover almost every agent built on this data, and all three exploit the same asymmetry: looking at the whole market costs nothing, looking closely costs five.

Tool-calling agents

One flat record with typed fields and readable condition sentences drops straight into a tool result. The model gets both the number and the sentence that explains it, so its answer can cite what it saw.

function callingMCP toolsassistants

Cheap-first triage

The free cached card set covers every symbol on four timeframes and arrives pre-sorted by absolute daily change. Shortlist there, then spend the metered call on the handful that survived.

pre-filterscost controlschedulers

Scheduled briefings

The overview object is a whole-market aggregate with sentiment counts and four top-five lists — enough for a daily digest without a single metered request, and enough grounding for a model to write around.

digestsreportsnewsletters
Frequently asked questions

Agent integration, clarified.

Where the model is, why bias changes spelling between surfaces, what to strip before rendering, and what a turn costs.

Is there a language model behind these endpoints?

No — and that is the point. Every sentence these endpoints return is assembled from measured values by fixed string templates: the conditions are tested against constant numeric boundaries, the scores are sums of constants, and the paragraph is built by joining the results. Nothing is sampled, so nothing can hallucinate a price, and the same inputs always produce the same record. The model in an "AI insights" pipeline is yours; what TickAtlas supplies is the grounded, machine-readable state you feed it.

Why does bias look different depending on which call I make?

Because the two surfaces spell it differently. GET /v1/summary returns lowercase bullish, bearish or neutral with strength in a separate bias_strength field. The cached market-insights cards return UPPERCASE with five values: STRONGLY BULLISH, BULLISH, NEUTRAL, BEARISH, STRONGLY BEARISH. The underlying scoring code is the same; only the encoding differs. Normalise on the way in, or an agent that branches on one spelling will silently fall through on the other.

What should I strip before the model sees the payload?

The recommendations array, and — if you render text to an end user — be aware that the leading entry of that array is also appended to the summary paragraph. Those strings are generated advice-shaped text, and TickAtlas publishes market data and computed analytics for software use rather than personalised investment advice. Everything else in the record is descriptive: measured values, classifications derived from fixed thresholds, and sentences naming the condition that fired.

What does an agent turn actually cost?

Every live call counts once against your daily quota. In pay-as-you-go credit a summary call costs 5 weighted units, a screener scan 2 and a single indicator read 1. The cached market-insights teasers — the whole-market card set and the market-wide overview — cost nothing at all, because usage accounting only applies to paths beginning /v1/ and those routes do no accounting of their own. The one credit-priced surface is the unlock, at $0.01 per symbol per timeframe plus one request, and re-unlocking the same pair inside seven hours is free.

How fresh is what the agent sees?

A live summary is computed on the request from the current cached indicator values, which change when our data updates — about every 60 seconds for the fastest timeframes and every 10 to 30 minutes for the slower ones. The pre-computed snapshots are different: a background job runs at 00:05, 06:05, 12:05, 18:05 UTC and stamps its rows on the hour, so a card read at 05:30 carries the 00:00 snapshot. updated_at on the live surface and snapshot_time on the cached one tell you exactly which it is.

Which timeframes can an agent ask for?

M1, M5, M15, M30, H1, H4, D1 on the live summary, defaulting to H1. The cached snapshot surface covers four of them — M30, H1, H4, D1 — because that is what the background job computes. Constrain the enum in your tool schema to the set the surface you call actually supports; an out-of-set timeframe is a 400 with the valid list in the detail, which costs the agent a wasted turn.

How many indicator series does the analysis read?

26 distinct series across four analysers — 12 trend, 6 momentum, 6 volatility and 2 volume. The platform publishes 42 series in total, so a summary is a documented subset rather than everything, and the subset is fixed: it does not change with the symbol, the timeframe or market conditions. If your agent needs a series outside that set, read it directly from /v1/indicator or /v1/multi.

Can the agent scan the whole market itself?

Yes, two ways. The free cached card set gives it every symbol on one timeframe with a bias, a confidence and the two signal counts already attached. Or, when you want the agent to express its own condition instead of accepting a pre-scored one, /v1/screener reads a single indicator series across every symbol in the live cache and returns the ones inside a min/max band, sorted and paged, for one call (2 weighted units).

Is there a plan gate?

Not on the live summary for developer API keys — a pay-as-you-go account reaches it on its $2.50 of starting credit, provided the key carries the indicators permission scope. The cached teaser routes have no gate either. The gates worth knowing about are elsewhere: tick data is Pro and Enterprise only, and WebSocket streaming starts at Starter.

Flat, typed, dated and reproducible

Give your agent something it cannot make up.

One request returns the classification, the numbers behind it and the sentences that explain them — and the whole-market view costs nothing at all. Start on your $2.50 of credit, no card.