A webhook is a saved SQL WHERE clause with a delivery target. Once a minute, we evaluate every webhook against the live universe and POST one event to each whose match set just gained new tickers. This is the API analog of the mobile product's alerts.
The pattern, end-to-end
Three steps. Step one is the only API call you make.
Create the webhook with POST /v1/webhooks. Provide a name, the SQL query, and an HTTPS URL we’ll deliver to.
We watch the universe. Once a minute, every tracked ticker is evaluated against your query. Tickers that transition from not-matching to matching since last evaluation are batched into a single webhook.fired event.
You receive the event. Verify the HMAC signature, idempotently process the matches by X-Tickerbot-Delivery-Id, return 2xx within 10 seconds.
A ticker that's already in the match set isn't re-fired on subsequent evaluations. It only re-fires after exiting and re-entering — same state-change deduplication as the mobile product. There's no event for tickers exiting the match set; the API only fires on becoming-true.
Create a webhook
POST/v1/webhooks
Create a webhook that POSTs to your URL when tickers start matching.
Each webhook is a saved SQL `WHERE` clause plus a `target_url` we POST to. We evaluate the query once a minute against the live universe. If any tickers transitioned from not-matching to matching since the last evaluation, we send one POST containing all of them. Tickers that have already been matching aren’t re-fired until they exit the match set and re-enter (state-change deduplication, same as the mobile product).
Webhooks are gated to the Reads + Webhooks plan or higher.
Authentication required
Body parameters
Name
In
Type
Required
Description
name
body
string
required
Human-readable label. Helps you find this webhook later in `GET /v1/webhooks`. Doesn’t need to be unique.
Example: small-cap gappers
q
body
string (SQL WHERE clause)
required
The condition to fire on. Same shape as `/v1/scan?q=`.
Example: gap_up_3pct AND volume_unusual_2x AND market_cap < 2000000000 AND NOT earnings_this_week
target_url
body
string (https URL)
required
HTTPS endpoint we POST events to. HTTP is rejected.
Example: https://yourapp.com/hooks/gappers
Responses
Status
Description
201
Webhook created. Response includes a `signing_secret` — store it; it is not shown again.
400
SQL parse error, invalid URL, or invalid name.
403
Webhooks require the Read+Write+Realtime plan.
Create a small-cap-gappers webhook
Request
curl -X POST https://api.tickerbot.io/v1/webhooks \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "small-cap gappers",
"q": "gap_up_3pct AND volume_unusual_2x AND market_cap < 2000000000 AND NOT earnings_this_week",
"target_url": "https://yourapp.com/hooks/gappers"
}'
Response · 201
{
"id": "wh_8f3a2b",
"name": "small-cap gappers",
"q": "gap_up_3pct AND volume_unusual_2x AND market_cap < 2000000000 AND NOT earnings_this_week",
"target_url": "https://yourapp.com/hooks/gappers",
"signing_secret": "whsec_5f8e4b1d3a2c9e7f6b5d4a3c2b1e0f9d",
"status": "pending_verification",
"created_at": "2026-04-30T14:40:00Z"
}
List webhooks
GET/v1/webhooks
List every webhook owned by the current API key.
Returns webhooks newest-first. `signing_secret` is omitted from list responses for security.
Authentication required
Query parameters
Name
In
Type
Required
Description
status
query
string
optional
Filter by status. Allowed: `active`, `pending_verification`, `disabled`.
List delivery attempts for one webhook — when it fired, what we got back.
Every POST we send to your `target_url` is recorded as a delivery, including retries (the same `id` covers all attempts on a single event). Use this to debug: which events fired, did your endpoint accept them, what status code did we see, what error if any. Newest-first.
Authentication required
Path parameters
Name
In
Type
Required
Description
id
path
string
required
Webhook identifier.
Example: wh_8f3a2b
Query parameters
Name
In
Type
Required
Description
status
query
string
optional
Filter by delivery status. Allowed: `pending`, `delivered`, `permanent_failure`.
Re-enable a disabled or stuck webhook. Re-fires the verification ping.
A webhook flips to `disabled` after 5 failed delivery retries. Once you’ve fixed your endpoint, call this to put it back into rotation. We reset the verification handshake — status goes to `pending_verification`, we POST a fresh `webhook.ping`, and on a 2xx response within 10 seconds the webhook flips to `active`. Past match-state is cleared, so the next evaluation cycle treats every currently-matching ticker as a new match (you’ll get one `webhook.fired` payload with everything currently matching).
Authentication required
Path parameters
Name
In
Type
Required
Description
id
path
string
required
Webhook identifier.
Example: wh_8f3a2b
Responses
Status
Description
200
Webhook re-enabled. Returns the updated webhook object.
404
Webhook not found, or owned by a different key.
Re-enable a disabled webhook
Request
curl -X POST https://api.tickerbot.io/v1/webhooks/wh_8f3a2b/enable \
-H "Authorization: Bearer YOUR_KEY"
Response · 200
{
"id": "wh_8f3a2b",
"name": "small-cap gappers",
"q": "gap_up_3pct AND volume_unusual_2x AND market_cap < 2000000000 AND NOT earnings_this_week",
"target_url": "https://yourapp.com/hooks/gappers",
"status": "pending_verification",
"created_at": "2026-04-30T14:40:00Z"
}
Delivery: headers
Every webhook delivery includes these headers. Inspect them in your handler to route events and verify authenticity.
Header
Description
Content-Type
Always `application/json`.
User-Agent
Always `Tickerbot-Webhooks/1.0`.
X-Tickerbot-Event
The event name (`webhook.fired` or `webhook.ping`). Useful for routing in your handler.
X-Tickerbot-Delivery-Id
Unique identifier for this delivery attempt. Stable across retries — use it for idempotency.
X-Tickerbot-Webhook-Id
The webhook that produced this event.
X-Tickerbot-Signature
HMAC-SHA256 signature in the form `t=<unix-timestamp>,v1=<hex-digest>`. The signed payload is `<timestamp>.<raw-body>` with the webhook’s `signing_secret` as the key.
Delivery: signature verification
HMAC-SHA256, Stripe-style. Reject any request that doesn’t verify.
The X-Tickerbot-Signature header has the form t=<unix-timestamp>,v1=<hex-digest>. To verify a delivery:
Extract the timestamp and signature from the header.
Concatenate <timestamp>, a literal ., and the raw request body.
Compute HMAC-SHA256(signing_secret, payload) as a hex string.
Compare with the v1 value using a constant-time comparison.
Reject deliveries whose timestamp is more than 5 minutes from your server's current time — that's the replay window.
We retry failed deliveries at exponential intervals. After all attempts fail the webhook transitions to disabled.
Attempt
Delay after previous
1
30 seconds
2
2 minutes
3
10 minutes
4
1 hour
5
6 hours
Retries reuse the same X-Tickerbot-Delivery-Id as the original attempt — use it to deduplicate on your side.
Event types
The shapes of every payload your endpoint may receive.
webhook.ping
A webhook is created. Sent once. If the target returns 2xx within 10 seconds, the webhook transitions from `pending_verification` to `active`.
Field
Type
Description
event
string
Always `webhook.ping`.
webhook_id
string
The webhook that just got created.
name
string
The webhook’s human-readable name.
as_of
timestamp (ISO 8601)
When the webhook was created.
message
string
Human-readable handshake message.
Example payload
{
"event": "webhook.ping",
"webhook_id": "wh_8f3a2b",
"name": "small-cap gappers",
"as_of": "2026-04-30T14:40:00Z",
"message": "If you can read this, your endpoint is reachable."
}
webhook.fired
Tickers newly entered the webhook’s match set during the last evaluation cycle (one minute). One POST per evaluation cycle that has at least one new match — never an empty payload, never one POST per ticker. Tickers that were already matching at the previous evaluation are not re-fired.
Field
Type
Description
event
string
Always `webhook.fired`.
webhook_id
string
The webhook that produced this event.
name
string
The webhook’s human-readable name.
q
string
The WHERE clause that matched (snapshot at delivery time).
as_of
timestamp (ISO 8601)
The evaluation cycle’s timestamp. The same value applies to every ticker in this payload.
matches
array
The tickers that just entered the match set. Each entry includes the ticker symbol, name, and the fields referenced in the WHERE clause at the moment of match.