REST API Reference
Direct HTTP API access for server-side integrations
Use the REST API to integrate Pushary with any language or platform. All endpoints require authentication via API key.
Base URL
https://pushary.com/api/v1/serverAuthentication
All server API endpoints require a full API key passed via the Authorization header:
Authorization: Bearer pk_xxx.sk_xxxThe API key consists of two parts:
pk_xxx- Public prefix (site key)sk_xxx- Secret portion (never expose client-side)
Example Request
curl -X GET https://pushary.com/api/v1/server/subscribers \
-H "Authorization: Bearer pk_abc123.sk_secret456"Authentication Errors
| Status | Error | Description |
|---|---|---|
| 401 | Unauthorized | Missing or invalid API key |
{
"error": "Unauthorized",
"message": "Invalid or missing API key. Use Authorization: Bearer pk_xxx.sk_xxx"
}Rate Limiting
Rate limits vary by plan and are applied per API key:
| Plan | Requests/minute |
|---|---|
| Free | 5 |
| Starter | 25 |
| Growth | 100 |
| Enterprise | 500 |
Rate Limit Headers
Every response includes rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1704067200Rate Limit Exceeded
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please retry after 60 seconds.",
"retryAfter": 60
}Pagination
List endpoints support cursor-based pagination:
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
limit | integer | 100 | 500 | Number of items per page |
cursor | string | - | - | Cursor for next page |
Response Format
{
"data": [...],
"hasMore": true,
"nextCursor": "abc123"
}Paginating Results
curl "https://pushary.com/api/v1/server/subscribers?limit=50&cursor=abc123" \
-H "Authorization: Bearer pk_xxx.sk_xxx"Send Notifications
Send push notifications directly to subscribers.
POST /send
curl -X POST https://pushary.com/api/v1/server/send \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "New Message",
"body": "You have a new notification",
"url": "https://example.com/messages"
}'Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Notification title |
body | string | Yes | Notification body text |
url | string | No | Click action URL |
iconUrl | string | No | Custom icon URL |
imageUrl | string | No | Large image URL |
subscriberIds | string[] | No | Target specific subscribers |
externalIds | string[] | No | Target by external user IDs |
tags | string[] | No | Target by subscriber tags |
Targeting
If no targeting parameters are provided, the notification is sent to all active subscribers.
curl -X POST https://pushary.com/api/v1/server/send \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Welcome Back!",
"body": "We missed you",
"externalIds": ["user_123", "user_456"]
}'Response
{
"success": true,
"campaignId": "camp_abc123",
"sent": 150,
"limits": {
"remaining": 9850,
"limit": 10000
}
}Subscribers
Manage push notification subscribers.
List Subscribers
GET /subscribersQuery Parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Items per page (default: 100, max: 500) |
cursor | string | Pagination cursor |
status | string | Filter by status: active, unsubscribed, expired, bounced |
externalId | string | Filter by external ID |
tags | string | Comma-separated tags filter |
Example
curl "https://pushary.com/api/v1/server/subscribers?status=active&limit=50" \
-H "Authorization: Bearer pk_xxx.sk_xxx"Response
{
"data": [
{
"id": "sub_abc123",
"siteId": "site_xyz",
"status": "active",
"externalId": "user_123",
"tags": ["premium", "newsletter"],
"browser": "Chrome",
"os": "Windows",
"country": "US",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
],
"hasMore": true,
"nextCursor": "sub_def456"
}Get Subscriber
GET /subscribers/:idcurl https://pushary.com/api/v1/server/subscribers/sub_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx"Update Subscriber
PATCH /subscribers/:idcurl -X PATCH https://pushary.com/api/v1/server/subscribers/sub_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"tags": ["premium", "early-access"],
"externalId": "user_456",
"customData": {"plan": "pro"}
}'Request Body
| Field | Type | Description |
|---|---|---|
tags | string[] | Update subscriber tags |
externalId | string | Update external identifier |
customData | object | Custom metadata |
Delete Subscriber
DELETE /subscribers/:idcurl -X DELETE https://pushary.com/api/v1/server/subscribers/sub_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx"Response
{
"success": true
}Get Subscriber Count
GET /subscribers/countcurl https://pushary.com/api/v1/server/subscribers/count \
-H "Authorization: Bearer pk_xxx.sk_xxx"Response
{
"total": 1500,
"active": 1200,
"unsubscribed": 300
}Campaigns
Create and manage notification campaigns.
List Campaigns
GET /campaignscurl "https://pushary.com/api/v1/server/campaigns?limit=20" \
-H "Authorization: Bearer pk_xxx.sk_xxx"Response
{
"data": [
{
"id": "camp_abc123",
"name": "Welcome Campaign",
"title": "Welcome!",
"body": "Thanks for subscribing",
"status": "draft",
"totalTargeted": 0,
"totalSent": 0,
"totalDelivered": 0,
"totalClicked": 0,
"createdAt": "2024-01-15T10:30:00Z"
}
],
"hasMore": false,
"nextCursor": null
}Create Campaign
POST /campaignscurl -X POST https://pushary.com/api/v1/server/campaigns \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Product Launch",
"title": "New Feature Available!",
"body": "Check out our latest update",
"actionUrl": "https://example.com/new-feature"
}'Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Internal campaign name |
title | string | Yes | Notification title |
body | string | Yes | Notification body |
iconUrl | string | No | Custom icon URL |
imageUrl | string | No | Large image URL |
actionUrl | string | No | Click action URL |
scheduledAt | string | No | ISO 8601 schedule time |
segmentId | string | No | Target segment ID |
Response
Returns the created campaign object with status 201.
Get Campaign
GET /campaigns/:idcurl https://pushary.com/api/v1/server/campaigns/camp_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx"Update Campaign
PATCH /campaigns/:idcurl -X PATCH https://pushary.com/api/v1/server/campaigns/camp_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Title",
"body": "Updated body text"
}'Request Body
| Field | Type | Description |
|---|---|---|
name | string | Campaign name |
title | string | Notification title |
body | string | Notification body |
iconUrl | string | Custom icon URL |
imageUrl | string | Large image URL |
actionUrl | string | Click action URL |
scheduledAt | string | ISO 8601 schedule time |
status | string | Campaign status |
Delete Campaign
DELETE /campaigns/:idcurl -X DELETE https://pushary.com/api/v1/server/campaigns/camp_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx"Send Campaign
POST /campaigns/:id/sendSend an existing campaign to all active subscribers.
curl -X POST https://pushary.com/api/v1/server/campaigns/camp_abc123/send \
-H "Authorization: Bearer pk_xxx.sk_xxx"Requirements
- Campaign must have status
draftorscheduled - Site must have VAPID keys configured
Response
Returns the updated campaign object with status sending.
Templates
Create reusable notification templates.
List Templates
GET /templatescurl "https://pushary.com/api/v1/server/templates" \
-H "Authorization: Bearer pk_xxx.sk_xxx"Response
{
"data": [
{
"id": "tmpl_abc123",
"name": "Welcome Template",
"title": "Welcome to {{siteName}}!",
"body": "Thanks for subscribing, {{userName}}",
"iconUrl": null,
"imageUrl": null,
"actionUrl": "https://example.com/welcome",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
],
"hasMore": false,
"nextCursor": null
}Create Template
POST /templatescurl -X POST https://pushary.com/api/v1/server/templates \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Order Confirmation",
"title": "Order Confirmed!",
"body": "Your order #{{orderId}} has been confirmed",
"actionUrl": "https://example.com/orders/{{orderId}}"
}'Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name |
title | string | Yes | Notification title |
body | string | Yes | Notification body |
iconUrl | string | No | Custom icon URL |
imageUrl | string | No | Large image URL |
actionUrl | string | No | Click action URL |
Get Template
GET /templates/:idcurl https://pushary.com/api/v1/server/templates/tmpl_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx"Update Template
PATCH /templates/:idcurl -X PATCH https://pushary.com/api/v1/server/templates/tmpl_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Title",
"body": "Updated body with {{variable}}"
}'Delete Template
DELETE /templates/:idcurl -X DELETE https://pushary.com/api/v1/server/templates/tmpl_abc123 \
-H "Authorization: Bearer pk_xxx.sk_xxx"Error Responses
All errors follow a consistent format:
{
"error": "Error Type",
"message": "Human-readable description"
}Error Codes
| Status | Error | Description |
|---|---|---|
| 400 | Bad Request | Missing required fields or invalid request body |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | Plan limit exceeded or permission denied |
| 404 | Not Found | Resource does not exist |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unexpected server error |
Plan Limit Error
{
"error": "Notification limit exceeded",
"message": "You've reached your monthly notification limit",
"upgradeUrl": "https://pushary.com/pricing"
}Missing Fields Error
{
"error": "Missing required fields: title, body"
}