Hooks and notifications
The shipped delivery surface (outcome hook endpoints, browser push, follows, alert watches), stated separately from the generic webhook channel — designed, not yet shipped in v1.
Two surfaces, one page, stated honestly. Outcome hook endpoints (/v1/hook-endpoints),
browser push, follows and alert watches are shipped and documented here. The generic
webhook channel — arbitrary event subscriptions, signed per target, delivery ledger and
retry budgets for any event — is designed, not yet shipped in v1. Nothing on this page
documents an endpoint that does not exist.
What exists today
| Surface | Routes | Status |
|---|---|---|
| Outcome hook endpoints | POST /v1/hook-endpoints, GET /v1/hook-endpoints | Shipped — paid add-on |
| Browser push | GET /v1/push/config, POST /v1/push/endpoints, GET /v1/push/endpoints | Shipped |
| Follows → resolution sentences | POST /v1/follows, GET /v1/follows | Shipped |
| Alert watches | GET /v1/alerts, POST /v1/alerts | Shipped — rides the alert engine's dedupe + cooldown law |
| Generic webhook channel | none | Designed, not yet shipped |
POST /v1/hook-endpoints — register an outcome endpoint
Registers (or idempotently replays) one payer-level endpoint. Every resolution that matches
your payer fires to it, signed X-Tollbridge-Signature (HMAC-SHA256). The per-endpoint secret
is returned once — store it; it is never shown again.
curl -X POST "https://api.tollbridge.app/v1/hook-endpoints" \
-H "x-tollbridge-payer: 0xYourAddress" \
-H "content-type: application/json" \
-d '{ "url": "https://example.com/hooks/tollbridge" }'- Price: one debit of the
billing.addon.hookadd-on (49,000 credits), ref = the endpoint id. Re-registering the same URL inside its 30-day window replays: no charge, secret not re-shown. After expiry, delete + re-register is the renewal (a new endpoint id, a new debit). - Registration never claims the hook is live. The response status is
registered. Delivery truth lives only in the append-only delivery record — one row per attempt. - URL safety: the address is checked at registration and re-checked before every fire — loopback, private ranges, link-local and metadata addresses are refused with a typed error.
- Secret storage: returned once; encrypted at rest (AES-256-GCM) when the deployment
configures a secret key, otherwise the deployment-wide signing secret is used. The record
keeps
nulleither way — never plaintext. - Cap: 10 active endpoints.
GET /v1/hook-endpoints — your endpoints and their delivery record
Your endpoints with delivery counts derived only from the append-only delivery rows
(registered / delivered / failing), never from optimism. Free; payer identity required.
curl "https://api.tollbridge.app/v1/hook-endpoints" \
-H "x-tollbridge-payer: 0xYourAddress"Pausing one endpoint is the identity-keyed DELETE — a soft stop; delivery history survives,
and a foreign id reads exactly like an unknown one (same typed 404).
GET /v1/push/config — is Web Push configured here?
Returns { configured, vapid_public_key }. configured: false with a null key is the honest
dark state: subscribe nothing, promise nothing.
curl "https://api.tollbridge.app/v1/push/config"POST /v1/push/endpoints / GET /v1/push/endpoints — your push devices
Register one browser push subscription (payer identity required; the endpoint URL must be
https and is safety-checked). Re-registering the same endpoint refreshes its keys and
re-enables it. The read lists your devices (host, timestamps, active flag — never a key);
the identity-keyed DELETE soft-stops one device (the row survives with disabled_at; a
re-subscribe re-enables it — a device is never silently deleted).
curl -X POST "https://api.tollbridge.app/v1/push/endpoints" \
-H "x-tollbridge-payer: 0xYourAddress" \
-H "content-type: application/json" \
-d '{ "subscription": { "endpoint": "https://fcm.googleapis.com/…", "keys": { "p256dh": "…", "auth": "…" } } }'
curl "https://api.tollbridge.app/v1/push/endpoints" \
-H "x-tollbridge-payer: 0xYourAddress"POST /v1/follows / GET /v1/follows — follow one question
Follow one (question × subject): on resolution the worker delivers the resolution sentence on every channel you enabled (channel bitmask 1=push, 2=email, 4=telegram). Delivery requires the deployment to have that channel configured — an unconfigured channel fails visibly, never silently. Engagement state only: no probability, prompt or threshold ever rides these rows.
curl -X POST "https://api.tollbridge.app/v1/follows" \
-H "x-tollbridge-payer: 0xYourAddress" \
-H "content-type: application/json" \
-d '{ "question_id": "S05_volatility_expansion", "subject_kind": "asset", "subject": "BTC", "channels": 1 }'
curl "https://api.tollbridge.app/v1/follows" \
-H "x-tollbridge-payer: 0xYourAddress"Unfollow is the identity-key DELETE (question × subject) — idempotent; removing nothing is
data, not an error. Re-following is idempotent and updates the channel bitmask.
GET /v1/alerts / POST /v1/alerts — alert watches
Watch a subject on the alert engine: kind (one of the seven engine kinds), asset or address,
and for probability kinds your own threshold. A threshold gates notifications only — it
never changes any published judgment. Delivery rides the same dedupe and cooldown law as
operator alerts, out to your push devices. Cap 50 active watches (typed 409 beyond).
curl -X POST "https://api.tollbridge.app/v1/alerts" \
-H "x-tollbridge-payer: 0xYourAddress" \
-H "content-type: application/json" \
-d '{ "kind": "probability", "subject_kind": "asset", "subject": "ETH", "threshold": 0.7 }'
curl "https://api.tollbridge.app/v1/alerts" \
-H "x-tollbridge-payer: 0xYourAddress"The identity-keyed DELETE stops one watch — a soft unsubscribe; the row that documented the
watch survives.
What does not exist yet (the generic webhook channel)
- No arbitrary event subscription endpoint, no per-target signing scheme for third-party targets beyond the outcome hook above, no exposed retry budget for generic events. We will not document endpoints that do not exist.
Roadmap (in order)
- Generic event subscriptions on top of the shipped delivery worker — queued → sent / failed with retry budgets, signed per target.
- Event vocabulary beyond resolutions (ladder turns, releases, rung crossings) on the same channel.
- Policy wiring —
action: "webhook"policy verdicts enqueue deliveries automatically.
Until that ships, use the shipped surfaces above, or re-run deterministic replays — see Decisions.