Sending notifications

Targets, content per language, data, links, buttons, categories and validation.

A send is a POST /v1/notifications with your secret key, or the same thing from New send in the panel. It responds 202 immediately and is delivered in the background.

{
  "target": { "type": "external_users", "ids": ["customer-123"] },
  "content": {
    "en": { "title": "Your order is on its way", "body": "Arriving today" },
    "es": { "title": "Tu pedido va en camino", "body": "Llega hoy" }
  },
  "data": { "orderId": "A-1029" },
  "deepLink": "myapp://orders/A-1029"
}

Targets (target.type)

Type Fields Reaches
devices ids or tokens Specific devices
external_users ids All the devices of those users (externalUserId)
topic name Those subscribed to the topic
segment segmentId Those matching a saved segment
filters rules An on-the-fly filter (same format as segments)
all — All active devices of the app
test_devices — Only test devices

With a test key, any target is limited to test devices. platforms: ["ios"] restricts to one platform.

Content

  • Per language: content.en, content.es… with title, subtitle (iOS) and body. Each device receives its language; if it isn't there, the app's default language.
  • Variables: {{name}} in the text, with their values in variables.
  • Templates: templateId uses a saved template; what you send in the request takes priority.
  • contentType:
    • alert, the visible one (default);
    • data_only, data only: the app builds the notification. The title and text travel in data, in the keys your framework's plugin reads (title and body; title and message in Cordova and Expo). See Compatibility;
    • silent, to update the app in the background.
  • data: up to 50 keys your app receives. Don't use keys starting with _ph: they're Pushtifly's.
  • deepLink: the app receives it when the notification is tapped.
  • actions: up to 3 buttons { id, title, deepLink }. They require code in the app (or the SDK).
  • sound: default or a sound included in the app and registered in the panel.
  • badge (iOS), ttlSeconds (up to 28 days), priority (high / normal).
  • Per-platform options:
    • android: channelId, color, tag, collapseKey;
    • ios: interruptionLevel, threadId, relevanceScore.

Category

  • transactional (default): orders, security, user reminders.
  • marketing: promotions. It goes through a lower-priority queue, so it never delays transactional ones, and it respects the app's limits.

Marketing limits

In each app's settings (Apps → edit → Marketing) you can set two limits. They're applied in each device's local time and only to marketing sends:

  • Maximum per device per day: notifications above the limit are skipped. They show up as skipped (code FREQUENCY_CAP) and don't count as failed.
  • Quiet hours (for example, from 22:00 to 08:00): delivery is postponed until the end time. The send stays in sending until they're delivered, and stats.deferred counts how many were postponed.

If the device didn't report its time zone, the company's is used. The SDK always sends it.

Validate without sending

"validateOnly": true validates everything, estimates how many devices it would reach and calculates the payload size, without creating the send.

The payload can't exceed 4 KB (2003): media never travels in the payload, only its URL.

Tracking

  • GET /v1/notifications/{id}: status and statistics (sent, accepted, failed, invalid tokens, opens, clicks).
  • GET /v1/notifications/{id}/deliveries: the result per device.
  • POST /v1/notifications/{id}/cancel: cancels a scheduled or in-progress send.
  • notification.completed and notification.failed webhooks when it ends. See Webhooks.