API Reference
Complete reference for the Push REST API. Use bearer tokens for dashboard integrations or project API keys for server-side notification delivery.
Overview
The Push API is a RESTful HTTP API returning JSON. All endpoints are scoped tohttps://api.push.yourdomain.com in production (or http://localhost:4000 in development).
https://api.push.yourdomain.comAuthentication
Push supports two authentication mechanisms. Both are accepted on all protected endpoints.
Obtained from POST /auth/verify-code. Valid for 7 days. Use for dashboard and user-scoped actions.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI...Project-level key from the dashboard. Use for server-side notification delivery.
x-api-key: pk_live_a1b2c3d4e5f6...Errors
All errors follow a consistent shape with an HTTP status code and JSON body:
// 400 Bad Request
{
"success": false,
"error": "Email is required"
}
// 401 Unauthorized
{
"success": false,
"error": "Invalid or expired code"
}
// 404 Not Found
{
"success": false,
"error": "Project not found"
}| Status | Meaning |
|---|---|
200 | Success |
400 | Bad request — missing or invalid fields |
401 | Unauthenticated — missing or invalid credentials |
403 | Forbidden — resource belongs to another entity |
404 | Not found |
500 | Internal server error |
Authentication Endpoints
/auth/request-codePublicSends a 6-digit one-time code to the provided email address. The code expires after 10 minutes.
{
"email": "[email protected]" // required
}// 200 OK
{
"success": true,
"message": "Code sent"
}/auth/verify-codePublicVerifies the OTP code. Automatically creates a Customer account and default Project if this is a first-time login. Returns a signed JWT valid for 7 days.
{
"email": "[email protected]", // required
"code": "483920" // required — 6-digit OTP
}// 200 OK
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI...",
"customer": { "id": 1, "email": "[email protected]", "name": null },
"project": { "id": 1, "name": "My Project", "api_key": "pk_..." }
}/auth/me🔑 Auth requiredReturns the authenticated customer profile and their default project.
// 200 OK
{
"success": true,
"customer": { "id": 1, "email": "[email protected]" },
"project": { "id": 1, "name": "My Project", "api_key": "pk_..." }
}Projects
/projects🔑 Auth requiredLists all projects belonging to the authenticated customer.
// 200 OK
{
"success": true,
"projects": [
{ "id": 1, "name": "My Project", "api_key": "pk_a1b2c3..." }
]
}/projects🔑 Auth requiredCreates a new project. An API key is automatically generated.
{
"name": "My New Project" // required
}// 200 OK
{
"success": true,
"project": { "id": 2, "name": "My New Project", "api_key": "pk_..." }
}/projects/:id🔑 Auth requiredRenames an existing project. Only the owning customer can update it.
{
"name": "Renamed Project" // required, non-empty
}// 200 OK
{
"success": true,
"project": { "id": 2, "name": "Renamed Project" }
}/projects/:id/regenerate-key🔑 Auth requiredInvalidates the current API key and issues a new one. The old key immediately stops working.
// 200 OK
{
"success": true,
"apiKey": "pk_new_a1b2c3d4..."
}/projects/branding🔑 Auth requiredFetches branding settings for the project in the auth context (from token or API key). Does not require an :id param.
// 200 OK
{
"success": true,
"projectId": 1,
"branding": {
"brandName": "Acme Corp",
"iconUrl": "https://acme.com/icon.png",
"badgeUrl": "https://acme.com/badge.png",
"heroImageUrl": "https://acme.com/hero.jpg",
"themeColor": "#0070F3"
}
}/projects/branding🔑 Auth requiredUpserts branding for the project in the auth context. All fields are optional — omit any field to leave it unchanged.
{
"brandName": "Acme Corp", // optional
"iconUrl": "https://...", // optional — used as notification icon
"badgeUrl": "https://...", // optional — used as notification badge
"heroImageUrl": "https://...", // optional — subscribe page hero
"themeColor": "#0070F3" // optional — hex color
}// 200 OK
{
"success": true,
"branding": { ...updatedBranding }
}/projects/:id/brandingPublicPublic endpoint — fetches branding for any project by ID. Used by hosted subscribe pages to apply your brand. When called with auth, performs ownership verification.
// 200 OK
{
"success": true,
"branding": { "brandName": "Acme Corp", ... }
}/projects/:id/analytics🔑 Auth requiredReturns aggregated analytics for a project: subscriber count, notification metrics, CTR, top-performing notifications, and subscriber growth over time.
// 200 OK
{
"success": true,
"analytics": {
"totalSubscribers": 142,
"notificationsSent": 58,
"impressions": 3420,
"clicks": 210,
"ctr": 6.14,
"topNotifications": [
{ "notificationId": "uuid", "clicks": 87, "impressions": 1200 }
],
"subscriberGrowth": [
{ "date": "2026-03-01", "count": 3 },
{ "date": "2026-03-02", "count": 7 }
]
}
}Subscribers
/subscribers/registerPublicRegisters a browser push subscription for a project. Called automatically by the Push service worker when a user opts in. Deduplicates by endpoint — re-registration of an existing endpoint updates metadata.
{
"projectId": 1, // required
"subscription": { // required — PushSubscription object
"endpoint": "https://fcm.googleapis.com/...",
"keys": {
"p256dh": "BNcRd...",
"auth": "tBHIt..."
}
},
"browser": "Chrome", // optional
"os": "Windows", // optional
"deviceType": "desktop" // optional
}// 200 OK
{
"success": true,
"subscriberId": 42,
"subscriber": {
"id": 42,
"projectId": 1,
"browser": "Chrome",
"os": "Windows",
"deviceType": "desktop",
"createdAt": "2026-03-01T10:00:00.000Z"
}
}/subscribers🔑 Auth requiredLists all subscribers scoped to the authenticated project (API key) or customer (JWT).
// 200 OK
{
"success": true,
"subscribers": [
{ "id": 42, "browser": "Chrome", "deviceType": "desktop", "createdAt": "..." }
]
}/subscribers🔑 Auth requiredManually creates or updates a subscriber record. Upserts by subscription endpoint.
{
"subscription": { // required
"endpoint": "https://...",
"keys": { "p256dh": "...", "auth": "..." }
},
"browser": "Firefox", // optional
"deviceType": "mobile" // optional
}// 200 OK
{ "success": true, "subscriber": { "id": 43, ... } }/subscribers/:id🔑 Auth requiredDeletes a subscriber. The subscriber must belong to the authenticated project or customer.
// 200 OK
{ "success": true, "deleted": 1 }Notifications
/notifications/send🔑 Auth requiredSends a notification. Supports four channels: web, mobile, email, and sms. Project branding is automatically applied to web notifications (icon, badge, title prefix).
POST /notifications/send
Content-Type: application/json
x-api-key: pk_live_...
{
"type": "web",
"target": { "all": true },
"payload": {
"title": "New feature launched 🎉",
"body": "Click to learn more",
"clickUrl": "https://yourdomain.com/features",
"icon": "https://yourdomain.com/icon.png", // optional, falls back to branding
"badge": "https://yourdomain.com/badge.png", // optional
"image": "https://yourdomain.com/banner.png", // optional
"data": { "custom": "value" } // optional
}
}{
"type": "web",
"target": { "subscriberIds": [42, 43, 44] },
"payload": { "title": "Hello!", "body": "..." }
}{
"type": "web",
"target": {
"endpoint": "https://fcm.googleapis.com/...",
"keys": { "p256dh": "BNcRd...", "auth": "tBHIt..." }
},
"payload": { "title": "Hello!", "body": "Direct push" }
}{
"type": "mobile",
"target": { "platform": "android", "token": "fcm_token_..." },
"payload": { "title": "Update available", "body": "v2.0 is here", "data": {} }
}{
"type": "email",
"target": "[email protected]",
"payload": { "subject": "Your order shipped", "body": "<p>Track your order...</p>" }
}{
"type": "sms",
"target": "+14155552671",
"payload": { "message": "Your verification code is 482910" }
}{
"success": true,
"results": [
{ "subscriberId": 42, "success": true },
{ "subscriberId": 43, "success": false, "error": "Subscription expired" }
]
}{ "success": true, "data": { ...providerResponse } }
// or on failure:
{ "success": false, "error": { "type": "delivery_failure", "message": "..." } }/notifications/history🔑 Auth requiredReturns all notification records for the authenticated project, ordered newest first.
// 200 OK
{
"success": true,
"data": [
{
"id": "uuid-1234",
"type": "web",
"payload": { "title": "...", "body": "..." },
"status": "delivered",
"recipientCount": 42,
"createdAt": "2026-03-20T14:30:00.000Z"
}
]
}/notifications/test/sendPublicExercises all configured notification providers using test tokens from environment variables (TEST_WEB_SUBSCRIPTION, TEST_FCM_TOKEN, etc.). Used for integration testing and provider health checks.
// 200 OK
{
"success": true,
"data": {
"web": { ...result },
"mobile": { ...result },
"email": { ...result },
"sms": { ...result }
}
}Events
/events/trackPublicRecords a notification lifecycle event. Called automatically by the Push service worker on the end-user's browser. Valid event types are delivered, shown, and clicked.
{
"notificationId": "uuid-1234", // required
"subscriberId": 42, // required
"eventType": "clicked", // required: "delivered" | "shown" | "clicked"
"projectId": 1, // optional but recommended for ownership check
"userAgent": "Mozilla/5.0 ...", // optional
"timestamp": "2026-03-20T14:31:00Z"// optional — defaults to now
}// 200 OK
{ "success": true }/events/subscriber/:id🔑 Auth requiredReturns all events for a specific subscriber, ordered newest first.
// 200 OK
{
"success": true,
"events": [
{ "id": 1, "notificationId": "uuid", "eventType": "clicked", "createdAt": "..." }
]
}/events/notifications/:notificationId🔑 Auth requiredReturns the full detail view for a single notification: its record, aggregated metrics (delivery, impressions, clicks, CTR), and the raw event timeline.
// 200 OK
{
"success": true,
"notification": { "id": "uuid", "type": "web", "payload": {}, "createdAt": "..." },
"metrics": {
"delivery": 42,
"impressions": 38,
"clicks": 12,
"ctr": 31.58
},
"timeline": [
{ "eventType": "delivered", "subscriberId": 1, "createdAt": "..." },
{ "eventType": "clicked", "subscriberId": 1, "createdAt": "..." }
]
}Customers
POST /customers endpoint creates accounts without auth. The GET|PUT|DELETE /customers/:id endpoints currently do not enforce ownership — access is gated only by valid authentication./customersPublicCreates a new customer account. If a customer with the same email already exists, the existing record is returned. Includes an auto-generated customer-level API key.
{
"name": "Acme Corp", // optional
"email": "[email protected]", // optional — used for deduplication
"phone": "+14155552671" // optional
}// 200 OK
{
"success": true,
"customer": {
"id": 1,
"name": "Acme Corp",
"email": "[email protected]",
"apiKey": "ck_..."
}
}/customers/me🔑 Auth requiredReturns the customer record for the owner of the provided API key. Uses customer-level API key (x-api-key) only — bearer tokens are not accepted on this endpoint.
// 200 OK
{ "success": true, "customer": { "id": 1, "name": "...", "email": "..." } }/customers/regenerate-key🔑 Auth requiredRegenerates and returns a new customer-level API key. Requires customer-level x-api-key authentication.
// 200 OK
{ "success": true, "apiKey": "ck_new_..." }/customers/:id🔑 Auth requiredFetches a customer record by ID.
// 200 OK
{ "success": true, "data": { "id": 1, "name": "...", "email": "..." } }/customers/:id🔑 Auth requiredPartially updates a customer record.
{
"name": "New Name", // optional
"email": "[email protected]", // optional
"phone": "+1...", // optional
"preferences": {}, // optional — arbitrary JSON object
"device_tokens": {} // optional — arbitrary JSON object
}// 200 OK
{ "success": true, "data": { "changes": 1 } }/customers/:id🔑 Auth requiredPermanently deletes a customer record and all associated data.
// 200 OK
{ "success": true }/customers/:id/device-token🔑 Auth requiredRegisters or updates a mobile device token (FCM for Android, APNs for iOS) for a customer. Stores tokens by platform.
{
"platform": "android", // required: "android" | "ios"
"token": "APA91bH..." // required — FCM or APNs token
}// 200 OK
{ "success": true, "data": { "android": "APA91bH...", "ios": null } }