Send Notifications (Universal)
Send one push notification to your universal audience — all devices, a device list, or a subscriber list — and read the per-transport accepted/failed result.
One endpoint sends one notification to the devices registered through the universal service:
POST https://app.nativenotify.com/api/universal/notifications/send
Request
{
"appId": 123,
"appToken": "yourAppToken",
"title": "Service this Sunday",
"message": "Doors open at 9:00 — the 10:30 service is unchanged.",
"audience": { "type": "all" }
}
| Field | Required | Notes |
|---|---|---|
appId, appToken | yes | Your app's pair. |
title | yes | Notification title. |
message | yes | Body text. body is accepted as an alias. |
audience | yes | This service sends only to its own registered devices — see the audience shapes below. |
pushData | no | JSON object delivered to the app with the notification (deep links, ids). |
bigPictureURL | no | Image url (Android big picture / iOS attachment source). |
| …rich options | no | The message options the APNs/FCM transports support (subtitle, sound behavior, badge, and so on) are passed through where the transport supports them. |
Audience shapes
{ "audience": { "type": "all" } }
{ "audience": { "type": "devices", "deviceIds": ["A1B2C3D4-install-key", "E5F6-install-key"] } }
{ "audience": { "type": "subscribers", "subscriberIds": ["user_8241", "user_8242"] } }
all— every registered universal device on the app.devices— the listeddeviceIds.subscribers— every device registered under the listedsubscriberIds (all of a user's devices, which is the supported pattern).
Live sends:
Sends are live and cannot be recalled. Agents are instructed to confirm title, body and audience with you before sending — do the same in scripts: a dry run means a devices audience with one device of your own.
Response — 200
{
"ok": true,
"devices": 1284,
"attempted": 1301,
"accepted": 1298,
"failed": 3,
"byType": {
"apns": { "attempted": 640, "accepted": 639, "failed": 1, "delivered": null },
"fcm": { "attempted": 661, "accepted": 659, "failed": 2, "delivered": null }
},
"skipped": { "apns": 0, "fcm": 4 },
"health": { "apns": { "struck": 0, "dead": 1 }, "fcm": { "struck": 1, "dead": 0 } },
"checkedAt": "2026-09-23T09:30:00.000Z"
}
| Field | Meaning |
|---|---|
devices | Devices the audience resolved to (a device counts once even when it has several tokens). |
attempted / accepted / failed | Tokens sent to, accepted by the transport, and rejected. |
byType | The same split per transport (apns, fcm). delivered is always null — native transports cannot prove delivery, and this service never fabricates it. |
skipped | Tokens with no credentials configured for their transport. An app-config gap, never counted against the token. |
health | Tokens currently marked dead or repeatedly failing (see Verify Delivery). |
Failures are per token: a rejected token is recorded with its transport answer, and repeatedly failing tokens accumulate strikes like the Expo path does (see Tokens & Receipts).
What agents do
Connected agents have their own tools (mass/indie/group/topic sends, scheduling, analytics) and — for accounts on the universal path — the same REST contract above is what a "send to my Flutter app" script or tool call ends up doing. Every response is machine-readable so an agent can report accepted vs failed honestly.
Related
- Test send — prove one device/token before a blast.
- Scheduling — one-off and recurring sends.
- Segments — named subscriber groups that sends and schedules can target.