API Reference
Gentle Push has a REST API for sending web push notifications with an API key. Using it is optional: the dashboard needs no code and the free plan is unlimited either way.
Complete reference for the Push REST API. Use bearer tokens for dashboard integrations or project API keys for server-side notification delivery.
Overview
The Gentle 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
Gentle 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 and email. 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>" }
}{
"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 },
}
}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. Native Android and iOS delivery is planned and not yet in use; tokens are accepted but nothing is sent to them today.
{
"platform": "android", // required: "android" | "ios"
"token": "APA91bH..." // required — FCM or APNs token
}// 200 OK
{ "success": true, "data": { "android": "APA91bH...", "ios": null } }