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" }
}
FieldRequiredNotes
appId, appTokenyesYour app's pair.
titleyesNotification title.
messageyesBody text. body is accepted as an alias.
audienceyesThis service sends only to its own registered devices — see the audience shapes below.
pushDatanoJSON object delivered to the app with the notification (deep links, ids).
bigPictureURLnoImage url (Android big picture / iOS attachment source).
…rich optionsnoThe 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 listed deviceIds.
  • subscribers — every device registered under the listed subscriberIds (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"
}
FieldMeaning
devicesDevices the audience resolved to (a device counts once even when it has several tokens).
attempted / accepted / failedTokens sent to, accepted by the transport, and rejected.
byTypeThe same split per transport (apns, fcm). delivered is always null — native transports cannot prove delivery, and this service never fabricates it.
skippedTokens with no credentials configured for their transport. An app-config gap, never counted against the token.
healthTokens 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.

  • 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.