Skip to main content

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

PlatformProviderSetup Required
iOSApple Push Notification service (APNs)APNs auth key or certificate
AndroidFirebase Cloud Messaging (FCM)FCM server key
WebWeb 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

ParameterTypeRequiredDescription
user_idstringConditionalUser to send to (all their devices). Exactly one of user_id or device_id is required.
device_idstringConditionalSpecific device to send to. Exactly one of user_id or device_id is required.
titlestringConditionalNotification title. At least one of title, body, or data is required.
bodystringConditionalNotification body text
dataobjectNoCustom data payload
badgenumberNoBadge count (iOS)
soundstringNoSound to play
image_urlstringNoImage URL to display
content_availablebooleanNoSilent/background push (data only, no visible alert)
action_buttonsarrayNoInteractive action buttons (max 3). Each: { id, title, action?, deep_link? }
tagsstring[]NoTags for filtering and analytics (max 10)
metadataobjectNoCustom 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:

  1. When a push fails due to invalid token, the device is marked inactive
  2. Webhook event device.unregistered is sent
  3. Device is excluded from future sends

Push Status

StatusDescription
queuedPush accepted and queued
sendingBeing sent to provider
sentAccepted by APNs/FCM
deliveredDelivered to device (when available)
failedPermanent failure

Viewing Messages

Via Dashboard

  1. Navigate to Push in the sidebar
  2. The Messages tab shows all sent push notifications with status and delivery info
  3. 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

  1. Navigate to Push in the sidebar
  2. Switch to the Devices tab
  3. View all registered devices with their platform, name, and last seen date
  4. 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

PlatformProviderCredentials Required
AndroidFirebase Cloud Messaging (FCM)Firebase Project ID, Service Account Email, Private Key
iOSApple Push Notification service (APNs)Key ID, Team ID, Private Key (.p8), Bundle ID, Production flag
WebWeb Push (VAPID)VAPID Subject, Public Key, Private Key

Adding a Provider

Via Dashboard

  1. Navigate to PushProviders in the sidebar
  2. Click Add Provider
  3. Select the provider (FCM, APNs, or Web Push)
  4. Enter the required credentials
  5. 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:

  1. In the Apple Developer Portal, create an APNs Auth Key (.p8 file)
  2. Note your Key ID (10-character string) and Team ID (from your Apple Developer account)
  3. In Zyphr, add the Apple Push Notification service provider
  4. Paste the contents of your .p8 key file into the Private Key field
  5. Enter your Key ID, Team ID, and app Bundle ID (e.g., com.yourapp.ios)
  6. Set Production to true for production APNs gateway, or false for sandbox

Android (FCM)

To configure FCM:

  1. In the Firebase Console, go to Project SettingsService Accounts
  2. Click Generate New Private Key to download a service account JSON file
  3. In Zyphr, add the Firebase Cloud Messaging provider
  4. 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:

  1. Generate VAPID keys (or use existing ones from your web app)
  2. In Zyphr, add the Web Push (VAPID) provider
  3. Enter your VAPID Subject (a mailto: or https: URL identifying the sender)
  4. 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 CodeDescriptionSolution
credentials_not_configuredPush credentials not set upConfigure in Settings
invalid_tokenDevice token is invalidDevice will be unregistered
device_not_foundDevice ID doesn't existCheck device registration
user_has_no_devicesUser has no registered devicesWait for device registration