> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerix.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Push Notifications

> Send push notifications to one or more devices through the Atelerix REST API.

Send a push notification to one or more registered device tokens, or to every
device subscribed to a topic.

<Note>
  See the [API introduction](/api-reference/introductaion) to set up your base URL and private key before making requests.
</Note>

## Parameters

<ParamField path="project-id" type="string" required placeholder="my-project-id">
  Your project ID from **Project Settings** in the [dashboard](https://app.atelerix.com).
</ParamField>

<ParamField body="title" type="string" required placeholder="Hello">
  Notification title shown to the user.
</ParamField>

<ParamField body="body" type="string" required placeholder="You have a new message.">
  Notification message body.
</ParamField>

<ParamField body="deviceTokens" type="string[]" placeholder="[&#x22;device-token-1&#x22;]">
  One or more device tokens to deliver the notification to. Required unless
  `sendByTopic` is `true`.
</ParamField>

<ParamField body="sendByTopic" type="boolean" default="false">
  Set to `true` to deliver to every device subscribed to `topic` instead of
  specific `deviceTokens` — when `true`, `deviceTokens` is ignored even if
  present. Devices subscribe to a topic from your app using the SDK; a topic
  is created automatically the first time a device subscribes to it, or you
  can create one manually from the **Topics** tab in the dashboard.
</ParamField>

<ParamField body="topic" type="string" placeholder="promotions">
  The topic key to broadcast to. Required when `sendByTopic` is `true`,
  ignored otherwise.
</ParamField>

<ParamField body="sound" type="string" placeholder="sound.mp3">
  Name of a custom notification sound. The file itself must already be
  bundled inside your app project — Atelerix only passes the filename
  through to APNs/FCM, it doesn't host or upload sound files. Leave empty to
  use the device's default notification sound.

  **iOS**: the sound file's name with its extension (e.g. `sound.mp3`;
  `.caf`/`.wav` also supported).

  **Android**: the resource name **without** an extension, matching a file
  under `res/raw/` (e.g. `sound` for a file at `res/raw/sound.mp3`).

  * Supported formats: `.wav`, `.mp3`, `.ogg`.
  * Keep the filename lowercase — some tooling/devices ignore uppercase
    letters in resource names.
  * Keep the file small and under \~30 seconds; large files may not play on
    some devices.
  * If the named file isn't found, the notification falls back to the
    device's default sound rather than failing.
  * A given sound is locked in the first time it's used on a device — Android
    fixes a notification channel's sound at creation and never lets it
    change afterward, so switching to a different `sound` value later
    creates a new channel rather than updating the old one.

  **Web**: not supported — the Web Notifications API has no cross-browser
  way to set a custom sound, so this parameter is ignored for web
  recipients.
</ParamField>

<ParamField body="imageUrl" type="string" placeholder="https://example.com/image.jpg">
  URL of an image to show as a rich image in the notification. Atelerix
  downloads it — this is a normal `https://` URL, not a file you need to
  bundle in your app (unlike `sound`).

  **Android**: works automatically, rendered as a `BigPictureStyle`
  notification.

  **iOS**: requires the app to have a Notification Service Extension
  configured (a one-time setup step — see the
  [Flutter push notifications guide](/frameworks/flutter/push-notifications#sending-an-image)).
  Without it, `imageUrl` is silently ignored on iOS; the notification still
  sends and displays normally, just without the image. Sending this field
  automatically sets APNs' `mutable-content` flag, which is what triggers the
  extension to run.

  **Web**: works automatically, no extra setup — the service worker renders
  it as the notification's icon/image directly.
</ParamField>

<ParamField body="metadata" type="object" placeholder="{&#x22;orderId&#x22;: &#x22;123&#x22;}">
  Arbitrary custom data to attach to the notification. Any JSON object; omit
  for no metadata. Delivered to the device alongside `title`/`body` and
  readable from the SDK as `payload.metadata` in
  `setOnNotificationReceived`/`setOnNotificationTapped`.
</ParamField>

<ParamField body="projectSlug" type="string" required placeholder="my-project-slug">
  Your project slug from **Project Settings**.
</ParamField>

<ParamField body="apiKey" type="string" required placeholder="your-private-key">
  Your private key from **Project Settings**.
</ParamField>

<ParamField body="source" type="string" default="API">
  Where the notification was sent from.
</ParamField>

<ParamField body="sentAt" type="string" placeholder="2026-09-01T10:00:00.000Z">
  An ISO 8601 timestamp to schedule delivery for later instead of sending
  immediately. Omit it (or pass a time in the past) to send right away. A
  scheduled notification can be edited or canceled before it goes out — see
  [Update a notification](/api-reference/update-notification) and
  [Cancel a scheduled notification](/api-reference/cancel-notification).
</ParamField>

<Warning>
  Never expose your private key in client-side code or public repositories. Send API requests from a trusted backend only.
</Warning>

## Response

```json 201 Created theme={null}
{
  "success": true,
  "message": "Notification sent successfully",
  "notificationId": "b6b1a2b0-9c3f-4b3e-9c3f-4b3e9c3f4b3e"
}
```

Save `notificationId` — it's what you pass to the other notification endpoints
(update, unsend, cancel, and delivery status).

On failure, the response follows the shape documented in [Error & success codes](/developers/errors-responses).
