REST API
Send push notifications from your server using the Abrova Push REST API — authentication, send endpoints, request body, and error responses.
Send push notifications from your server using the REST API.
This REST API must only be used from your backend server, never from mobile apps or client-side code. The server secret can be extracted from mobile apps by attackers, which would allow them to send unauthorized push notifications.
For mobile apps: use the native SDKs (iOS, Android, Flutter, React Native) which only support receiving notifications. To send notifications from your app, make a request to your own backend server, which then calls the AbrovaPush API.
Authentication#
All API requests require both your API Key and Server Secret in the headers.
curl -H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
https://push-api.abrova.ir/push/...Required Headers
| Option | Type | Required | Description |
|---|---|---|---|
| x-api-key | String | Yes | Your project API key (ab_live_xxx) |
| x-server-secret | String | Yes | Your server secret (ab_srv_xxx) — required for all send operations |
For additional security, you can configure an IP whitelist in your project settings. When enabled, only requests from whitelisted IP addresses can use the server secret.
Send Notification#
The REST API exposes six send endpoints, one per audience shape: a single user (all their devices), a single device, multiple devices by ID, a topic, a segment, or every registered device.
Send to User
Send to all devices of a user.
curl -X POST https://push-api.abrova.ir/push/send-to-user \
-H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_123",
"title": "Hello!",
"body": "You have a new message",
"data": {
"messageId": "msg_456",
"action": "open_chat"
}
}'Send to Device
Send to a specific device.
curl -X POST https://push-api.abrova.ir/push/send \
-H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"deviceId": "dev_abc123def456",
"title": "Order Update",
"body": "Your order has shipped!",
"data": {
"orderId": "ORD-789"
}
}'Send to Devices
Send to multiple devices by ID.
curl -X POST https://push-api.abrova.ir/push/send-to-devices \
-H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"deviceIds": ["dev_abc123", "dev_def456", "dev_ghi789"],
"title": "Batch Notification",
"body": "This goes to multiple devices",
"data": {
"campaign": "promo_2024"
}
}'Send to Topic
Send to every subscriber of a topic.
curl -X POST https://push-api.abrova.ir/push/send-to-topic \
-H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"topic": "sports",
"title": "Breaking News",
"body": "Your team just won!"
}'Send to Segment
Send to every device in a saved segment.
curl -X POST https://push-api.abrova.ir/push/send-to-segment \
-H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"segmentId": "segment-uuid-123",
"title": "Just for you",
"body": "A deal for our most active users"
}'Broadcast
Send to every registered device.
curl -X POST https://push-api.abrova.ir/push/broadcast \
-H "x-api-key: ab_live_your_api_key" \
-H "x-server-secret: ab_srv_your_server_secret" \
-H "Content-Type: application/json" \
-d '{
"title": "App Update",
"body": "New features available! Update now."
}'Request Body#
| Option | Type | Required | Description |
|---|---|---|---|
| title | string | Conditional | Notification title (required unless templateId is set) |
| body | string | Conditional | Notification body text (required unless templateId is set) |
| templateId | string | No | Render a saved template instead of title/body |
| templateVariables | object | No | Variables substituted into the template |
| locale | string | No | Template locale to render (e.g. en, fa) |
| data | object | No | Custom data payload delivered to the client as-is |
| userId | string | Conditional | Target user ID (required for send-to-user) |
| deviceId | string | Conditional | Target device ID (required for /push/send) |
| deviceIds | string[] | Conditional | Array of device IDs (required for send-to-devices) |
| topic | string | Conditional | Target topic name (required for send-to-topic) |
| segmentId | string | Conditional | Target segment ID (required for send-to-segment) |
| appIdentifier | string | No | Only deliver to devices of this app (bundle ID / package name). Not accepted by send-to-devices |
Unknown body fields are rejected with 400 Bad Request.
For rich notifications with images, action buttons, deep links, and more, see Rich Notifications.
Response#
Successful sends return the device counts, the generated messageId (a UUID) and a billing summary:
{
"success": 5,
"failed": 0,
"messageId": "3f1c2a9e-8b7d-4e21-9a0c-5d6e7f8a9b0c",
"billing": {
"messagesCharged": 5,
"remaining": 99995
}
}success and failed are device counts. billing.remaining is -1 when nothing was charged or the remaining quota is unknown.
No Recipients
When the target had zero registered devices the send is not treated as a delivery failure. The response carries reason: "no_recipients" and both counts are zero so your server can distinguish the two cases without polling the message:
{
"success": 0,
"failed": 0,
"messageId": "3f1c2a9e-8b7d-4e21-9a0c-5d6e7f8a9b0c",
"reason": "no_recipients",
"billing": { "messagesCharged": 0, "remaining": -1 }
}The message is recorded with status: "no_recipients" and the webhook fires message.no_recipients (not message.failed).
Error Responses#
Missing or Invalid Credentials
{
"statusCode": 401,
"message": "API key is required (x-api-key header)"
}Missing Server Secret
{
"statusCode": 401,
"message": "Server secret is required for this operation (x-server-secret header). Server secret can only be used from your backend server, never from client apps."
}IP Not in Whitelist
{
"statusCode": 403,
"message": "Access denied: Your IP address (x.x.x.x) is not in the allowed list. Please add your server IP to the allowed IPs in Abrova Console (Project settings)."
}