API de Notificações
Envie uma notificação para a caixa de entrada de um usuário, com entrega opcional de push via APNs para os dispositivos dele.
Create Notification
/notificationsCreate an in-app notification and optionally push it to all user devices. No subscription required — it counts toward your monthly notification quota (free tier included) and needs notifications at send or above, which your default integration key already has.
Request Body
| Field | Type | Required | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
title | string | Yes | Notification title | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
body | string | Yes | Notification body text | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
subtitle | string | No | Optional subtitle | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
level | string | No | passive, active (default), time-sensitive, or critical. Controls iOS interruption level. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
volume | number | No | Sound volume for critical alerts (0.0–1.0). Only used when level is critical. Defaults to 1.0. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
thread_id | string | No | Groups notifications in Notification Center | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
collapse_id | string | No | APNs deduplication key (max 64 chars). Not stored or returned in responses. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
source | string | No | Source identifier (e.g. integration name) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
source_display_name | string | No | Human-readable source name shown in notification settings and inbox grouping | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
url | string | No | Action URL (max 2048 chars). Any URL scheme except javascript:, data:, file:, or vbscript:; http(s) URLs also require a host. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
media | object | No | Rich media attachment. url (HTTPS, max 2048 chars) plus type (image, video, or audio). iOS renders inline. Apple size caps: image 10 MB, audio 5 MB, video 50 MB. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
actions | array | No | Up to 10 dynamic action buttons. Each: id (string, max 64), title (string, max 64), optional url, foreground (bool), destructive (bool), authentication_required (bool), icon (SF Symbol name). Full field list on Actions. An action with no url and no foreground is recorded by the server; see Notification Answers. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
icon_url | string | No | Per-notification source avatar, shown as the Communication Notification avatar on iOS. Accepts http or https (max 2048 chars, recommended ≤256×256 and ≤100 KB; the iOS extension rejects responses larger than 512 KB). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
metadata | object | No | Key-value string pairs (max 20 keys, key max 64 chars, value max 4096 chars, and 8 KB total across all keys and values) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
activity_slug | string | No | Optional link to an existing activity. An unknown slug is rejected with 422 before the notification is persisted. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
push | boolean | No | If true (default), send APNs rich alert to all user devices. Set false to store in the inbox only. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
target | object | No | Organization keys only: which members get it, as groups, tags and members. See Teams. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Chega na versão 1.17.0 do app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
encrypted | string | No | A pw1 envelope holding the title, subtitle, body and url, sealed with the user's encryption key (max 3072 chars). Leave those four fields out when it is set; title and body are required only without it. Not available to organization keys. See End-to-End Encryption. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
acknowledge | object | No | Repeat the push until someone acknowledges it: repeat_seconds (30-3600, default 60), expire_seconds (60-10800, default 3600), action_title (default Acknowledge). Not with push: false or level passive. See Acknowledged Alerts. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tags | array | No | Up to 10 labels (1-64 printable ASCII characters, no spaces) for canceling acknowledged notifications as a group. Requires acknowledge. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
callback_url | string | No | https URL that gets a signed POST when the notification is acknowledged or expires (max 2048 chars). Requires acknowledge. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
curl -X POST https://api.pushward.app/notifications \
-H "Authorization: Bearer hlk_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Deploy Complete",
"body": "Successfully deployed to production",
"source": "github-actions",
"source_display_name": "GitHub Actions",
"level": "active"
}'Response (201):
{
"id": 42,
"title": "Deploy Complete",
"subtitle": "",
"body": "Successfully deployed to production",
"thread_id": "",
"level": "active",
"source": "github-actions",
"source_display_name": "GitHub Actions",
"url": "",
"media_url": "https://example.com/img.png",
"media_type": "image",
"actions": [
{ "id": "rerun", "title": "Re-run", "foreground": true }
],
"icon_url": "",
"metadata": {},
"activity_slug": "",
"pushed": true,
"created_at": "2026-04-24T21:00:00Z",
"delivery": "all"
}On POST /notifications only, the response also includes these read-only fields
(omitted from GET responses):
| Field | Values | Meaning | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
delivery | all, partial, none | Whether every, some, or no devices accepted the push. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
reason | no_apns_token, apns_rejected, push_disabled | Failure mode when delivery is not all -- for a push: false create it is push_disabled with delivery none. Omitted on a fully successful push. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
answerable | true | The server records the answer to this notification (at least one action was sent without a url). Read it with GET /notifications/answers/{id}. Omitted otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Chega na versão 1.17.0 do app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
receipt | object | Sent with acknowledge: the receipt, as GET /notifications/receipts/{id} returns it. Omitted otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Scheduled Notifications
Queue a notification for a later send_at, or repeat it on a cron schedule. The body, rules and statuses are on the Scheduled Notifications page.
/notifications/scheduledSchedule a notification: a POST /notifications body plus send_at (RFC 3339, in the future, at most 365 days ahead), or a recurrence (cron, timezone, until, count) that repeats it, with send_at then optional as the start point. Returns 201 with the schedule. At most 25 pending per account (409 scheduled_notification.limit_exceeded); a repeating schedule holds one slot for its whole series. Each send counts toward the notification quota when it goes out; an account already out of quota gets 429 quota.exceeded.
/notifications/scheduledList schedules. ?status=scheduled (default) lists pending ones soonest first; sent, failed, canceled or all list latest first. ?limit=1-100 (default 50) per page; pass next_cursor back as ?cursor= with the same status for the next page. A key sees only the schedules it created.
/notifications/scheduled/{id}Get one schedule, including notification_id, sent_at and the push outcome once it has been sent, or failure_reason if it failed. A repeating schedule also reports recurrence, occurrence and last_sent_at.
/notifications/scheduled/{id}Cancel a pending schedule (204); for a repeating schedule this stops the series. It stays readable as canceled for 24 hours, then it is deleted. ?purge=true deletes it outright with no canceled record.
Notification Answers
Read what the user answered to a notification sent with url-less actions. How recording works is on the Notification Answers page.
/notifications/answers/{id}Get the answer to a notification: notification_id, status (pending or answered), action_id, text and answered_at. id is the notification id from POST /notifications, or the notification_id of a sent scheduled notification. ?wait=0-25 holds the request open until the answer lands (long-poll). The first answer wins; answers are kept 30 days. A key reads only answers to notifications it sent. Returns 404 notification_answer.not_found when none of the actions was url-less, and 429 answer_wait.limit_exceeded when too many waits are open.
Esta seção descreve um recurso de uma atualização do app que está em análise na App Store. Ele é desbloqueado aqui automaticamente assim que a atualização for lançada.
Acknowledged Alerts
Follow and stop a notification sent with acknowledge. The receipt fields, callbacks and their signature are on the Acknowledged Alerts page.
/notifications/receipts/{id}Get the receipt of a notification sent with acknowledge: status (active, acknowledged, expired or canceled), repeats_sent, expires_at, who acknowledged it and on which device, the action, cancel_reason, tags and the callback delivery. ?wait=0-25 holds the request open while it is active. A key reads only receipts of notifications it sent. Finished receipts are kept 7 days. 404 notification_receipt.not_found when there is none.
/notifications/receipts/{id}/cancelStop the repeats and return the receipt; its callback is not sent. Delivered banners stay. A receipt that already finished comes back unchanged.
/notifications/receipts/cancelCancel every active receipt the calling key sent with a tag. Body {"tag": "..."}; returns {"canceled": <count>}.
Error Responses
Errors use the RFC 9457 Problem Details shape (Content-Type: application/problem+json) — see Errors for the body shape and known code values.
| Status | Meaning | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
400 | Malformed JSON, or a field-level validation failure (media, action URL scheme, duplicate action id, metadata size, or text_input rules) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
401 | Missing or invalid token | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
403 | Integration key's notifications level is none (integration_key.permission_denied), or it sets activity_slug without activity access, or an organization key limited to some groups and tags targets outside them (integration_key.target_denied) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
422 | Schema violation (wrong shape, maxLength, or enum), an unknown activity_slug, or a bad target (org.target_*) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
429 | Per-IP rate limit (code: rate_limit.exceeded) or monthly notification quota exhausted (code: quota.exceeded) — pairs with Retry-After and retry_after_ms. See Errors for the quota body shape. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
500 | Internal server error | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Chega na versão 1.17.0 do app | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
409 | 25 acknowledged notifications are already active for the account (notification_receipt.limit_exceeded) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
422 | An encrypted push that would not fit 4 KB (notification.encrypted_too_large), encrypted from an organization key (notification.encryption_unavailable), or acknowledged notifications switched off for now (notification_receipt.disabled) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||