bzap

push notifications via webhook

one curl command away
terminal
$ curl -X POST https://bzap-server.fly.dev/v1/your_secret \
  -d '{"title":"Deploy","message":"v2.1 is live! 🚀"}'

{"message":"Notification sent"}
iPhone iPad Siri Shortcuts Privacy-First

Built for people who build things

Bzap fits into your workflow, whatever that looks like.

🏠

Home Automation

Motion alerts, leak detection, temperature drops. Tap a button on the notification to turn on lights or lock doors.

"Motion detected in garage"
→ [Turn On Lights] [Lock Door]
🚀

CI/CD Pipelines

Know the moment your build passes, deploy finishes, or tests fail. Approve deploys from the notification.

"Deploy v2.3.1 ready"
→ [Deploy to Prod] [Rollback]
🤖

AI Coding Sessions

Using Claude Code or Copilot? Get notified when tasks finish. Review and approve from your phone.

"feat: add auth — 12 tests pass"
→ [Approve] [Reject]
📡

Server Monitoring

Uptime checks, error spikes, disk warnings. Restart services or scale up with one tap.

"API down — 502 for 2 min"
→ [Restart] [Scale Up]
📜

Cron Jobs & Scripts

Long-running backups, data exports, ML training. Get pinged when done — or when they crash.

"Backup complete: 12.4 GB"
→ [View Log] [Dismiss]
🔔

Anything with HTTP

If it can make an HTTP request, it can send you a Bzap. Python, Node, Go, Bash, Zapier, n8n.

requests.post(url, json=
  {"message": "Hello!"})

Notifications that do things

Action buttons that fire webhooks back. Your phone becomes a remote control.

Bzap now
🚨 Motion Detected
Front porch camera — 11:42 PM
💡 Lights
🔒 Lock
🔊 Alarm

Close the loop

Other push apps are one-way. Bzap lets you respond.

  • include actions in your payload
  • each action has a response webhook
  • user taps → bzap fires the webhook
  • no app to open, just tap
payload.json
{
  "title": "Motion Detected",
  "message": "Front porch camera",
  "actions": [
    {
      "id": "lights",
      "label": "Turn On Lights",
      "webhook": "http://ha.local/api/lights"
    }
  ]
}

Everything you need, nothing you don't

Bzap is opinionated about simplicity.

Two-Way

Action buttons fire webhooks back

📲

QR Code

Share webhook as scannable QR

🗣

Siri

3 Shortcuts intents

📋

Templates

GitHub, Docker, Python...

🔍

Search

Full-text + JSON/CSV export

🔐

Private

Messages never stored on server

🖥

Multi-Platform

iPhone & iPad native

🎯

Per-Device

Target specific devices

API Reference

Simple REST API. JSON in, push notification out.

POST/v1/{secret}Send notification
POST/v1/sendSend (Bearer auth)
POST/v1/devices/registerRegister device
GET/v1/devicesList devices
DELETE/v1/devices/{id}Unregister
POST/v1/secret/rotateRotate secret
POST/v1/responses/{id}Submit response
GET/v1/responses/{id}Poll response
GET/status/{token}Public status page
POST/v1/heartbeat/{token}Send heartbeat ping
POST/v1/monitorsCreate monitor (Bearer)
GET/v1/monitorsList monitors (Bearer)
GET/v1/monitors/{id}/statsMonitor stats (Bearer)

Payload Fields

FieldTypeDescription
titlestringNotification title
subtitlestringSubtitle line
messagestringBody text
thread_idstringGroup by thread
soundstringNotification sound
open_urlstringURL to open when tapped
image_urlstringImage attachment
interruption_levelstringpassive / active / time-sensitive
actionsarrayAction buttons with response webhooks (max 4)

Action Buttons Example

Add up to 4 action buttons. Each button fires a webhook when tapped.

two-way-actions.sh
$ curl -X POST https://bzap-server.fly.dev/v1/your_secret \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Deploy Ready",
    "message": "v2.3.1 — all tests passing",
    "actions": [
      {
        "id": "deploy",
        "label": "Deploy to Prod",
        "webhook": "https://your-ci.com/deploy"
      },
      {
        "id": "rollback",
        "label": "Rollback",
        "webhook": "https://your-ci.com/rollback"
      }
    ]
  }'

{"message":"Notification sent"}

Response Channel

Two-way communication. Send a notification, get an answer back. Add response_channel: true to any action to enable polling for the user's response.

1. Approve / Reject Buttons

Ask a yes/no question. The response includes which button was tapped.

approve-reject.sh
# Step 1: Send notification with response_channel actions
$ curl -s -X POST https://bzap-server.fly.dev/v1/your_secret \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Deploy to Production?",
    "message": "v2.3.1 — all tests passing",
    "actions": [
      {"id": "approve", "label": "Approve", "response_channel": true},
      {"id": "reject", "label": "Reject", "destructive": true, "response_channel": true}
    ]
  }'

{"message":"Notification sent","response_id":"abc-123"}

# Step 2: Poll for the user's response (Bearer auth)
$ curl -s https://bzap-server.fly.dev/v1/responses/abc-123 \
  -H 'Authorization: Bearer your_secret'

# While waiting:
HTTP 202 {"status":"pending"}

# After user taps a button:
HTTP 200 {"status":"responded","action_id":"approve","device_name":"iPhone"}

2. Custom Choice Buttons

Up to 4 custom buttons. Each has its own id returned in the response.

custom-buttons.sh
$ curl -s -X POST https://bzap-server.fly.dev/v1/your_secret \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Which environment?",
    "message": "Ready to deploy feature-login",
    "actions": [
      {"id": "staging", "label": "Staging", "response_channel": true},
      {"id": "production", "label": "Production", "response_channel": true},
      {"id": "cancel", "label": "Cancel", "destructive": true, "response_channel": true}
    ]
  }'

{"message":"Notification sent","response_id":"def-456"}

# Poll → user taps "Production"
{"status":"responded","action_id":"production","device_name":"iPad"}

3. Free Text Input

Ask the user to type a response. Set type: "text_input" to show a text field when the button is tapped.

text-input.sh
$ curl -s -X POST https://bzap-server.fly.dev/v1/your_secret \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "What branch?",
    "message": "Which branch should I deploy?",
    "actions": [
      {
        "id": "reply",
        "label": "Reply",
        "type": "text_input",
        "text_input_placeholder": "Branch name...",
        "response_channel": true
      }
    ]
  }'

{"message":"Notification sent","response_id":"ghi-789"}

# Poll → user types "feature/login-v2"
{"status":"responded","action_id":"reply","text":"feature/login-v2","device_name":"iPhone"}

How It Works

1. Send a notification with response_channel: true on one or more actions.

2. The server returns a response_id — your ticket to poll for the answer.

3. Poll GET /v1/responses/{response_id} with Bearer auth.

202 while waiting

200 with the response (one-time read, then deleted)

404 if expired (5 min TTL)

4. Responses are one-time-read — after you get a 200, the row is deleted.

5. Actions can have both webhook and response_channel — the webhook fires immediately, and you can still poll.

Action Fields

FieldTypeDescription
idstringUnique action identifier (returned in response)
labelstringButton label shown to user
webhookstringURL to POST when tapped (optional)
destructiveboolShow button in red (optional)
response_channelboolEnable polling for this action's response
typestring"text_input" to show a text field
text_input_placeholderstringPlaceholder text for text input

Dead Man's Switch

Your service pings Bzap. If it stops, you get alerted.

How It Works

1. Create a Heartbeat monitor in the app — you get a unique ping URL.

2. Add a curl call to the end of your script, cron job, or pipeline.

3. If the ping stops arriving within the expected interval + grace period, Bzap sends you a push notification.

4. Respond from your lock screen — tap Restart, Acknowledge, or fire a webhook.

Use Cases

Cron Job Monitoring

Add a ping at the end of your cron script. If the job fails or hangs, no ping is sent and you get alerted.

backup.sh
#!/bin/bash
# Daily database backup
pg_dump mydb > /backups/$(date +%F).sql

# Tell Bzap we're alive
curl -s -X POST https://bzap-server.fly.dev/v1/heartbeat/your_token

CI/CD Pipeline

Ping after a successful deploy. If the pipeline breaks silently, you know.

.github/workflows/deploy.yml
- name: Deploy
  run: flyctl deploy --remote-only

- name: Heartbeat
  run: curl -s https://bzap-server.fly.dev/v1/heartbeat/your_token

Background Worker / Queue Processor

Ping after processing each batch. If the worker crashes or gets stuck, silence triggers the alert.

worker.py
while True:
    batch = queue.get_batch()
    process(batch)

    # Heartbeat after each batch
    requests.post("https://bzap-server.fly.dev/v1/heartbeat/your_token")

IoT / Raspberry Pi

A sensor or edge device pings every few minutes. Goes silent = offline.

sensor.sh (crontab: */5 * * * *)
# Read sensor + ping Bzap
TEMP=$(cat /sys/class/thermal/thermal_zone0/temp)
curl -s -X POST https://bzap-server.fly.dev/v1/heartbeat/your_token

AI Agent / Claude Code

An autonomous agent pings after each task. If it crashes or gets stuck, you get alerted on your phone.

agent-loop.sh
while true; do
  claude --task "$NEXT_TASK"
  curl -s https://bzap-server.fly.dev/v1/heartbeat/your_token
done

Configuration

SettingDescriptionDefault
intervalHow often you expect a ping (1, 5, or 15 min)5 min
grace_periodExtra wait time after interval before alertingSame as interval
failure_thresholdConsecutive misses before marking as down (1-10)3

Keyword Monitoring

For HTTP monitors, you can also check the response body for a keyword. Set the method to GET and provide a keyword — Bzap will alert if the keyword is missing (or present, if you choose "must NOT contain").

keyword-monitor.sh
# Create a monitor that checks for "healthy" in the response
$ curl -s -X POST https://bzap-server.fly.dev/v1/monitors \
  -H 'Authorization: Bearer your_secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "API Health",
    "url": "https://api.example.com/health",
    "interval": 60,
    "method": "GET",
    "keyword": "healthy",
    "keyword_should_exist": true
  }'

Use Bzap on Multiple Devices

iPhone + iPad. Same account, same notifications.

Recommended: Link Device (QR Code)

The most reliable way to set up a second device is the QR code flow. It works instantly, across any Apple ID, with no waiting:

On your existing device (the one that already has your account):

Settings → Link Device → Show QR Code

On your new device:

Settings → Link Device → Scan QR Code

The new device imports your account secret and registers itself with the server. Both devices will receive notifications from all your webhooks.

iCloud Keychain Sync

Bzap also syncs your account secret via iCloud Keychain in the background. If both devices share the same Apple ID with Passwords & Keychain enabled, the secret will eventually sync automatically.

However, this sync is not instant — it can take seconds to minutes depending on network conditions. If the new device launches before the sync completes, it will generate a new (separate) account. That's why QR linking is the recommended approach for the initial setup.

Once both devices share the same secret (via QR or sync), future changes like secret rotation will sync automatically via iCloud Keychain.

How It Works

Bzap uses a secret as your account identifier — no email, no password. Every device with the same secret is part of the same account. When a notification is sent to your webhook, the server pushes it to all registered devices.

Subscriptions are tied to your Apple ID via StoreKit, so they work across all your devices automatically — no extra steps needed.

Troubleshooting

IssueSolution
New device doesn't see my monitorsUse Link Device → Scan QR from your existing device. This is the fastest and most reliable method.
iCloud sync didn't workiCloud Keychain sync can be slow. Don't wait — use the QR code flow instead. Check Settings → Apple ID → iCloud → Passwords & Keychain is on for future syncs.
Different Apple IDs on devicesQR code flow works across any Apple ID — no iCloud needed
Subscription not showing on second deviceTap Restore Subscription on the Subscription page
Notifications only on one deviceMake sure push notifications are enabled in system settings on both devices

ready to go bzap? ⚡

Free to try. One webhook. Infinite possibilities.

⚡ Get Bzap