跳至內容

通知 API

向使用者的收件匣傳送通知,並可選擇透過 APNs 推播至其裝置。

Create Notification

POST /notifications

Create 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

FieldTypeRequiredDescription
titlestringYesNotification title
bodystringYesNotification body text
subtitlestringNoOptional subtitle
levelstringNopassive, active (default), time-sensitive, or critical. Controls iOS interruption level.
volumenumberNoSound volume for critical alerts (0.0–1.0). Only used when level is critical. Defaults to 1.0.
thread_idstringNoGroups notifications in Notification Center
collapse_idstringNoAPNs deduplication key (max 64 chars). Not stored or returned in responses.
sourcestringNoSource identifier (e.g. integration name)
source_display_namestringNoHuman-readable source name shown in notification settings and inbox grouping
urlstringNoAction URL (max 2048 chars). Any URL scheme except javascript:, data:, file:, or vbscript:; http(s) URLs also require a host.
mediaobjectNoRich 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.
actionsarrayNoUp 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_urlstringNoPer-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).
metadataobjectNoKey-value string pairs (max 20 keys, key max 64 chars, value max 4096 chars, and 8 KB total across all keys and values)
activity_slugstringNoOptional link to an existing activity. An unknown slug is rejected with 422 before the notification is persisted.
pushbooleanNoIf true (default), send APNs rich alert to all user devices. Set false to store in the inbox only.
targetobjectNoOrganization keys only: which members get it, as groups, tags and members. See Teams.
將在 app 版本 1.17.0 中推出
範例
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):

FieldValuesMeaning
deliveryall, partial, noneWhether every, some, or no devices accepted the push.
reasonno_apns_token, apns_rejected, push_disabledFailure mode when delivery is not all -- for a push: false create it is push_disabled with delivery none. Omitted on a fully successful push.
answerabletrueThe 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.
將在 app 版本 1.17.0 中推出

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.

POST /notifications/scheduled

Schedule 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.

GET /notifications/scheduled

List 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.

GET /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.

DELETE /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.

GET /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.

將在 app 版本 1.17.0 中推出

本節介紹的功能來自一個正在等待 App Store 審核的 app 更新。更新上線後,此處會自動解鎖。

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.

StatusMeaning
400Malformed JSON, or a field-level validation failure (media, action URL scheme, duplicate action id, metadata size, or text_input rules)
401Missing or invalid token
403Integration 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)
422Schema violation (wrong shape, maxLength, or enum), an unknown activity_slug, or a bad target (org.target_*)
429Per-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.
500Internal server error
將在 app 版本 1.17.0 中推出