Documentation
WebhookPush turns any webhook into a push notification on your phone. Point a service at your private URL — the moment it fires, you get a push and the message lands in your inbox.
Quickstart
1. Create a webhook (in the iOS app: Webhooks → New webhook, or on the web dashboard). Your secret is shown once — copy it right away.
2. Send a POST to your ingest URL:
curl -X POST https://d1yykmxdakarpv.cloudfront.net/ingest/<webhookId> \
-H "x-webhook-secret: <your-secret>" \
-H "Content-Type: application/json" \
-d '{"title":"Deploy done","body":"build #42 ✓"}'3. The push arrives on every registered device and the message is kept in your inbox (retention depends on your plan).
Authentication — three modes
- Header secret (default): send
x-webhook-secretwith every call. - URL secret: enable "URL secret (?secret=)" on the webhook, then append
?secret=<your-secret>to the URL — for services that can't send custom headers (TradingView, some monitors). - No secret: switch "Require secret" off — the unguessable URL is the only credential. Rotate by deleting/recreating the webhook.
Lost the secret? Rotate secret reveals a fresh one (the old one stops working immediately).
TradingView
TradingView webhooks can't send custom headers, so use the URL secret:
- 1. On your webhook, enable "URL secret (?secret=)".
- 2. Copy the full URL —
https://d1yykmxdakarpv.cloudfront.net/ingest/<id>?secret=<secret>(shown when the secret is revealed). - 3. In TradingView: Alert → Notifications → Webhook URL → paste it.
- 4. Set the alert Message to JSON for a clean notification:
{"title":"{{ticker}}","body":"Crossed {{close}}"}Plain text also works — it's delivered as-is as the notification body. - 5. Optional — put an "Open in TradingView" button on the message. Send the symbol and exchange as their own fields:
{"symbol":"{{ticker}}","exchange":"{{exchange}}","price":"{{close}}"}then set the webhook's Link template to reference them:https://www.tradingview.com/chart/?symbol={{ payload.exchange }}:{{ payload.symbol }}Keep the JSON values quoted: an empty TradingView variable otherwise renders"price": ,and the whole payload fails to parse. On iOS the link opens the TradingView app when it's installed.
Message format
title— notification title (falls back to the webhook name).body— notification body (falls back to the raw text, then the full payload).- Non-JSON bodies are kept as text — nothing is dropped.
- Report failures with
?status=fail(or"status":"fail"in the payload) plus anerrorfield — the notification shows the error and, with monitoring on, fires an alert.
Templates
Per-webhook title/body templates shape the notification from any payload with {{ payload.field }} placeholders. Mix literal text with as many placeholders as you like — e.g. a title of FX {{ payload.repo }} {{ payload.status }}. Leave the body template empty to deliver the full payload.
Fields & nesting
Reach any depth with dots, and index arrays with brackets. A missing field (or missing parent) renders to nothing rather than erroring.
{{ payload.title }}
{{ payload.data.subtitle }} # nested, any depth
{{ payload.b.c.d }}
{{ payload.items[0] }} # array indexFilters
Pipe a value through one or more filters with |. Unknown filters are ignored (the value passes through unchanged).
{{ payload.title | default: "Alert" }} # fallback when empty/missing (alias: or)
{{ payload.side | upper }} # UPPERCASE (also: lower, title)
{{ payload.price | round: 2 }} # 3.14159 -> 3.14
{{ payload.ts | date }} # ISO 8601
{{ payload.ts | date: "short" }} # 2026-07-11 (also: "time")
{{ payload.sym | default: "?" | upper }} # chain them left-to-rightExtra variables
Beyond payload, templates can reference the webhook itself and the current time.
{{ webhook.name }} # this webhook's name
{{ now }} # delivery time
{{ now | date: "short" }} # 2026-07-11Conditionals
Show a section only when a field is present (non-empty), or compare it with == / !=. An optional {{else}} branch handles the other case.
{{#if payload.error}}❌ {{ payload.error }}{{else}}✅ ok{{/if}}
{{#if payload.status == "down"}}ALERT{{/if}}
{{#if payload.env != "prod"}}(test){{/if}}Safe by design
Templates are never executed as code — only these placeholders and filters are substituted. Malformed syntax (an unclosed {{ or {{#if}}) is left as plain text, and output is capped at 2,000 characters. If a template renders to nothing, the notification falls back to the payload's own title/body (then the webhook name), so you never get a blank push.
Monitoring (dead-man's-switch)
Enable Monitor on a webhook with an interval + grace period: if the webhook isn't called within that window, you get an alert — perfect for cron jobs and backups that should check in regularly. A successful ping clears the alert state.
AI & MCP
WebhookPush connects to Claude and ChatGPT over MCP, so an agent can push to your phone — and block on your actual answer before it carries on. Connect a hosted connector with one URL, or run the local server with npx.
Full guide: the MCP connector.
Plans & limits
- Free — 50 calls/day, 7-day history.
- Starter — 100 calls/day, 14-day history.
- Pro — 1,000 calls/day, 90-day history, 7-day free trial.
- Enterprise — custom limits, 1-year history.
Over-quota calls return 402 with an upgrade link; short bursts are smoothed by a per-webhook burst guard (429). See pricing for details.
Questions? Contact us.