Skip to content

Sending notifications

POST https://api.pushbell.app/v1/messages. The body can be JSON, a form (application/x-www-form-urlencoded) or multipart/form-data. The key goes in the Authorization: Bearer header.

Field Description
title Title (up to 250 characters). If missing, the type’s title, otherwise the project name.
message Text (up to 4,000 characters, depending on your plan).
type, vars Notification type and template variables.
priority -2 silent record · -1 silent · 0 normal · 1 high (breaks through quiet hours) · 2 emergency (repeats until acknowledged).
sound Sound name: a built-in sound (cash, bell, alarm…), a custom sound you uploaded in the dashboard, vibrate or none. Pushover sound names work too.
url, url_title A link attached to the notification.
actions Up to 3 buttons (the number depends on your plan): {"title": "Open the door", "kind": "http", "url": "https://…"} or {"kind": "open_url", …}. open_url opens the link on the device. An http button’s address never reaches the device: when it’s tapped, the PushBell server sends a signed POST to it (webhook signature).
attachment (multipart), attachment_base64 + attachment_type, image_url An image. Attachments are processed (EXIF orientation applied, location and other metadata removed, longest side 1440 px), shown in the notification and the inbox, and deleted with the message.
timestamp The real time of the event (Unix seconds); shown instead of the time it was received.
group, badge Notification group (same thread on iOS, same group on Android) and app badge (a number or +1).
html, monospace Limited HTML (b, i, u, font color, a) or monospaced text.
to User (u_…) or group (g_…) keys. If missing, the project’s default audience.
device Only these device names or tags.
ttl Seconds: the notification is deleted from the devices and the inbox this long after delivery (e.g. one-time codes).
expire_at If it can’t be delivered by this time, it isn’t sent at all.
send_at Scheduled sending.

Response:

{ "status": 1, "id": "01a17a88-3ed9-76aa-9ed9-1b312156d5cc" }

Quota status comes in the response headers: X-Limit-App-Limit, X-Limit-App-Remaining, X-Limit-App-Reset (approximate).

In the dashboard you define types for a project (e.g. sale, alarm); give type in the request and the type’s settings apply:

  • Template: a title / text like {{amount}} sale, filled in from vars.
  • Sound, logo and color (the color is the notification’s color on Android).
  • Priority: for example, the alarm type can be an emergency. If the request has no priority, the type’s applies; if the type is an emergency, the repeat interval and duration come from the type too. In that case the receipt isn’t in the response; it shows in the dashboard’s message log and the message’s details.
  • Link, link title, buttons and ttl.
  • Summaries: notifications that arrive in a row are collected into one summary.

A field given in the request always wins over the type’s. After saving a type in the dashboard, Send to me shows it on your own devices; this test doesn’t count toward your quota.

Batch sending: POST /v1/messages/batch sends up to 500 notifications in one request; if one is invalid, none is queued. All fields are in the API reference.