starti.app
REST API

Push Notifications

Send push notifications and badge updates to users, devices or topics.

Send Notification

POST /push-notifications/send

Send notifications or badge updates to users, devices or topics. The request body is an array of notification objects, allowing you to send multiple notifications in a single request.

Each notification targets exactly one of userIds, deviceIds or topics — they cannot be combined in the same object. The userIds correspond to the IDs registered via startiapp.User.registerId() on the client side, and the deviceIds to the installation IDs from startiapp.App.deviceId().

Request body

The request body is a JSON array of notification objects.

[
  {
    "userIds": ["user123", "user456"],
    "title": "New Message",
    "body": "You have received a new message",
    "openToUrl": "https://example.com/message/123",
    "badgeCount": 5
  }
]

Prop

Type

Exactly one of userIds, deviceIds or topics must be provided. To send a visible notification, include both title and body. To update only the badge count, omit title and body and provide badgeCount.

Examples

curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '[
    {
      "userIds": ["user123"],
      "title": "New Message",
      "body": "You have received a new message",
      "openToUrl": "https://example.com/message/123"
    },
    {
      "userIds": ["user456"],
      "badgeCount": 5
    }
  ]' \
  https://api.starti.app/v1/push-notifications/send
curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '[
    {
      "deviceIds": ["00000000-0000-0000-0000-000000000000"],
      "title": "Signed in on a new device",
      "body": "Tap to review your recent activity"
    }
  ]' \
  https://api.starti.app/v1/push-notifications/send
curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '[
    {
      "topics": ["general", "announcements"],
      "title": "System Update",
      "body": "The system will be updated tonight",
      "openToUrl": "https://example.com/updates"
    }
  ]' \
  https://api.starti.app/v1/push-notifications/send
curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '[
    {
      "userIds": ["user123"],
      "badgeCount": 5
    }
  ]' \
  https://api.starti.app/v1/push-notifications/send

Responses

Every response carries an x-request-id header — the empty 200 of a fully delivered batch included. It identifies the call, so you have something to record alongside your own logs and something concrete to quote in a support request.

If your brand has the notification log switched on in Manager, that same id is what a call is listed under there: the body you sent, the recipients it resolved to, and the outcome for each of them. Nothing else about the request or the response changes — the header is an addition, and every field documented below is unaffected.

Every target in the request gets its own outcome in the results array, each echoing what you addressed it with — userId, deviceId or topics:

  • delivered — handed to the push service. deviceCount says how many devices it went to.
  • skipped — nothing to deliver to. reason says why; currently always no_active_device.
  • failed — delivery was attempted and failed. message carries the underlying error.

The status code follows the worst outcome in the batch: 207 if any target failed, otherwise 200. It tells you whether anything needs acting on — not whether every recipient was reached — so skipped targets never make a request 207.

no_active_device means the user has no device registered, or every device behind them has lost its push token — typically because the app was uninstalled or notifications were turned off. Retrying will not help, so treat it as a signal to stop sending to that user rather than as a failure. They become reachable again the moment the app registers a new token. When we know when we last heard from the device, unreachableSince tells you how long they have been gone.

On this page