Push Notifications
Send push notifications to mobile devices (iOS, Android) and web browsers through a unified API. You can send notifications via the API and manage push configuration through the Dashboard.
Supported Platforms
| Platform | Provider | Setup Required |
|---|---|---|
| iOS | Apple Push Notification service (APNs) | APNs auth key or certificate |
| Android | Firebase Cloud Messaging (FCM) | FCM server key |
| Web | Web Push (VAPID) | VAPID keys (auto-generated) |
Quick Start
Send a Push Notification
curl -X POST https://api.zyphr.dev/v1/push \
-H "X-API-Key: zy_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_123",
"title": "New Message",
"body": "You have a new message from John"
}'
Using Node.js SDK
import { Zyphr } from '@zyphr-dev/node-sdk';
const zyphr = new Zyphr({ apiKey: process.env.ZYPHR_API_KEY });
// Send to all devices for a user
await zyphr.push.send({
user_id: 'user_123',
title: 'New Message',
body: 'You have a new message',
data: {
type: 'message',
message_id: 'msg_456',
},
});
// Or send to a specific device
await zyphr.push.send({
device_id: 'device_abc',
title: 'New Message',
body: 'You have a new message',
});
Device Registration
Before sending push notifications, devices must be registered:
curl -X POST https://api.zyphr.dev/v1/devices \
-H "X-API-Key: zy_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_123",
"token": "fcm_or_apns_token_here",
"platform": "ios",
"app_version": "1.0.0",
"os_version": "17.0"
}'
// Register a device (typically called from your mobile/web app)
await zyphr.devices.register({
subscriber_id: 'sub_123',
token: 'fcm_or_apns_token_here',
platform: 'ios', // 'ios' | 'android' | 'web'
app_version: '1.0.0',
os_version: '17.0',
});
See Device Management for more details.
Push Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | string | Conditional | User to send to (all their devices). Exactly one of user_id or device_id is required. |
device_id | string | Conditional | Specific device to send to. Exactly one of user_id or device_id is required. |
title | string | Conditional | Notification title. At least one of title, body, or data is required. |
body | string | Conditional | Notification body text |
data | object | No | Custom data payload |
badge | number | No | Badge count (iOS) |
sound | string | No | Sound to play |
image_url | string | No | Image URL to display |
content_available | boolean | No | Silent/background push (data only, no visible alert) |
action_buttons | array | No | Interactive action buttons (max 3). Each: { id, title, action?, deep_link? } |
tags | string[] | No | Tags for filtering and analytics (max 10) |
metadata | object | No | Custom metadata |
Platform-Specific Options
iOS (APNs)
curl -X POST https://api.zyphr.dev/v1/push \
-H "X-API-Key: zy_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_123",
"title": "New Message",
"body": "Content here",
"badge": 5,
"sound": "default"
}'
await zyphr.push.send({
user_id: 'user_123',
title: 'New Message',
body: 'Content here',
badge: 5,
sound: 'default',
});
Android (FCM)
await zyphr.push.send({
user_id: 'user_123',
title: 'New Message',
body: 'Content here',
image_url: 'https://yourapp.com/image.png',
data: {
click_action: 'OPEN_MESSAGE',
},
});
Web Push
await zyphr.push.send({
user_id: 'user_123',
title: 'New Message',
body: 'Content here',
image_url: 'https://yourapp.com/image.png',
action_buttons: [
{ id: 'view', title: 'View' },
{ id: 'dismiss', title: 'Dismiss' },
],
});
Silent Push
Send data-only notifications that don't display to the user:
curl -X POST https://api.zyphr.dev/v1/push \
-H "X-API-Key: zy_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_123",
"content_available": true,
"data": {
"type": "sync",
"resource": "messages"
}
}'
await zyphr.push.send({
user_id: 'user_123',
content_available: true,
data: {
type: 'sync',
resource: 'messages',
},
});
Device Management
List User Devices
curl https://api.zyphr.dev/v1/devices?user_id=user_123 \
-H "X-API-Key: zy_live_your_key"
const { data: devices } = await zyphr.devices.list({ user_id: 'user_123' });
for (const device of devices) {
console.log(`${device.platform}: ${device.last_seen_at}`);
}
Unregister a Device
curl -X DELETE https://api.zyphr.dev/v1/devices/device_abc \
-H "X-API-Key: zy_live_your_key"
// Called when user logs out or uninstalls
await zyphr.devices.delete('device_abc');
Handle Invalid Tokens
Zyphr automatically handles invalid/expired tokens:
- When a push fails due to invalid token, the device is marked inactive
- Webhook event
device.unregisteredis sent - Device is excluded from future sends
Push Status
| Status | Description |
|---|---|
queued | Push accepted and queued |
sending | Being sent to provider |
sent | Accepted by APNs/FCM |
delivered | Delivered to device (when available) |
failed | Permanent failure |
Viewing Messages
Via Dashboard
- Navigate to Push in the sidebar
- The Messages tab shows all sent push notifications with status and delivery info
- Click on any message to view full details including device info and delivery events
Via API
# List push messages
curl "https://api.zyphr.dev/v1/push?page=1&per_page=25" \
-H "X-API-Key: zy_live_your_key"
# Get a specific push message
curl https://api.zyphr.dev/v1/push/PUSH_ID \
-H "X-API-Key: zy_live_your_key"
# Get delivery events
curl -X POST https://api.zyphr.dev/v1/push/PUSH_ID/events \
-H "X-API-Key: zy_live_your_key"
Managing Devices
Via Dashboard
- Navigate to Push in the sidebar
- Switch to the Devices tab
- View all registered devices with their platform, name, and last seen date
- Unlink or delete devices as needed
Via API
# List devices
curl "https://api.zyphr.dev/v1/devices?user_id=user_123" \
-H "X-API-Key: zy_live_your_key"
# Unregister a device
curl -X DELETE https://api.zyphr.dev/v1/devices/device_abc \
-H "X-API-Key: zy_live_your_key"
Provider Setup
Configure push providers through the Dashboard or the API.
Supported Providers
| Platform | Provider | Credentials Required |
|---|---|---|
| Android | Firebase Cloud Messaging (FCM) | Firebase Project ID, Service Account Email, Private Key |
| iOS | Apple Push Notification service (APNs) | Key ID, Team ID, Private Key (.p8), Bundle ID, Production flag |
| Web | Web Push (VAPID) | VAPID Subject, Public Key, Private Key |
Adding a Provider
Via Dashboard
- Navigate to Push → Providers in the sidebar
- Click Add Provider
- Select the provider (FCM, APNs, or Web Push)
- Enter the required credentials
- Click Add Provider to save
From the Providers page you can also edit, delete, and monitor the health of each provider.
Via API
# Set push provider config
curl -X POST https://api.zyphr.dev/v1/providers/push_provider/config \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider": "fcm",
"credentials": {
"project_id": "YOUR_PROJECT_ID",
"service_account_email": "...",
"private_key": "..."
}
}'
# Get current push provider config
curl https://api.zyphr.dev/v1/providers/push_provider/config \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
iOS (APNs)
To configure APNs:
- In the Apple Developer Portal, create an APNs Auth Key (
.p8file) - Note your Key ID (10-character string) and Team ID (from your Apple Developer account)
- In Zyphr, add the Apple Push Notification service provider
- Paste the contents of your
.p8key file into the Private Key field - Enter your Key ID, Team ID, and app Bundle ID (e.g.,
com.yourapp.ios) - Set Production to
truefor production APNs gateway, orfalsefor sandbox
Android (FCM)
To configure FCM:
- In the Firebase Console, go to Project Settings → Service Accounts
- Click Generate New Private Key to download a service account JSON file
- In Zyphr, add the Firebase Cloud Messaging provider
- Enter the Project ID, Service Account Email (
client_email), and Private Key (private_key) from the JSON file
Web Push (VAPID)
To configure Web Push:
- Generate VAPID keys (or use existing ones from your web app)
- In Zyphr, add the Web Push (VAPID) provider
- Enter your VAPID Subject (a
mailto:orhttps:URL identifying the sender) - Enter your VAPID Public Key and VAPID Private Key
Your web application uses the VAPID public key to create push subscriptions:
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: 'YOUR_VAPID_PUBLIC_KEY',
});
Provider Health
Monitor provider health from the Push Providers page. Each provider has independent health tracking with a circuit breaker:
- Healthy — Normal operation
- Degraded — Experiencing intermittent failures
- Circuit Open — Temporarily disabled after repeated failures (auto-recovers after 5 minutes)
Topics
Send to all subscribers of a topic:
// Subscribe a device to a topic
await zyphr.devices.subscribeToTopic('device_abc', 'promotions');
// Send to all topic subscribers
await zyphr.push.sendToTopic('promotions', {
title: 'Flash Sale!',
body: '50% off everything today',
});
See Topics for more details.
Webhooks
Receive real-time push events:
{
"event": "push.delivered",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"message_id": "push_abc123",
"device_id": "device_xyz",
"platform": "ios",
"status": "delivered"
}
}
Error Handling
| Error Code | Description | Solution |
|---|---|---|
credentials_not_configured | Push credentials not set up | Configure in Settings |
invalid_token | Device token is invalid | Device will be unregistered |
device_not_found | Device ID doesn't exist | Check device registration |
user_has_no_devices | User has no registered devices | Wait for device registration |