Agents
The shape of this API is the reason it works natively with coding agents. Flat SQL WHERE clauses over named columns and flags. No joins, no window functions, no schema introspection round-trip. Hand the schema to your agent once and it can compose, backtest, and subscribe queries on its own. This page covers the conceptual setup and the drop-in tool definitions for every common runtime.
Why this works with agents
Constraints chosen for LLM ergonomics, not against them.
- The grammar is small. A
WHEREclause over named columns. NoJOIN, noGROUP BY, noOVER. An LLM that has seen the schema once can compose the query without a doc lookup. - The schema fits in a prompt. ~100 numeric and string columns + ~50 pre-thresholded boolean flags. The full schema page is one scroll. Drop it into a system prompt and the agent has the vocabulary.
- No surprise dialect. Identifiers are the customer-facing names listed on the schema page; the API doesn't rewrite, alias, or coerce them. What the agent writes is what runs.
- One language, every endpoint. The same
qstring drives/scan,/scan?asof=,/webhooks, and the saved-rules surface. The agent learns one composition rule and applies it everywhere.
The typical agent loop
Three calls, all the same shape.
- User asks something in English (“find oversold semis bouncing on volume”).
- Agent translates to a
qclause and calls/v2/scanto see live matches. - If the user wants confidence, agent calls
/v2/scan?asof=YYYY-MM-DDacross past dates to sanity-check the edge. - If the user wants to be alerted, agent registers the same
qas a webhook so future matches push to the user's channel.
State lives in the API. The agent stays stateless across turns; the user's saved universes, rules, and webhooks persist on Tickerbot.
What to put in the system prompt
A short bootstrap so the agent doesn’t have to re-derive the vocabulary.
Three things turn an LLM into a useful Tickerbot agent:
- The list of column and flag names (from
/api/schema.json, or just the schema page pasted in). - The grammar bounds (“flat WHERE clause; identifiers are bare names; numeric literals are fully specified, not
1.5B”). - The asset-symbol prefix rules (
X:BTCUSDfor crypto, etc. — see Asset symbols).
See the marketing-side /agents page for a worked example with prompts, an agent transcript, and a starter repo.
Pick a runtime
Claude tool-use docs for the API surface. Pass the JSON below as the tools array on a Messages request.
All tools, one JSON blob
The whole set in one paste. Use this if your runtime accepts a tool array.
[
{
"name": "tickerbot_list_tickers",
"description": "GET /v2/tickers. List active tickers, paginated. Returns the universe of tracked symbols (~12,000 US equities + top 100 crypto by market cap) in alphabetical order with a slim payload (`ticker`, `name`, `asset_type`, `exchange`, `market_cap`). Use cursor pagination to walk the full list, or pass `?tickers=...` for bulk lookup of named symbols with full rows.",
"input_schema": {
"type": "object",
"properties": {
"tickers": {
"type": "string",
"description": "Comma-separated list of symbols (up to 50). When set, the response returns the full row for each requested symbol; pagination params are ignored. Symbols missing from our universe come back with `_not_found: true`."
},
"limit": {
"type": "integer",
"description": "Page size for the alphabetical walk. Max 1000.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response's `next_cursor` field. Continues the walk from after that page."
},
"search": {
"type": "string",
"description": "Substring filter over `ticker` (case-insensitive) and `name`. When set, results are ordered by `market_cap DESC NULLS LAST`."
},
"asset_type": {
"type": "string",
"description": "Filter by asset type — typically `equity` or `crypto`. Matched case-insensitively against the stored value."
},
"exchange": {
"type": "string",
"description": "Filter by exchange code (uppercase). Common values: `XNYS`, `XNAS`, `BATS`."
},
"sector": {
"type": "string",
"description": "Filter by sector name. Exact match against the stored `sector` field."
},
"min_market_cap": {
"type": "number",
"description": "Minimum market cap (USD). Results are ordered by `market_cap DESC NULLS LAST` when set."
}
}
}
},
{
"name": "tickerbot_get_ticker",
"description": "GET /v2/tickers/{ticker}. Get the full current state of one ticker. Returns the entire ticker row. Every field on the schema page, including current values for all numeric signals and the current value of every boolean flag. Treat it as the authoritative current snapshot for a symbol.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Ticker symbol. Case-insensitive. Equities: exchange symbol (`AAPL`). Crypto: bare symbol (`BTC`)."
}
},
"required": [
"ticker"
]
}
},
{
"name": "tickerbot_get_ticker_history",
"description": "GET /v2/tickers/{ticker}/history. Get the full ticker row as of a past date. Time-travel to any historical date and pull the whole wide row as it stood then, including the boolean flag values, technical indicators, and the most-recent fundamentals known on that date. Useful for backtests and \"what did we know\" reconstructions.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"asof": {
"type": "string",
"description": "Target date as `YYYY-MM-DD` or full ISO timestamp `YYYY-MM-DDTHH:MM:SSZ`. The response returns the most-recent daily snapshot on or before this date."
}
},
"required": [
"ticker",
"asof"
]
}
},
{
"name": "tickerbot_get_ticker_events",
"description": "GET /v2/tickers/{ticker}/events. Discrete event log for one ticker. Returns splits, dividends, and analyst rating changes for the ticker, newest-first, in a unified envelope. Each event has a `ts`, a `kind`, and a `payload` whose shape depends on the kind.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"from": {
"type": "string",
"description": "Earliest event timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to your plan's history window."
},
"to": {
"type": "string",
"description": "Latest event timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to \"now\"."
},
"kind": {
"type": "string",
"description": "Filter by event kind.",
"enum": [
"split",
"dividend",
"rating_change"
]
},
"limit": {
"type": "integer",
"description": "Page size. Max 1000.",
"default": 100
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
},
"required": [
"ticker"
]
}
},
{
"name": "tickerbot_get_signals_match",
"description": "GET /v2/signals/{signal}. Find tickers that match a signal right now. Return the set of tickers where the named signal is true (for boolean flags) or where the numeric value satisfies a single-bounded condition. Sorted by signal value descending for numerics, alphabetically by ticker for booleans.",
"input_schema": {
"type": "object",
"properties": {
"signal": {
"type": "string",
"description": "A column on `ticker`. Boolean flags (e.g. `golden_cross_today`, `above_sma_50`) are detected automatically; numerics (e.g. `rsi_14`, `market_cap`, `pe_ratio`) require a condition."
},
"condition": {
"type": "string",
"description": "Required for numeric signals. Single bound, format `<op><value>`. Operators: `>`, `>=`, `=`, `!=`, `<`, `<=`. Examples: `>70`, `<=200`, `!=0`. Ignored for boolean flags."
},
"limit": {
"type": "integer",
"description": "Page size. Max 200.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
},
"required": [
"signal"
]
}
},
{
"name": "tickerbot_get_signal_history",
"description": "GET /v2/signals/{signal}/{ticker}/history/{interval}. Time series of one signal for one ticker. Returns a sequence of `{t, v}` bars for the requested signal × ticker at the chosen resolution. `t` is an ISO timestamp (or `YYYY-MM-DD` for daily/weekly). `v` is the signal value at that bar (a number for numeric signals, `true`/`false` for boolean flags).",
"input_schema": {
"type": "object",
"properties": {
"signal": {
"type": "string",
"description": "A column on the wide-state tables (matches the schema page 1:1)."
},
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"interval": {
"type": "string",
"description": "Resolution. Daily-only signals (SMAs, RSI, MACD, fundamentals) are not stored at minute/hourly resolution; request `1d` for those.",
"enum": [
"1m",
"1h",
"1d",
"1w"
]
},
"from": {
"type": "string",
"description": "Earliest bar timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to your plan's history window."
},
"to": {
"type": "string",
"description": "Latest bar timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to \"now\"."
},
"limit": {
"type": "integer",
"description": "Page size. Max 1000.",
"default": 252
},
"cursor": {
"type": "string",
"description": "Opaque cursor. Walks back in time page-by-page from the most-recent bar."
}
},
"required": [
"signal",
"ticker",
"interval"
]
}
},
{
"name": "tickerbot_get_scan",
"description": "GET /v2/scan. Run a SQL WHERE against the current universe. Filter the live ticker universe with a SQL WHERE clause expressed in our SQL grammar. Returns matching tickers sorted by your chosen column. Columns in `q`, `order`, and `fields` are the customer-facing names listed on /api/schema and /api/flags. No translation layer.",
"input_schema": {
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "SQL WHERE expression. Required unless `rule` is supplied. Max 4000 chars. Semicolons, comments, and write-side keywords (INSERT/UPDATE/DELETE/DROP/etc.) are rejected."
},
"rule": {
"type": "string",
"description": "Slug of a saved rule (see `/v2/rules`). Its `q`, `universe_id`, `order`, `dir`, and `fields` become defaults; any of those passed as query-string parameters override."
},
"universe": {
"type": "string",
"description": "Slug of a system universe (`top_10`, `top_100`) or one of your own (`/v2/universes`). Scopes the scan to those tickers. When omitted, the scan runs across all ~12,000 tracked tickers."
},
"asof": {
"type": "string",
"description": "Optional. Run the WHERE against historical daily state for the given `YYYY-MM-DD` (or full ISO). Plan history depth applies."
},
"order": {
"type": "string",
"description": "Column to sort by. Must be a valid identifier (lowercase letters, digits, underscore).",
"default": "day_change_pct"
},
"dir": {
"type": "string",
"description": "Sort direction.",
"enum": [
"asc",
"desc"
],
"default": "desc"
},
"fields": {
"type": "string",
"description": "Comma-separated list of extra columns to include in each result row. Default columns are always present: ticker, name, asset_type, price, day_change_pct, gap_pct, relative_volume, market_cap."
},
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
}
}
},
{
"name": "tickerbot_post_scan",
"description": "POST /v2/scan. Same as GET /v2/scan, with `q` in the body. POST mirror of `GET /v2/scan` for queries too long to fit in a URL. Accepts the same parameters (`q`, `order`, `dir`, `fields`, `limit`) in a JSON body. `cursor` continues to come from the query string for consistency with the GET pagination shape.",
"input_schema": {
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "SQL WHERE expression."
},
"order": {
"type": "string",
"description": "Sort column."
},
"dir": {
"type": "string",
"description": "Sort direction.",
"enum": [
"asc",
"desc"
]
},
"fields": {
"type": "string",
"description": "Comma-separated extra columns."
},
"limit": {
"type": "integer",
"description": "Page size, max 100."
},
"cursor": {
"type": "string",
"description": "Opaque cursor (query string, not body)."
}
},
"required": [
"q"
]
}
},
{
"name": "tickerbot_post_webhook",
"description": "POST /v2/webhooks. Create a webhook subscription. Register a SQL WHERE clause (inline `q` or `rule_id`) + an HTTPS target URL. On the cadence configured for your plan, we evaluate the clause against the relevant ticker universe. When a new ticker enters the match set, we POST a `webhook.fired` event to your target. On creation we also send a one-shot `webhook.ping` to verify reachability; the subscription stays in `pending_verification` until the ping returns a 2xx response, then flips to `active`.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Human-readable label. Helps you find this webhook later in `GET /v2/webhooks`. Doesn't need to be unique."
},
"q": {
"type": "string",
"description": "SQL WHERE clause. Same grammar as `/v2/scan`. Either this or `rule_id` is required."
},
"rule_id": {
"type": "string",
"description": "Slug of a saved rule (see `/v2/rules`). The webhook stores a snapshot of the rule's `q` + `universe_id` at creation time."
},
"target_url": {
"type": "string",
"description": "HTTPS endpoint that will receive POSTed events. Must start with `https://`. Plain HTTP is rejected."
},
"cadence": {
"type": "string",
"description": "How often to evaluate this webhook. Defaults to your plan's fastest cadence; pick a slower one to conserve quota or smooth out noisy fires.",
"enum": [
"1m",
"5m",
"15m",
"hourly",
"nyse_open"
]
}
},
"required": [
"name",
"target_url"
]
}
},
{
"name": "tickerbot_list_webhooks",
"description": "GET /v2/webhooks. List webhook subscriptions on this API key. Returns webhook subscriptions created by the current API key, newest-first. Visibility is key-scoped: webhooks created with a different key on the same account are not returned here. Use `?status=` to filter and the `cursor` field to paginate.",
"input_schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Filter by status.",
"enum": [
"active",
"pending_verification",
"disabled"
]
},
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
}
}
},
{
"name": "tickerbot_get_webhook",
"description": "GET /v2/webhooks/{id}. Fetch one webhook subscription. Returns the current state of a webhook subscription. Visibility is key-scoped: webhooks created by another key (even on the same account) return 404.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id returned by `POST /v2/webhooks`."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_delete_webhook",
"description": "DELETE /v2/webhooks/{id}. Delete a webhook subscription. Hard delete. Any pending deliveries already enqueued may still fire (they capture the target URL + signing secret at queue time). To pause-rather-than-delete, just stop accepting deliveries at your target; after enough consecutive failures the subscription flips to `disabled`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_list_webhook_deliveries",
"description": "GET /v2/webhooks/{id}/deliveries. Inspect recent deliveries for a webhook. Returns the most-recent deliveries (pings and fires) for a webhook, newest-first. Useful for diagnosing failures and verifying signatures. The full request body is not included; we keep them small.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
},
"status": {
"type": "string",
"description": "Filter by delivery status.",
"enum": [
"pending",
"delivered",
"permanent_failure"
]
},
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_enable_webhook",
"description": "POST /v2/webhooks/{id}/enable. Re-enable a disabled or pending webhook. Resets a webhook back to `pending_verification`, clears its match-state cache (so the next eval treats every currently-matching ticker as new and fires a single `webhook.fired`), and re-enqueues the handshake ping. On 2xx the webhook flips to `active`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_test_fire_webhook",
"description": "POST /v2/webhooks/{id}/test. Send a one-off synthetic delivery for QA / smoke testing. Writes a pending `webhook.fired` delivery with `test: true` and an empty `matches` array. The scheduler picks it up on its next tick and POSTs the same headers + signature shape as a real firing — the only difference is the `test` flag in the body and on the delivery row. Useful for verifying your receiver is reachable, parses the payload correctly, and verifies the signature.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_list_universes",
"description": "GET /v2/universes. List your universes. A universe is a named list of tickers you can reference from `/v2/scan?universe=`, `/v2/signals/{signal}?universe=`, `/v2/tickers?universe=`, and `/v2/webhooks`. System universes (`top_10` and `top_100`, the top-N most-actively-traded tickers, rebalanced monthly) are available to every account at `GET /v2/universes/system`.",
"input_schema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
}
}
},
{
"name": "tickerbot_create_universe",
"description": "POST /v2/universes. Create a universe. Create a named ticker list owned by the calling account. Body: `{ id?, name, description?, tickers }`. If `id` is omitted, a slug is generated.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Optional slug. Lowercase letters, digits, underscore. Must be unique within your account."
},
"name": {
"type": "string",
"description": "Human-readable label."
},
"description": {
"type": "string",
"description": "Free-form notes."
},
"tickers": {
"type": "array",
"description": "Ticker symbols. Validated against your plan scope + the active universe.",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"tickers"
]
}
},
{
"name": "tickerbot_list_system_universes",
"description": "GET /v2/universes/system. List system universes (top_10, top_100). System universes are read-only ticker lists rebalanced monthly by 30-day trailing dollar volume. Available to every account regardless of plan.",
"input_schema": {
"type": "object",
"properties": {}
}
},
{
"name": "tickerbot_get_universe",
"description": "GET /v2/universes/{id}. Fetch a single universe. Returns the universe doc. Use `top_10`/`top_100` to fetch a system universe; any other slug must be one your account owns.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Universe slug."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_patch_universe",
"description": "PATCH /v2/universes/{id}. Update a universe. Update `name`, `description`, or `tickers`. To add/remove ticker subsets without replacing the full list, pass `{ add: [...], remove: [...] }` instead of `tickers`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Universe slug."
},
"name": {
"type": "string",
"description": "New label."
},
"description": {
"type": "string",
"description": "New notes."
},
"tickers": {
"type": "array",
"description": "Replace the full ticker list.",
"items": {
"type": "string"
}
},
"add": {
"type": "array",
"description": "Add these tickers (deduplicated).",
"items": {
"type": "string"
}
},
"remove": {
"type": "array",
"description": "Remove these tickers.",
"items": {
"type": "string"
}
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_delete_universe",
"description": "DELETE /v2/universes/{id}. Delete a universe. Permanently delete one of your universes. System universes cannot be deleted.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Universe slug."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_list_rules",
"description": "GET /v2/rules. List your saved rules. A rule is a saved `{q, universe_id?, order, dir, fields}` bundle. Rules can be referenced from `/v2/scan?rule=` (one-off run) and `/v2/webhooks` (subscribe to fires). Same SQL grammar as `/v2/scan`.",
"input_schema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor."
}
}
}
},
{
"name": "tickerbot_create_rule",
"description": "POST /v2/rules. Create a saved rule. Save a scan bundle so it can be re-run with `/v2/scan?rule=` or subscribed to via `/v2/webhooks`. The `universe_id` is optional; if unset, the rule runs against your plan default at execution time.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Optional slug."
},
"name": {
"type": "string",
"description": "Human-readable label."
},
"description": {
"type": "string",
"description": "Free-form notes."
},
"q": {
"type": "string",
"description": "SQL WHERE clause."
},
"universe_id": {
"type": "string",
"description": "Slug of a system or caller-owned universe to scope this rule."
},
"order": {
"type": "string",
"description": "Sort column.",
"default": "day_change_pct"
},
"dir": {
"type": "string",
"description": "Sort direction.",
"enum": [
"asc",
"desc"
]
},
"fields": {
"type": "array",
"description": "Extra columns to include.",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"q"
]
}
},
{
"name": "tickerbot_get_rule",
"description": "GET /v2/rules/{id}. Fetch a saved rule. Returns the rule doc.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Rule slug."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_patch_rule",
"description": "PATCH /v2/rules/{id}. Update a saved rule. Update any field on a rule. To detach `universe_id` set it to `null`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Rule slug."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_delete_rule",
"description": "DELETE /v2/rules/{id}. Delete a saved rule. Webhooks referencing this rule continue to fire using their snapshotted `q`; they don't break.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Rule slug."
}
},
"required": [
"id"
]
}
},
{
"name": "tickerbot_create_strategy",
"description": "POST /v2/strategies. Create a user-defined condition, optionally with exit policy. A strategy is a saved boolean expression over the signal vocabulary (the same column names documented on /api/schema and /api/signals). It's queried per ticker at evaluation time — the same condition works on AAPL today and NVDA tomorrow.\n\nWithout exit policy fields, a strategy behaves as a \"watch\" — it emits a 'strategy.entered' event when the condition flips true on a ticker and a 'strategy.exited' event when it flips false. With exit policy, the strategy tracks position state per ticker: stop_loss_pct closes the position when price falls that percent below entry, take_profit_pct closes when price rises that percent above entry, and max_hold_bars closes after that many bars regardless. `exit_reason` on the exit event discriminates which path fired.\n\nThe condition is validated by the same compiler that runs at evaluation time — invalid expressions are rejected synchronously with structured errors. See /api/strategies/condition-grammar for the accepted syntax.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Slug — lowercase, [a-z0-9_], unique within your account."
},
"description": {
"type": "string",
"description": "Free-form notes."
},
"condition": {
"type": "string",
"description": "Boolean expression over signal columns. See /api/strategies/condition-grammar."
},
"stop_loss_pct": {
"type": "number",
"description": "Close the position when price drops this percent below entry. e.g. 0.05 = 5% stop-loss."
},
"take_profit_pct": {
"type": "number",
"description": "Close the position when price rises this percent above entry."
},
"max_hold_bars": {
"type": "integer",
"description": "Close the position after this many bars regardless of price. Bars are at the resolution of the consuming endpoint."
}
},
"required": [
"name",
"condition"
]
}
},
{
"name": "tickerbot_get_strategy",
"description": "GET /v2/strategies/{name}. Fetch a saved strategy. Returns the strategy definition. Same shape as the POST response.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
}
},
"required": [
"name"
]
}
},
{
"name": "tickerbot_list_strategies",
"description": "GET /v2/strategies. List all your strategies. Cursor-paginated, like other v2 listings.",
"input_schema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Page size, max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from a prior response."
}
}
}
},
{
"name": "tickerbot_patch_strategy",
"description": "PATCH /v2/strategies/{name}. Edit condition, description, or exit policy. Partial update — only the fields you supply change. The condition is re-validated on every update.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug (immutable)."
},
"description": {
"type": "string",
"description": "New description."
},
"condition": {
"type": "string",
"description": "New condition. Re-validated."
},
"stop_loss_pct": {
"type": "number",
"description": "Send `null` to clear."
},
"take_profit_pct": {
"type": "number",
"description": "Send `null` to clear."
},
"max_hold_bars": {
"type": "integer",
"description": "Send `null` to clear."
}
},
"required": [
"name"
]
}
},
{
"name": "tickerbot_delete_strategy",
"description": "DELETE /v2/strategies/{name}. Remove a strategy. Subscribed webhooks become inactive once the strategy is gone; existing delivery rows are kept for audit.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
}
},
"required": [
"name"
]
}
},
{
"name": "tickerbot_strategy_history",
"description": "GET /v2/strategies/{name}/{ticker}/history/{interval}. Time-series of the strategy's condition value on a single ticker. Returns the condition evaluated at each bar for a given (strategy × ticker × interval). Same response shape as /v2/signals/{name}/{ticker}/history/{interval} — the dashboard chart overlay code handles both interchangeably.\n\nUseful for visualizing past firings before subscribing a webhook: write the condition, hit this endpoint, see when it would have fired.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
},
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"interval": {
"type": "string",
"description": "Bar resolution.",
"enum": [
"1m",
"1h",
"1d"
]
},
"from": {
"type": "integer",
"description": "Earliest epoch ms (inclusive). Defaults to interval-dependent lookback."
},
"to": {
"type": "integer",
"description": "Latest epoch ms (inclusive). Defaults to now."
},
"cursor": {
"type": "string",
"description": "Opaque cursor for pagination."
}
},
"required": [
"name",
"ticker",
"interval"
]
}
},
{
"name": "tickerbot_strategy_events",
"description": "GET /v2/strategies/{name}/{ticker}/events. Paired (start, end) spans where the condition was true. Returns the condition-true intervals as `(start_t, end_t)` pairs — efficient when you only need fire moments rather than the full per-bar series.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
},
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"from": {
"type": "integer",
"description": "Earliest epoch ms."
},
"to": {
"type": "integer",
"description": "Latest epoch ms."
},
"cursor": {
"type": "string",
"description": "Opaque cursor for pagination."
}
},
"required": [
"name",
"ticker"
]
}
},
{
"name": "tickerbot_strategy_backtest",
"description": "GET /v2/strategies/{name}/backtest. Walk historical bars maintaining position state; return paired trades. For strategies with exit policy, this walks bars in order and produces a series of (entry, exit, pnl, exit_reason) records the way a real trading bot would. With no exit policy, the strategy exits when the condition flips false; PnL is null unless `position_size` is supplied.\n\nDistinct from /history (per-bar boolean) and /events (condition-true spans). Backtest is the only one of the three that consumes the exit-policy fields.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
},
"ticker": {
"type": "string",
"description": "Ticker symbol to backtest on."
},
"interval": {
"type": "string",
"description": "Bar resolution. Defaults to 1d.",
"enum": [
"1m",
"1h",
"1d"
],
"default": "1d"
},
"from": {
"type": "integer",
"description": "Earliest epoch ms."
},
"to": {
"type": "integer",
"description": "Latest epoch ms."
},
"position_size": {
"type": "number",
"description": "Dollars per trade. When supplied, the PnL fields become absolute; otherwise PnL is expressed as percent."
}
},
"required": [
"name",
"ticker"
]
}
}
]Per-tool reference
One block per tool, indexed by name.
tickerbot_list_tickers
GET /v2/tickers
{
"name": "tickerbot_list_tickers",
"description": "GET /v2/tickers. List active tickers, paginated. Returns the universe of tracked symbols (~12,000 US equities + top 100 crypto by market cap) in alphabetical order with a slim payload (`ticker`, `name`, `asset_type`, `exchange`, `market_cap`). Use cursor pagination to walk the full list, or pass `?tickers=...` for bulk lookup of named symbols with full rows.",
"input_schema": {
"type": "object",
"properties": {
"tickers": {
"type": "string",
"description": "Comma-separated list of symbols (up to 50). When set, the response returns the full row for each requested symbol; pagination params are ignored. Symbols missing from our universe come back with `_not_found: true`."
},
"limit": {
"type": "integer",
"description": "Page size for the alphabetical walk. Max 1000.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response's `next_cursor` field. Continues the walk from after that page."
},
"search": {
"type": "string",
"description": "Substring filter over `ticker` (case-insensitive) and `name`. When set, results are ordered by `market_cap DESC NULLS LAST`."
},
"asset_type": {
"type": "string",
"description": "Filter by asset type — typically `equity` or `crypto`. Matched case-insensitively against the stored value."
},
"exchange": {
"type": "string",
"description": "Filter by exchange code (uppercase). Common values: `XNYS`, `XNAS`, `BATS`."
},
"sector": {
"type": "string",
"description": "Filter by sector name. Exact match against the stored `sector` field."
},
"min_market_cap": {
"type": "number",
"description": "Minimum market cap (USD). Results are ordered by `market_cap DESC NULLS LAST` when set."
}
}
}
}tickerbot_get_ticker
GET /v2/tickers/{ticker}
{
"name": "tickerbot_get_ticker",
"description": "GET /v2/tickers/{ticker}. Get the full current state of one ticker. Returns the entire ticker row. Every field on the schema page, including current values for all numeric signals and the current value of every boolean flag. Treat it as the authoritative current snapshot for a symbol.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Ticker symbol. Case-insensitive. Equities: exchange symbol (`AAPL`). Crypto: bare symbol (`BTC`)."
}
},
"required": [
"ticker"
]
}
}tickerbot_get_ticker_history
GET /v2/tickers/{ticker}/history
{
"name": "tickerbot_get_ticker_history",
"description": "GET /v2/tickers/{ticker}/history. Get the full ticker row as of a past date. Time-travel to any historical date and pull the whole wide row as it stood then, including the boolean flag values, technical indicators, and the most-recent fundamentals known on that date. Useful for backtests and \"what did we know\" reconstructions.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"asof": {
"type": "string",
"description": "Target date as `YYYY-MM-DD` or full ISO timestamp `YYYY-MM-DDTHH:MM:SSZ`. The response returns the most-recent daily snapshot on or before this date."
}
},
"required": [
"ticker",
"asof"
]
}
}tickerbot_get_ticker_events
GET /v2/tickers/{ticker}/events
{
"name": "tickerbot_get_ticker_events",
"description": "GET /v2/tickers/{ticker}/events. Discrete event log for one ticker. Returns splits, dividends, and analyst rating changes for the ticker, newest-first, in a unified envelope. Each event has a `ts`, a `kind`, and a `payload` whose shape depends on the kind.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"from": {
"type": "string",
"description": "Earliest event timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to your plan's history window."
},
"to": {
"type": "string",
"description": "Latest event timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to \"now\"."
},
"kind": {
"type": "string",
"description": "Filter by event kind.",
"enum": [
"split",
"dividend",
"rating_change"
]
},
"limit": {
"type": "integer",
"description": "Page size. Max 1000.",
"default": 100
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
},
"required": [
"ticker"
]
}
}tickerbot_get_signals_match
GET /v2/signals/{signal}
{
"name": "tickerbot_get_signals_match",
"description": "GET /v2/signals/{signal}. Find tickers that match a signal right now. Return the set of tickers where the named signal is true (for boolean flags) or where the numeric value satisfies a single-bounded condition. Sorted by signal value descending for numerics, alphabetically by ticker for booleans.",
"input_schema": {
"type": "object",
"properties": {
"signal": {
"type": "string",
"description": "A column on `ticker`. Boolean flags (e.g. `golden_cross_today`, `above_sma_50`) are detected automatically; numerics (e.g. `rsi_14`, `market_cap`, `pe_ratio`) require a condition."
},
"condition": {
"type": "string",
"description": "Required for numeric signals. Single bound, format `<op><value>`. Operators: `>`, `>=`, `=`, `!=`, `<`, `<=`. Examples: `>70`, `<=200`, `!=0`. Ignored for boolean flags."
},
"limit": {
"type": "integer",
"description": "Page size. Max 200.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
},
"required": [
"signal"
]
}
}tickerbot_get_signal_history
GET /v2/signals/{signal}/{ticker}/history/{interval}
{
"name": "tickerbot_get_signal_history",
"description": "GET /v2/signals/{signal}/{ticker}/history/{interval}. Time series of one signal for one ticker. Returns a sequence of `{t, v}` bars for the requested signal × ticker at the chosen resolution. `t` is an ISO timestamp (or `YYYY-MM-DD` for daily/weekly). `v` is the signal value at that bar (a number for numeric signals, `true`/`false` for boolean flags).",
"input_schema": {
"type": "object",
"properties": {
"signal": {
"type": "string",
"description": "A column on the wide-state tables (matches the schema page 1:1)."
},
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"interval": {
"type": "string",
"description": "Resolution. Daily-only signals (SMAs, RSI, MACD, fundamentals) are not stored at minute/hourly resolution; request `1d` for those.",
"enum": [
"1m",
"1h",
"1d",
"1w"
]
},
"from": {
"type": "string",
"description": "Earliest bar timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to your plan's history window."
},
"to": {
"type": "string",
"description": "Latest bar timestamp (inclusive). YYYY-MM-DD or ISO. Defaults to \"now\"."
},
"limit": {
"type": "integer",
"description": "Page size. Max 1000.",
"default": 252
},
"cursor": {
"type": "string",
"description": "Opaque cursor. Walks back in time page-by-page from the most-recent bar."
}
},
"required": [
"signal",
"ticker",
"interval"
]
}
}tickerbot_get_scan
GET /v2/scan
{
"name": "tickerbot_get_scan",
"description": "GET /v2/scan. Run a SQL WHERE against the current universe. Filter the live ticker universe with a SQL WHERE clause expressed in our SQL grammar. Returns matching tickers sorted by your chosen column. Columns in `q`, `order`, and `fields` are the customer-facing names listed on /api/schema and /api/flags. No translation layer.",
"input_schema": {
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "SQL WHERE expression. Required unless `rule` is supplied. Max 4000 chars. Semicolons, comments, and write-side keywords (INSERT/UPDATE/DELETE/DROP/etc.) are rejected."
},
"rule": {
"type": "string",
"description": "Slug of a saved rule (see `/v2/rules`). Its `q`, `universe_id`, `order`, `dir`, and `fields` become defaults; any of those passed as query-string parameters override."
},
"universe": {
"type": "string",
"description": "Slug of a system universe (`top_10`, `top_100`) or one of your own (`/v2/universes`). Scopes the scan to those tickers. When omitted, the scan runs across all ~12,000 tracked tickers."
},
"asof": {
"type": "string",
"description": "Optional. Run the WHERE against historical daily state for the given `YYYY-MM-DD` (or full ISO). Plan history depth applies."
},
"order": {
"type": "string",
"description": "Column to sort by. Must be a valid identifier (lowercase letters, digits, underscore).",
"default": "day_change_pct"
},
"dir": {
"type": "string",
"description": "Sort direction.",
"enum": [
"asc",
"desc"
],
"default": "desc"
},
"fields": {
"type": "string",
"description": "Comma-separated list of extra columns to include in each result row. Default columns are always present: ticker, name, asset_type, price, day_change_pct, gap_pct, relative_volume, market_cap."
},
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
}
}
}tickerbot_post_scan
POST /v2/scan
{
"name": "tickerbot_post_scan",
"description": "POST /v2/scan. Same as GET /v2/scan, with `q` in the body. POST mirror of `GET /v2/scan` for queries too long to fit in a URL. Accepts the same parameters (`q`, `order`, `dir`, `fields`, `limit`) in a JSON body. `cursor` continues to come from the query string for consistency with the GET pagination shape.",
"input_schema": {
"type": "object",
"properties": {
"q": {
"type": "string",
"description": "SQL WHERE expression."
},
"order": {
"type": "string",
"description": "Sort column."
},
"dir": {
"type": "string",
"description": "Sort direction.",
"enum": [
"asc",
"desc"
]
},
"fields": {
"type": "string",
"description": "Comma-separated extra columns."
},
"limit": {
"type": "integer",
"description": "Page size, max 100."
},
"cursor": {
"type": "string",
"description": "Opaque cursor (query string, not body)."
}
},
"required": [
"q"
]
}
}tickerbot_post_webhook
POST /v2/webhooks
{
"name": "tickerbot_post_webhook",
"description": "POST /v2/webhooks. Create a webhook subscription. Register a SQL WHERE clause (inline `q` or `rule_id`) + an HTTPS target URL. On the cadence configured for your plan, we evaluate the clause against the relevant ticker universe. When a new ticker enters the match set, we POST a `webhook.fired` event to your target. On creation we also send a one-shot `webhook.ping` to verify reachability; the subscription stays in `pending_verification` until the ping returns a 2xx response, then flips to `active`.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Human-readable label. Helps you find this webhook later in `GET /v2/webhooks`. Doesn't need to be unique."
},
"q": {
"type": "string",
"description": "SQL WHERE clause. Same grammar as `/v2/scan`. Either this or `rule_id` is required."
},
"rule_id": {
"type": "string",
"description": "Slug of a saved rule (see `/v2/rules`). The webhook stores a snapshot of the rule's `q` + `universe_id` at creation time."
},
"target_url": {
"type": "string",
"description": "HTTPS endpoint that will receive POSTed events. Must start with `https://`. Plain HTTP is rejected."
},
"cadence": {
"type": "string",
"description": "How often to evaluate this webhook. Defaults to your plan's fastest cadence; pick a slower one to conserve quota or smooth out noisy fires.",
"enum": [
"1m",
"5m",
"15m",
"hourly",
"nyse_open"
]
}
},
"required": [
"name",
"target_url"
]
}
}tickerbot_list_webhooks
GET /v2/webhooks
{
"name": "tickerbot_list_webhooks",
"description": "GET /v2/webhooks. List webhook subscriptions on this API key. Returns webhook subscriptions created by the current API key, newest-first. Visibility is key-scoped: webhooks created with a different key on the same account are not returned here. Use `?status=` to filter and the `cursor` field to paginate.",
"input_schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Filter by status.",
"enum": [
"active",
"pending_verification",
"disabled"
]
},
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
}
}
}tickerbot_get_webhook
GET /v2/webhooks/{id}
{
"name": "tickerbot_get_webhook",
"description": "GET /v2/webhooks/{id}. Fetch one webhook subscription. Returns the current state of a webhook subscription. Visibility is key-scoped: webhooks created by another key (even on the same account) return 404.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id returned by `POST /v2/webhooks`."
}
},
"required": [
"id"
]
}
}tickerbot_delete_webhook
DELETE /v2/webhooks/{id}
{
"name": "tickerbot_delete_webhook",
"description": "DELETE /v2/webhooks/{id}. Delete a webhook subscription. Hard delete. Any pending deliveries already enqueued may still fire (they capture the target URL + signing secret at queue time). To pause-rather-than-delete, just stop accepting deliveries at your target; after enough consecutive failures the subscription flips to `disabled`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
}
},
"required": [
"id"
]
}
}tickerbot_list_webhook_deliveries
GET /v2/webhooks/{id}/deliveries
{
"name": "tickerbot_list_webhook_deliveries",
"description": "GET /v2/webhooks/{id}/deliveries. Inspect recent deliveries for a webhook. Returns the most-recent deliveries (pings and fires) for a webhook, newest-first. Useful for diagnosing failures and verifying signatures. The full request body is not included; we keep them small.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
},
"status": {
"type": "string",
"description": "Filter by delivery status.",
"enum": [
"pending",
"delivered",
"permanent_failure"
]
},
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor."
}
},
"required": [
"id"
]
}
}tickerbot_enable_webhook
POST /v2/webhooks/{id}/enable
{
"name": "tickerbot_enable_webhook",
"description": "POST /v2/webhooks/{id}/enable. Re-enable a disabled or pending webhook. Resets a webhook back to `pending_verification`, clears its match-state cache (so the next eval treats every currently-matching ticker as new and fires a single `webhook.fired`), and re-enqueues the handshake ping. On 2xx the webhook flips to `active`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
}
},
"required": [
"id"
]
}
}tickerbot_test_fire_webhook
POST /v2/webhooks/{id}/test
{
"name": "tickerbot_test_fire_webhook",
"description": "POST /v2/webhooks/{id}/test. Send a one-off synthetic delivery for QA / smoke testing. Writes a pending `webhook.fired` delivery with `test: true` and an empty `matches` array. The scheduler picks it up on its next tick and POSTs the same headers + signature shape as a real firing — the only difference is the `test` flag in the body and on the delivery row. Useful for verifying your receiver is reachable, parses the payload correctly, and verifies the signature.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook id."
}
},
"required": [
"id"
]
}
}tickerbot_list_universes
GET /v2/universes
{
"name": "tickerbot_list_universes",
"description": "GET /v2/universes. List your universes. A universe is a named list of tickers you can reference from `/v2/scan?universe=`, `/v2/signals/{signal}?universe=`, `/v2/tickers?universe=`, and `/v2/webhooks`. System universes (`top_10` and `top_100`, the top-N most-actively-traded tickers, rebalanced monthly) are available to every account at `GET /v2/universes/system`.",
"input_schema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from the previous response."
}
}
}
}tickerbot_create_universe
POST /v2/universes
{
"name": "tickerbot_create_universe",
"description": "POST /v2/universes. Create a universe. Create a named ticker list owned by the calling account. Body: `{ id?, name, description?, tickers }`. If `id` is omitted, a slug is generated.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Optional slug. Lowercase letters, digits, underscore. Must be unique within your account."
},
"name": {
"type": "string",
"description": "Human-readable label."
},
"description": {
"type": "string",
"description": "Free-form notes."
},
"tickers": {
"type": "array",
"description": "Ticker symbols. Validated against your plan scope + the active universe.",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"tickers"
]
}
}tickerbot_list_system_universes
GET /v2/universes/system
{
"name": "tickerbot_list_system_universes",
"description": "GET /v2/universes/system. List system universes (top_10, top_100). System universes are read-only ticker lists rebalanced monthly by 30-day trailing dollar volume. Available to every account regardless of plan.",
"input_schema": {
"type": "object",
"properties": {}
}
}tickerbot_get_universe
GET /v2/universes/{id}
{
"name": "tickerbot_get_universe",
"description": "GET /v2/universes/{id}. Fetch a single universe. Returns the universe doc. Use `top_10`/`top_100` to fetch a system universe; any other slug must be one your account owns.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Universe slug."
}
},
"required": [
"id"
]
}
}tickerbot_patch_universe
PATCH /v2/universes/{id}
{
"name": "tickerbot_patch_universe",
"description": "PATCH /v2/universes/{id}. Update a universe. Update `name`, `description`, or `tickers`. To add/remove ticker subsets without replacing the full list, pass `{ add: [...], remove: [...] }` instead of `tickers`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Universe slug."
},
"name": {
"type": "string",
"description": "New label."
},
"description": {
"type": "string",
"description": "New notes."
},
"tickers": {
"type": "array",
"description": "Replace the full ticker list.",
"items": {
"type": "string"
}
},
"add": {
"type": "array",
"description": "Add these tickers (deduplicated).",
"items": {
"type": "string"
}
},
"remove": {
"type": "array",
"description": "Remove these tickers.",
"items": {
"type": "string"
}
}
},
"required": [
"id"
]
}
}tickerbot_delete_universe
DELETE /v2/universes/{id}
{
"name": "tickerbot_delete_universe",
"description": "DELETE /v2/universes/{id}. Delete a universe. Permanently delete one of your universes. System universes cannot be deleted.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Universe slug."
}
},
"required": [
"id"
]
}
}tickerbot_list_rules
GET /v2/rules
{
"name": "tickerbot_list_rules",
"description": "GET /v2/rules. List your saved rules. A rule is a saved `{q, universe_id?, order, dir, fields}` bundle. Rules can be referenced from `/v2/scan?rule=` (one-off run) and `/v2/webhooks` (subscribe to fires). Same SQL grammar as `/v2/scan`.",
"input_schema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Page size. Max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor."
}
}
}
}tickerbot_create_rule
POST /v2/rules
{
"name": "tickerbot_create_rule",
"description": "POST /v2/rules. Create a saved rule. Save a scan bundle so it can be re-run with `/v2/scan?rule=` or subscribed to via `/v2/webhooks`. The `universe_id` is optional; if unset, the rule runs against your plan default at execution time.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Optional slug."
},
"name": {
"type": "string",
"description": "Human-readable label."
},
"description": {
"type": "string",
"description": "Free-form notes."
},
"q": {
"type": "string",
"description": "SQL WHERE clause."
},
"universe_id": {
"type": "string",
"description": "Slug of a system or caller-owned universe to scope this rule."
},
"order": {
"type": "string",
"description": "Sort column.",
"default": "day_change_pct"
},
"dir": {
"type": "string",
"description": "Sort direction.",
"enum": [
"asc",
"desc"
]
},
"fields": {
"type": "array",
"description": "Extra columns to include.",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"q"
]
}
}tickerbot_get_rule
GET /v2/rules/{id}
{
"name": "tickerbot_get_rule",
"description": "GET /v2/rules/{id}. Fetch a saved rule. Returns the rule doc.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Rule slug."
}
},
"required": [
"id"
]
}
}tickerbot_patch_rule
PATCH /v2/rules/{id}
{
"name": "tickerbot_patch_rule",
"description": "PATCH /v2/rules/{id}. Update a saved rule. Update any field on a rule. To detach `universe_id` set it to `null`.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Rule slug."
}
},
"required": [
"id"
]
}
}tickerbot_delete_rule
DELETE /v2/rules/{id}
{
"name": "tickerbot_delete_rule",
"description": "DELETE /v2/rules/{id}. Delete a saved rule. Webhooks referencing this rule continue to fire using their snapshotted `q`; they don't break.",
"input_schema": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Rule slug."
}
},
"required": [
"id"
]
}
}tickerbot_create_strategy
POST /v2/strategies
{
"name": "tickerbot_create_strategy",
"description": "POST /v2/strategies. Create a user-defined condition, optionally with exit policy. A strategy is a saved boolean expression over the signal vocabulary (the same column names documented on /api/schema and /api/signals). It's queried per ticker at evaluation time — the same condition works on AAPL today and NVDA tomorrow.\n\nWithout exit policy fields, a strategy behaves as a \"watch\" — it emits a 'strategy.entered' event when the condition flips true on a ticker and a 'strategy.exited' event when it flips false. With exit policy, the strategy tracks position state per ticker: stop_loss_pct closes the position when price falls that percent below entry, take_profit_pct closes when price rises that percent above entry, and max_hold_bars closes after that many bars regardless. `exit_reason` on the exit event discriminates which path fired.\n\nThe condition is validated by the same compiler that runs at evaluation time — invalid expressions are rejected synchronously with structured errors. See /api/strategies/condition-grammar for the accepted syntax.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Slug — lowercase, [a-z0-9_], unique within your account."
},
"description": {
"type": "string",
"description": "Free-form notes."
},
"condition": {
"type": "string",
"description": "Boolean expression over signal columns. See /api/strategies/condition-grammar."
},
"stop_loss_pct": {
"type": "number",
"description": "Close the position when price drops this percent below entry. e.g. 0.05 = 5% stop-loss."
},
"take_profit_pct": {
"type": "number",
"description": "Close the position when price rises this percent above entry."
},
"max_hold_bars": {
"type": "integer",
"description": "Close the position after this many bars regardless of price. Bars are at the resolution of the consuming endpoint."
}
},
"required": [
"name",
"condition"
]
}
}tickerbot_get_strategy
GET /v2/strategies/{name}
{
"name": "tickerbot_get_strategy",
"description": "GET /v2/strategies/{name}. Fetch a saved strategy. Returns the strategy definition. Same shape as the POST response.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
}
},
"required": [
"name"
]
}
}tickerbot_list_strategies
GET /v2/strategies
{
"name": "tickerbot_list_strategies",
"description": "GET /v2/strategies. List all your strategies. Cursor-paginated, like other v2 listings.",
"input_schema": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description": "Page size, max 100.",
"default": 50
},
"cursor": {
"type": "string",
"description": "Opaque cursor from a prior response."
}
}
}
}tickerbot_patch_strategy
PATCH /v2/strategies/{name}
{
"name": "tickerbot_patch_strategy",
"description": "PATCH /v2/strategies/{name}. Edit condition, description, or exit policy. Partial update — only the fields you supply change. The condition is re-validated on every update.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug (immutable)."
},
"description": {
"type": "string",
"description": "New description."
},
"condition": {
"type": "string",
"description": "New condition. Re-validated."
},
"stop_loss_pct": {
"type": "number",
"description": "Send `null` to clear."
},
"take_profit_pct": {
"type": "number",
"description": "Send `null` to clear."
},
"max_hold_bars": {
"type": "integer",
"description": "Send `null` to clear."
}
},
"required": [
"name"
]
}
}tickerbot_delete_strategy
DELETE /v2/strategies/{name}
{
"name": "tickerbot_delete_strategy",
"description": "DELETE /v2/strategies/{name}. Remove a strategy. Subscribed webhooks become inactive once the strategy is gone; existing delivery rows are kept for audit.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
}
},
"required": [
"name"
]
}
}tickerbot_strategy_history
GET /v2/strategies/{name}/{ticker}/history/{interval}
{
"name": "tickerbot_strategy_history",
"description": "GET /v2/strategies/{name}/{ticker}/history/{interval}. Time-series of the strategy's condition value on a single ticker. Returns the condition evaluated at each bar for a given (strategy × ticker × interval). Same response shape as /v2/signals/{name}/{ticker}/history/{interval} — the dashboard chart overlay code handles both interchangeably.\n\nUseful for visualizing past firings before subscribing a webhook: write the condition, hit this endpoint, see when it would have fired.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
},
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"interval": {
"type": "string",
"description": "Bar resolution.",
"enum": [
"1m",
"1h",
"1d"
]
},
"from": {
"type": "integer",
"description": "Earliest epoch ms (inclusive). Defaults to interval-dependent lookback."
},
"to": {
"type": "integer",
"description": "Latest epoch ms (inclusive). Defaults to now."
},
"cursor": {
"type": "string",
"description": "Opaque cursor for pagination."
}
},
"required": [
"name",
"ticker",
"interval"
]
}
}tickerbot_strategy_events
GET /v2/strategies/{name}/{ticker}/events
{
"name": "tickerbot_strategy_events",
"description": "GET /v2/strategies/{name}/{ticker}/events. Paired (start, end) spans where the condition was true. Returns the condition-true intervals as `(start_t, end_t)` pairs — efficient when you only need fire moments rather than the full per-bar series.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
},
"ticker": {
"type": "string",
"description": "Ticker symbol."
},
"from": {
"type": "integer",
"description": "Earliest epoch ms."
},
"to": {
"type": "integer",
"description": "Latest epoch ms."
},
"cursor": {
"type": "string",
"description": "Opaque cursor for pagination."
}
},
"required": [
"name",
"ticker"
]
}
}tickerbot_strategy_backtest
GET /v2/strategies/{name}/backtest
{
"name": "tickerbot_strategy_backtest",
"description": "GET /v2/strategies/{name}/backtest. Walk historical bars maintaining position state; return paired trades. For strategies with exit policy, this walks bars in order and produces a series of (entry, exit, pnl, exit_reason) records the way a real trading bot would. With no exit policy, the strategy exits when the condition flips false; PnL is null unless `position_size` is supplied.\n\nDistinct from /history (per-bar boolean) and /events (condition-true spans). Backtest is the only one of the three that consumes the exit-policy fields.",
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Strategy slug."
},
"ticker": {
"type": "string",
"description": "Ticker symbol to backtest on."
},
"interval": {
"type": "string",
"description": "Bar resolution. Defaults to 1d.",
"enum": [
"1m",
"1h",
"1d"
],
"default": "1d"
},
"from": {
"type": "integer",
"description": "Earliest epoch ms."
},
"to": {
"type": "integer",
"description": "Latest epoch ms."
},
"position_size": {
"type": "number",
"description": "Dollars per trade. When supplied, the PnL fields become absolute; otherwise PnL is expressed as percent."
}
},
"required": [
"name",
"ticker"
]
}
}How to wire it up
The runtime calls the tool. Your code forwards to api.tickerbot.io.
When the LLM decides to call a tool, your code receives the tool name and arguments. Route the call to the matching Tickerbot endpoint (the endpoint field on each tool body above, or hard-coded in your handler), forward the bearer token, and return the JSON response to the LLM.
The OpenAPI spec covers anything generator-driven if your runtime isn't one of the three above.