Skip to main content

Push notification categories

A notification category is a per-tenant template you reference by identifier on a send — it carries an optional custom sound and up to 10 interactive action buttons so every send that names it expands to the same curated shape. Define the category once (dashboard or API), then pass its identifier as notification_channel on POST /api/v1/push/send. This is a tenant-owned control: you curate which categories exist, and the send path expands them per request. Nothing here gates delivery — a send that names an unknown identifier proceeds with a plain, non-interactive notification.

1. Why curate categories

Push delivery fails or under-performs in predictable ways, and category hints address the content side:
  • Interactive actions ship uniformly. Instead of passing per-platform overrides on every send, you name one identifier and the send path expands its stored iOS actions, Android tap action, and sound.
  • APNs payload rules are enforced at curation time. Identifiers are validated as UPPER_SNAKE_CASE (max 64 chars), action titles are capped at 128 chars, and a category carries at most 10 actions — the constraints APNs enforces are caught when you author the category, not when APNs rejects a mis-shaped payload with a per-device failed result.
  • Identifiers are wire-bound. The iOS / Android client registers and matches on the identifier string, so categories are immutable after create — delete and recreate to change one. This keeps in-flight pushes referencing the shape the client cached.
For the delivery-failure side (per-device error strings like BadDeviceToken, suppression, and frequency-cap skips), see the push end-to-end guide.

2. Manage categories in the dashboard

Open Messages → Push → Manage push notifications → Notification Categories (/messages/push/manage/notification-categories). The page lists the categories defined for your tenant and sits beside the Scheduled pushes, Device Tokens, and Live Activities satellites. The page is guarded for owner, admin, and developer roles — the same role set the other push management pages require.

3. Category shape

Each category record holds: The API mirrors the shape exactly:
Supporting endpoints: GET /api/v1/push/categories (newest first, capped at 200 rows — also the per-tenant creation limit), GET /api/v1/push/categories/:id, and DELETE /api/v1/push/categories/:id (empty 204). Identifier reuse is the supported update pattern: delete, then recreate — a conflicting identifier returns 409 PUSH_CATEGORY_IDENTIFIER_CONFLICT.

4. Apply a category on send

Pass the category’s identifier as notification_channel on POST /api/v1/push/send:
When the identifier resolves, the send expands the category before the provider call:
  • iOS — the APNs payload carries category: "INVOICE_REMINDER", plus the category’s custom sound unless the send’s own ios.sound override wins. If the send supplies no actions of its own, the category’s stored actions fill in.
  • Android — the FCM click_action is set to the identifier, and unless you override android.channel_id explicitly, notification_channel doubles as the Android channel id.
  • Unresolved identifier — the send proceeds as a plain notification; naming an unknown identifier is not a failure.
Per-device results stay in the notifications[] array exactly as without categories: status of sent, failed, or skipped, with a provider error string (for example BadDeviceToken) on failures. Categories annotate delivery shape; the push end-to-end guide covers the failure taxonomy.

5. End-to-end example

  1. Create the category — with the PAY_NOW / SNOOZE actions shown above, or through the dashboard’s Notification Categories page.
  2. Send a test push — fire POST /api/v1/push/test-send with "notification_channel": "INVOICE_REMINDER" against your own devices to validate the whole chain without polluting campaign stats.
  3. Verify on device — the iOS device renders the notification with the registered PAY NOW / SNOOZE buttons and the custom chime; Android routes the tap through click_action: "INVOICE_REMINDER".
  4. Read the result — each device in notifications[] reports sent; a failed row on an unregistered device still carries a raw provider error such as BadDeviceToken for you to act on.
Categories are per-tenant, and the per-tenant cap is 200 — within APNs’ practical category limits per bundle.