> ## Documentation Index
> Fetch the complete documentation index at: https://replyke-feat-push-rich-payload-fields.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Push Notification

> Send a push notification to one or more users across all their registered devices

Fans a push notification out to every registered device belonging to the listed users. The server dispatches to APNs (iOS), FCM (Android), and the Web Push protocol in parallel, using whichever platform credentials are configured for this project.

Requires a service or master key (`Authorization: Bearer <serviceKey>`). End-user tokens are rejected — this endpoint is intended for your backend, not for end users calling it directly.

Requires the `push` bundle.

## Body Parameters

<ParamField body="userIds" type="string[]" required>
  Array of Sublay user IDs to notify. Between 1 and 100 IDs per request.
</ParamField>

<ParamField body="title" type="string" required>
  Notification title. Displayed as the bold heading on the device.
</ParamField>

<ParamField body="body" type="string" required>
  Notification body text.
</ParamField>

<ParamField body="data" type="object">
  Optional key-value data payload forwarded to the app alongside the notification. Values must be strings or serializable primitives. Use this to pass deep-link targets, IDs, or any context your app needs when the user taps the notification.
</ParamField>

### Rich payload fields

All optional. Each is mapped to whichever platform(s) support it at dispatch time and silently ignored on platforms that have no equivalent. See the [Push Notifications guide](/push-notifications#rich-notification-payloads) for the client-side setup some of these require (Android channels, the iOS Notification Service Extension, your web service worker).

<ParamField body="sound" type="string">
  Sound file to play. iOS: APNs `sound`. Android: governed by the channel on 8+ — pair with `channelId`. Web: forwarded to the service worker.
</ParamField>

<ParamField body="badge" type="number">
  iOS app-icon badge count (APNs `badge`). No Android equivalent. The caller supplies the number; Sublay tracks no unread state.
</ParamField>

<ParamField body="channelId" type="string">
  Android notification channel id (FCM `android.notification.channel_id`). The channel must be created client-side; on Android 8+ it owns sound/importance/vibration.
</ParamField>

<ParamField body="priority" type="string">
  `"high"` or `"normal"`. iOS: APNs `apns-priority` (10/5). Android: FCM `android.priority`. `high` wakes the device for time-sensitive pushes.
</ParamField>

<ParamField body="subtitle" type="string">
  iOS subtitle line under the title (APNs `alert.subtitle`).
</ParamField>

<ParamField body="imageUrl" type="string">
  Rich/big-picture image URL. Android (FCM `image`) and Web work out of the box. iOS additionally requires a Notification Service Extension in the app — the URL is forwarded in the payload and `mutable-content` is set automatically.
</ParamField>

<ParamField body="tag" type="string">
  Display-replace key so notifications collapse in the UI (FCM `android.notification.tag`, Web `tag`).
</ParamField>

<ParamField body="collapseId" type="string">
  Transport-level collapse identifier (APNs `apns-collapse-id`, FCM `collapse_key`) — supersedes an undelivered push with the same id.
</ParamField>

<ParamField body="threadId" type="string">
  iOS notification grouping (APNs `thread-id`).
</ParamField>

<ParamField body="ttl" type="number">
  Time-to-live in seconds for offline devices (APNs `apns-expiration` computed from now, FCM `android.ttl`).
</ParamField>

<ParamField body="mutableContent" type="boolean">
  iOS `mutable-content` flag, enabling the app's Notification Service Extension to modify the payload (e.g. attach `imageUrl`). Set implicitly when `imageUrl` is provided.
</ParamField>

## Response

Returns `200` with a `results` map keyed by user ID. Every requested `userId` is present in the response — users with no registered devices get an empty array rather than being omitted.

```json theme={null}
{
  "results": {
    "usr_abc123": [
      { "platform": "ios", "success": true },
      { "platform": "android", "success": true }
    ],
    "usr_def456": [],
    "usr_ghi789": [
      { "platform": "web", "success": false, "reason": "credentials_not_configured" }
    ]
  }
}
```

<ResponseField name="results" type="object">
  Map from user ID to an array of per-device delivery results.

  <Expandable title="per-device result fields">
    <ResponseField name="platform" type="&#x22;ios&#x22; | &#x22;android&#x22; | &#x22;web&#x22;">
      The platform this result is for.
    </ResponseField>

    <ResponseField name="success" type="boolean">
      Whether the push was accepted by the upstream provider (APNs, FCM, or Web Push).
    </ResponseField>

    <ResponseField name="reason" type="string">
      Present only when `success` is `false`. Common values:

      * `"credentials_not_configured"` — no provider config exists for this platform (or it is disabled)
      * Provider-specific error codes returned by APNs/FCM/Web Push
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  Devices whose tokens or subscriptions are reported as permanently invalid by the upstream provider (e.g. APNs `BadDeviceToken`, FCM `UNREGISTERED`, Web Push HTTP 410) are automatically deleted during the send — no separate cleanup step is needed.
</Note>

## Error Responses

<AccordionGroup>
  <Accordion title="Invalid Body — 400">
    ```json theme={null}
    { "error": "...", "code": "push-send/invalid-body" }
    ```

    Returned when `userIds` is empty, exceeds 100 entries, or required fields are missing.
  </Accordion>

  <Accordion title="Forbidden — 403">
    ```json theme={null}
    { "error": "Forbidden" }
    ```

    Returned when called with an end-user access token instead of a service/master key.
  </Accordion>

  <Accordion title="Bundle Not Installed — 403">
    ```json theme={null}
    { "error": "...", "code": "database/tables-not-available" }
    ```
  </Accordion>
</AccordionGroup>

## See Also

* [Node SDK — push.send](/node-sdk/push-notifications)
* [Register Device](/api-reference/push-notifications/register-device)
* [Push Notifications overview](/push-notifications)
