Pushpad

REST API for Web Push Notifications and Pushpad API

You can use the REST API to send web push notifications. You can also use it to automate any task that you would normally perform manually in the Pushpad dashboard (e.g. creating a project) or for advanced integrations (e.g. updating the tags associated to the subscriptions).

The REST API includes:

If you only need to send push notifications from your web app, which is the most common use case, you can also use the libraries.

Authentication and global headers

In order to use the REST API you must generate a token in your account settings.

The following headers must be present in every request:

Content-Type: application/json
Accept: application/json
Authorization: Token token="ACCESS_TOKEN"

Root endpoint

All the requests sent to the API must use this prefix:

https://pushpad.xyz/api/v1

Status codes and errors

The response codes from the API follow the standard HTTP semantics.

These are some of the most common status codes that can be returned by the API:

The successful status codes are described in more detail below for each endpoint.


Notifications API

POST /projects/PROJECT_ID/notifications

Send a web push notification.

Request

{
  "notification": {
    "body": "Hello world",
    "title": "My Website",
    "target_url": "https://example.com",
    "icon_url": "https://example.com/assets/icon.png",
    "badge_url": "https://example.com/assets/badge.png",
    "image_url": "https://example.com/assets/image.png",
    "ttl": 600,
    "require_interaction": true,
    "silent": false,
    "urgent": true,
    "custom_data": "",
    "actions": [
      {
        "title": "A button",
        "target_url": "https://example.com/button-link",
        "icon": "https://example.com/assets/button-icon.png",
        "action": "myActionName"
      }
    ],
    "starred": false,
    "send_at": "2016-07-06T10:09:00.000Z",
    "custom_metrics": ["metric1", "metric2"]
  },
  "uids": ["uid0", "uid1", "uidN"],
  "tags": ["tag0", "tag1", "tagA && !tagB"]
}

Response

201 Created
{
  "id": 197123, 
  "scheduled": 5, 
  "uids": ["uid0", "uid1", "uidN"]
}

GET /notifications/NOTIFICATION_ID

Get a notification and its stats.

Response

200 OK
{
  "id": 200, 
  "project_id": 123,
  "title": "Foo Bar", 
  "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", 
  "target_url": "https://example.com", 
  "icon_url": "https://example.com/assets/icon.png", 
  "badge_url": "https://example.com/assets/badge.png", 
  "image_url": "https://example.com/assets/image.png",
  "ttl": 604800,
  "require_interaction": false,
  "silent": false,
  "urgent": false,
  "custom_data": "",
  "custom_metrics": [],
  "actions": [],
  "starred": false,
  "uids": null,
  "tags": null,
  "send_at": "2016-07-06T10:09:00.000Z",
  "created_at": "2016-07-06T10:09:14.834Z",
  "scheduled_count": 0,
  "successfully_sent_count": 4, 
  "opened_count": 1
}

The following fields become available some seconds after the sending of the notification, when the deliveries have been fully scheduled:

You can read more about stats and their meaning in the Monitoring section.

For future notifications and cancelled notifications the stats are not available. The following fields are returned instead:

Note that notifications are stored on Pushpad for 35 days, then are removed.

GET /projects/PROJECT_ID/notifications

Lists the latest notifications.

Response

200 OK
[
  {
    "id": 212,
    "project_id": 123,
    "title": "Foo Bar",
    "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
    "target_url": "https://example.com",
    "icon_url": "https://example.com/assets/icon.png", 
    "badge_url": "https://example.com/assets/badge.png",
    "image_url": null,
    "ttl": 604800,
    "require_interaction": false,
    "silent": false,
    "urgent": false,
    "custom_data": "",
    "custom_metrics": [],
    "actions": [],
    "starred": false,
    "uids": ["uid0", "uid1", "uidN"],
    "tags": null,
    "send_at": null,
    "created_at": "2016-07-06T10:58:39.222Z",
    "scheduled_count": 0,
    "successfully_sent_count": 4,
    "opened_count": 1
  },
  {
    "id": 211,
    "project_id": 123,
    "title": "Foo Bar",
    "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
    "target_url": "https://example.com",
    "icon_url": "https://example.com/assets/icon.png", 
    "badge_url": "https://example.com/assets/badge.png",
    "image_url": "https://example.com/assets/image.png",  
    "ttl": 604800,
    "require_interaction": false,
    "silent": false,
    "urgent": false,
    "custom_data": "",
    "custom_metrics": ["metric1", "metric2"],
    "actions": [],
    "starred": false,
    "uids": null,
    "tags": ["tag1", "tagA && !tagB"],
    "send_at": "2016-07-06T10:09:00.000Z", 
    "created_at": "2016-07-06T10:58:39.192Z",
    "scheduled_count": 400,
    "successfully_sent_count": 4,
    "opened_count": 1
  }
]

You can pass these additional parameters in the query string of the URL:

Note that notifications are stored on Pushpad for 35 days, then are removed.

DELETE /notifications/NOTIFICATION_ID/cancel

Cancel a scheduled notification.

Response

204 No Content

Subscriptions API

GET /projects/PROJECT_ID/subscriptions

List the subscriptions.

Response

200 OK
[
  {
    "id": 1169, 
    "endpoint": "https://example.com/push/f7Q1Eyf7EyfAb1", 
    "p256dh": "BCQVDTlYWdl05lal3lG5SKr3VxTrEWpZErbkxWrzknHrIKFwihDoZpc_2sH6Sh08h-CacUYI-H8gW4jH-uMYZQ4=",
    "auth": "cdKMlhgVeSPzCXZ3V7FtgQ==",
    "uid": "exampleUid", 
    "tags": ["exampleTag1", "exampleTag2"],
    "last_click_at": "2023-11-03T10:30:00.000Z",
    "created_at": "2016-09-06T10:47:05.494Z"
  },
  {
    "id": 1117,
    "endpoint": "https://example.com/push/Q19f7EyfAb123u", 
    "p256dh": "BHhrxvu3G2__igFYiH_C0BTRL5TfLofea1jzpCanSkr7IpBwH7ydYyUHFv1jaD_vEzMVJhXemyG1LgbEjHAXpNY=",
    "auth": "Ob3K94ec0XgOF6UgaR8Tbw==",
    "uid": null,
    "tags": [],
    "last_click_at": null,
    "created_at": "2016-09-06T10:47:05.494Z"
  }
}

Warning: last_click_at is an experimental feature that was added on November 2023. All the clicks before that date were not recorded and null is returned.

You can pass these additional parameters in the query string of the URL:

For example you can search for a subscription of myUser1 with myTag1 or myTag2:

/projects/123/subscriptions?tags[]=myTag1&tags[]=myTag2&uids[]=myUser1

You can also use boolean expressions for tags. For example you can search all the subscriptions that match the expression tag1 && tag2 || !tag3 (remember to URL encode the special characters):

/projects/123/subscriptions?tags=tag1+%26%26+tag2+%7C%7C+%21tag3

If you just need to count the subscriptions that match a given query, you can make a HEAD request and read the X-Total-Count header.

GET /projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID

Show a subscription.

Response

200 OK
{
  "id": 1169, 
  "endpoint": "https://example.com/push/f7Q1Eyf7EyfAb1", 
  "p256dh": "BCQVDTlYWdl05lal3lG5SKr3VxTrEWpZErbkxWrzknHrIKFwihDoZpc_2sH6Sh08h-CacUYI-H8gW4jH-uMYZQ4=",
  "auth": "cdKMlhgVeSPzCXZ3V7FtgQ==",
  "uid": "exampleUid", 
  "tags": ["exampleTag1", "exampleTag2"], 
  "last_click_at": "2023-11-03T10:30:00.000Z",
  "created_at": "2016-09-06T10:47:05.494Z"
}

POST /projects/PROJECT_ID/subscriptions

Create or import a subscription.

This is not the standard way to collect subscriptions. Usually you collect subscriptions using the Javascript SDK.

Request

{
  "endpoint": "https://example.com/push/f7QEy7AAf71fICM:Af71Ey7AAAAf791bEjr",
  "p256dh": "BCQVDTlYWdl05lal3lG5SKr3VxTrEWpZErbkxWrzknHrIKFwihDoZpc_2sH6Sh08h-CacUYI-H8gW4jH-uMYZQ4=",
  "auth": "cdKMlhgVeSPzCXZ3V7FtgQ==",
  "uid": "123",
  "tags": ["tag1", "tag2"]
}

Response

201 Created

See GET for the response body.

PUT/PATCH /projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID

Update a subscription.

Request

{
  "uid": "123",
  "tags": ["tag1", "tag2"]
}

Response

200 OK

See GET for the response body.

DELETE /projects/PROJECT_ID/subscriptions/SUBSCRIPTION_ID

Delete a subscription.

Response

204 No Content

Projects API

GET /projects

List all projects.

Response

200 OK
[
  {
    "id": 339, 
    "sender_id": null, 
    "name": "Example Project 2", 
    "url": "https://pushpad.xyz/projects/339.json"
  }, 
  {
    "id": 338, 
    "sender_id": 123, 
    "name": "Example Project 1", 
    "url": "https://pushpad.xyz/projects/338.json"
  }
]

GET /projects/PROJECT_ID

Show project details and some stats.

Response

200 OK
{
  "id": 361,
  "sender_id": 123,
  "name": "Example Project",
  "website": "https://example.com",
  "icon_url": "https://example.com/icon.png",
  "badge_url": "https://example.com/badge.png",
  "created_at": "2016-07-06T10:58:39.143Z",
  "subscriptions_count": 4,
  "notifications_ttl": 604800,
  "notifications_require_interaction": false,
  "notifications_silent": false
}

POST /projects

Create a new project.

Request

{
  "sender_id": 123,
  "name": "My project",
  "website": "https://example.com",
  "icon_url": "https://example.com/icon.png"
}

Response

201 Created

See GET for the response body.

PUT/PATCH /projects/PROJECT_ID

Update project settings.

Request

{
  "name": "My project",
  "website": "https://example.com",
  "icon_url": "https://example.com/icon.png"
}

Response

200 OK

See GET for the response body.

DELETE /projects/PROJECT_ID

Delete a project asynchronously.

Response

202 Accepted

Senders API

GET /senders

List all senders.

Response

200 OK
[
  {
    "id": 174,
    "name": "My sender 2",
    "url": "https://pushpad.xyz/senders/174.json"
  },
  {
    "id": 173,
    "name": "My sender 1",
    "url": "https://pushpad.xyz/senders/173.json"
  }
]

GET /senders/SENDER_ID

Show sender settings.

Response

200 OK
{
  "id": 182,
  "name": "My sender",
  "created_at": "2016-07-06T11:28:21.266Z"
}

POST /senders

Create a sender.

Request

{
  "name": "My sender"
}

Response

201 Created

See GET for the response body.

PUT/PATCH /senders/SENDER_ID

Update sender settings.

Request

{
  "name": "My sender"
}

Response

200 OK

See GET for the response body.

DELETE /senders/SENDER_ID

Delete a sender. You cannot delete a sender if it has associated projects.

Response

204 No Content