API reference · Webhooks
Create a subscription
POST/v1/subscriptions
Follow phrases on an event, or one market by ticker, and optionally have every hit posted to your webhook, signed.
On this page
Auth. An API token: Authorization: Bearer lb_… (create one). Signed-in web sessions work too.
Limits. Each subscription counts toward your plan's subscriptions (5, 25 or 200); a new webhook URL toward its webhook endpoints (1, 5 or unlimited).
Parameters
Body
| Name | Type | Required | Description |
|---|---|---|---|
event_id | string | no | The event to follow (ev_…). Send this with phrases, or market alone. |
phrases | array of string | no | Phrase keys to follow on the event. |
subjects | array of string | no | Typed-fact subjects to receive (fact_extracted). |
webhook_url | string | no | An HTTPS URL to post each hit to. |
context | array of string | no | Context kinds to receive about the market: on_air, topic, near_miss, typed. |
market | string | no | A market ticker. Langbot follows that market's phrases on the event that settles it. |
Request
curl -X POST "https://api.langbot.ai/v1/subscriptions" \
-H "Authorization: Bearer $LANGBOT_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"market": "KXEARNINGSMENTIONNVDA-26OCT-BLACKWELL", "webhook_url": "https://example.com/hooks/langbot"}'from langbot import LangbotClient
async with LangbotClient() as lb: # reads LANGBOT_API_TOKEN
sub = await lb.subscribe_market(
"KXEARNINGSMENTIONNVDA-26OCT-BLACKWELL", webhook_url="https://example.com/hooks/langbot"
)
print(sub.id, sub.phrases)import { LangbotClient } from "@langbotai/sdk";
const lb = new LangbotClient(); // reads LANGBOT_API_TOKEN
const sub = await lb.subscribeMarket("KXEARNINGSMENTIONNVDA-26OCT-BLACKWELL", {
webhookUrl: "https://example.com/hooks/langbot",
});
console.log(sub.id);Response
201 Created
{
"id": "sub_01J9…",
"user_id": "usr_01J9…",
"event_id": "ev_nvda_q3_2026",
"phrases": ["blackwell"],
"subjects": [],
"webhook_url": "https://example.com/hooks/langbot",
"secret": "9c1f…",
"created_at": 1760050000000,
"market_ticker": "KXEARNINGSMENTIONNVDA-26OCT-BLACKWELL",
"context": [],
"market": { "ticker": "KXEARNINGSMENTIONNVDA-26OCT-BLACKWELL", "venue": "kalshi", "event_id": "ev_nvda_q3_2026", "title": "Will NVIDIA say \"Blackwell\" on its Q3 earnings call?", "status": "open", "phrases": ["blackwell"], "close_ts": 1760058000000 },
"market_title": "Will NVIDIA say \"Blackwell\" on its Q3 earnings call?"
}Webhook delivery. Each hit is a POST of the event JSON to webhook_url with X-Langbot-Signature: sha256=<hex HMAC-SHA256 of the raw body, keyed with secret>. Up to 4 attempts, 1 s, 4 s and 16 s apart; any 2xx acknowledges. Without a webhook_url, hits land in your dashboard inbox.
import { createHmac, timingSafeEqual } from "node:crypto";
const expected = `sha256=${createHmac("sha256", secret).update(rawBody).digest("hex")}`;
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-langbot-signature"]));Errors
| Status | code | When |
|---|---|---|
| 404 | not_found | Unknown event or market. |
| 422 | validation_error | The market is not yet attached to a live event, or the body mixes market with event_id. |
| 401 | auth_required | No token was sent. |
| 401 | token_invalid | The token was not recognised (mistyped, revoked or expired). |
| 402 | quota_exceeded | Your plan's subscriptions or webhook endpoints are all in use; delete one or move up a plan. |
| 429 | rate_limited | Over your request budget; wait Retry-After seconds. |
Every error body is {"detail": …, "code": "…"}; branch on code. All codes: Errors.