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-secret with 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 URLhttps://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.

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 an error field — 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 index

Filters

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-right

Extra 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-11

Conditionals

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.

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.