Quick start
relaybell sends web push notifications to your users' browsers (desktop & Android) โ no app required. Two steps: add the SDK to collect subscribers, then call the API to send.
1. Add the SDK to your website
<script src="https://your-relaybell-host/relaybell-sdk.js"></script>
<script>
RelayBell.init({ projectId: "YOUR_PROJECT_ID", apiBase: "https://your-relaybell-host" });
</script>
Find your projectId in the dashboard under Settings โ API & SDK. The SDK shows your configured opt-in prompt and registers subscribers automatically.
sw.js service worker at your site root โ copy it from this server's /sw.js.2. Send a notification
curl -X POST https://your-relaybell-host/api/v1/notifications \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Hello ๐","body":"Your first push","url":"https://example.com"}'
Authentication
Server-to-server requests authenticate with a project API key as a Bearer token. Generate one in Settings โ API & SDK โ Generate API key (shown once โ store it securely).
Authorization: Bearer rb_live_xxxxxxxxxxxxxxxx
Public, browser-side endpoints (subscribe, opt-in config) need only the projectId and are called by the SDK for you.
Send a notification
POST /api/v1/notifications ยท auth: Bearer API key
Queues a notification; the response returns immediately and delivery happens asynchronously.
JavaScript (Node)
const res = await fetch("https://your-relaybell-host/api/v1/notifications", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.RELAYBELL_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Flash sale ๐ฅ",
body: "30% off ends tonight",
url: "https://shop.example.com/sale",
image: "https://cdn.example.com/sale.jpg",
actions: [{ action: "a0", title: "Shop now", url: "https://shop.example.com" }],
}),
});
const data = await res.json(); // { ok: true, notificationId, status }
Notification options
| Field | Type | Description |
|---|---|---|
title | string | Required. Notification title. |
body | string | Body text (plain text; emoji supported). |
url | string | Opened when the notification is clicked. |
icon | string (URL) | Small icon. Defaults to the project logo. |
image | string (URL) | Large hero image (Chrome/Edge/Android). |
badge | string (URL) | Monochrome status-bar badge (mobile). |
actions | array | Up to 2 buttons: [{ action, title, url }]. |
requireInteraction | boolean | Keep on screen until the user interacts. |
tag | string | Replace/group notifications with the same tag. |
segmentId | string | Send only to a saved segment (see Targeting). |
filters | object | Inline targeting rules (see Targeting). |
sendAt | ISO date | Schedule for a future time (see Scheduling). |
Targeting & segments
By default a send goes to all subscribers. Target a subset with a saved segmentId or inline filters.
{
"title": "Pricing update",
"filters": {
"match": "all",
"rules": [
{ "field": "country", "op": "eq", "value": "IN" },
{ "field": "url", "op": "contains", "value": "/pricing" },
{ "field": "tag:plan", "op": "eq", "value": "pro" }
]
}
}
Fields: country, language, url, tag:KEY. Ops: eq, neq, contains, exists, not_exists. Match: all or any.
Scheduling
Add sendAt (ISO 8601) to schedule for later. The response status will be scheduled.
{ "title": "Good morning โ๏ธ", "sendAt": "2026-06-24T03:30:00.000Z" }
Cancel a scheduled send: POST /api/v1/notifications/:id/cancel. Quiet hours (Settings) auto-defer immediate sends to the end of the window.
Tags & attributes
Attach custom data to subscribers from the browser to power segments:
RelayBell.setTags({ plan: "pro", city: "Mumbai" });
relaybell also auto-captures url (subscribe page), language, country (via CDN header), and device (desktop / android / ios).
Personalize with merge tags
Use any attribute or tag as a merge tag in a notification's title or body โ it is replaced per subscriber at send time. Add a fallback after a | for subscribers who don't have that value:
{"title":"Hi {name|there} ๐","body":"Your {city} order has shipped"}
Set the values first with RelayBell.setTags({ name: "Asha", city: "Mumbai" }). A token with no value and no fallback renders empty โ so always give a fallback for tags not every subscriber has.
Image uploads
Host an image on relaybell and use the returned URL as an icon or image:
POST /api/v1/upload โ multipart field file (PNG/JPG/GIF/WebP, โค2 MB), auth: Bearer API key โ { "url": "https://.../uploads/abc.png" }
SDK reference
RelayBell.init(options)
| Option | Description |
|---|---|
projectId | Required. Your project id. |
apiBase | Your relaybell host (e.g. https://push.relaybell.com). |
swPath | Service worker path (default /sw.js). |
externalId | Your own user id, to tie a subscriber to your system. |
tags | Initial tags object. |
RelayBell.setTags(tags) ยท RelayBell.subscribeNow()
setTags updates custom attributes; subscribeNow forces the native permission prompt + subscription.
Responses & errors
All responses are JSON. Successful sends return 202 Accepted:
{ "ok": true, "notificationId": "โฆ", "status": "queued" } // or "scheduled"
| Status | Meaning |
|---|---|
400 | Invalid request (e.g. missing title). |
401 | Missing/invalid API key. |
404 | Project or resource not found. |
202 | Accepted โ queued for delivery. |
Need the marketing dashboard instead? Open the dashboard โ