Notifications and notification subscriptions

Read a Person's notification inbox, set which channels deliver notifications, and route an Account's notifications to specific people with the V3 API.

This page covers three things: the notification inbox of a Person, the channels that deliver notifications, and subscriptions that route an Account's notifications to the people who should see them.

A notification is created from a template. Each template has a handle (for example InvoicePaid) and a group. Wingspan creates the notification for each recipient and delivers it on the channels the recipient allows: InApp, Email or SMS. Your integration does not create notifications. The routes that emit and clear notifications are internal and are not part of the public API.

Prerequisites

  • A Person login session or token for the inbox and channel-settings routes. These routes act on the signed-in Person only.
  • For subscriptions, a credential with notifications.notification:read to read and notifications.notification:write to create or delete, and X-Wingspan-Account set to the Account whose notifications you route.

Endpoints

PurposeMethod and path
List inboxGET /v3/platform/persons/{personId}/notifications
Get a notificationGET /v3/platform/persons/{personId}/notifications/{notificationId}
Mark viewedPOST /v3/platform/persons/{personId}/notifications/{notificationId}/view
DismissPOST /v3/platform/persons/{personId}/notifications/{notificationId}/dismiss
Bulk mark viewedPOST /v3/platform/persons/{personId}/notifications/bulk-view
Bulk dismissPOST /v3/platform/persons/{personId}/notifications/bulk-dismiss
Get channel settingsGET /v3/platform/persons/{personId}/notification-channel-settings
Update channel settingsPATCH /v3/platform/persons/{personId}/notification-channel-settings
List templatesGET /v3/platform/notification-templates
List subscriptionsGET /v3/platform/notification-subscriptions
Create a subscriptionPOST /v3/platform/notification-subscriptions
Get a subscriptionGET /v3/platform/notification-subscriptions/{subscriptionId}
Delete a subscriptionDELETE /v3/platform/notification-subscriptions/{subscriptionId}

Person-scoped routes

The inbox, bulk and channel-settings routes belong to a Person, not an Account. Do not send X-Wingspan-Account on them. If you do, the API returns 400 with code: AccountScopeNotApplicable. If personId is not the Person you are signed in as, the API returns 404 ResourceNotFound.

Read the inbox

curl -g "https://api.wingspan.app/v3/platform/persons/Pq3mT8vLw2NzKc5xRb7HdA/notifications?filter[priority][eq]=High&page[size]=25" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN"

Results are newest first. There is no sort parameter. When you omit filter[status][anyOf], the list returns Active and Viewed notifications. Only notifications whose InApp delivery reached Sent or Delivered appear.

FilterValues
filter[status][anyOf][]Active, Viewed, Dismissed
filter[priority][eq]Low, Normal, High
filter[handle][eq], filter[group][eq]Template handle or group. See List templates.
filter[subjectAccountId][eq]Notifications about one Account
filter[isPersonal][eq]true for notifications that belong to the Person and not to an Account
filter[createdAt][gte], filter[createdAt][lte]Date-time range

To count unread notifications, request filter[status][anyOf][]=Active and read pagination.totalSize.

{
  "url": "/v3/platform/persons/Pq3mT8vLw2NzKc5xRb7HdA/notifications?filter[priority][eq]=High",
  "data": [
    {
      "id": "Hk9rW4tNx2LbQv6cYm8DeP",
      "handle": "InvoicePaid",
      "status": "Active",
      "priority": "High",
      "type": "Dismissable",
      "subject": "Invoice paid",
      "message": "Invoice 1042 was paid.",
      "personId": "Pq3mT8vLw2NzKc5xRb7HdA",
      "subjectAccountId": "Nw7kQ2pLx9RtVb3mHc5dZa",
      "channels": ["InApp", "Email"],
      "events": { "createdAt": "2026-11-02T14:05:11.000Z" }
    }
  ],
  "pagination": { "nextPageToken": "", "totalSize": 1 }
}

The example values are illustrative. A notification also carries actionTitle, actionUrl, attachments, deliveries, referenceKey, expiresAt, context and metadata when they apply.

Mark viewed or dismiss

Status moves one way: Active, then Viewed, then Dismissed. Both calls take no body and return the updated notification.

curl -X POST "https://api.wingspan.app/v3/platform/persons/Pq3mT8vLw2NzKc5xRb7HdA/notifications/Hk9rW4tNx2LbQv6cYm8DeP/view" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
StatusCause
404The notification does not exist, or belongs to another Person.
409 InvalidStateTransitionYou viewed a Dismissed notification, or you dismissed a NonDismissable one.
409 IdempotencyKeyConflictYou replayed an Idempotency-Key with a different request.

Bulk view and bulk dismiss

Send exactly one of filter or notificationIds. notificationIds takes 1 to 100 IDs. filter accepts subjectAccountId, isPersonal, status, handle, group, priority, createdAtGte and createdAtLte. If you omit limit in a filter, every match is selected. isPersonal: true together with subjectAccountId returns 400.

curl -X POST "https://api.wingspan.app/v3/platform/persons/Pq3mT8vLw2NzKc5xRb7HdA/notifications/bulk-dismiss" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "filter": { "handle": "InvoicePaid" } }'

The response is 202 with an operation. A small selection can come back already Completed. Otherwise status is Processing: poll the URL in the Location header with the same Person token and no account header until the status is terminal. See Async operations. result reports matched, succeeded, skipped and failed. Bulk dismiss skips NonDismissable notifications and counts them in skipped.

Choose delivery channels

Get channel settings always works. A Person who never changed anything has defaultChannels of isInAppEnabled: true, isEmailEnabled: true, isSmsEnabled: false, and no overrides.

Update channel settings changes only the flags you send. If you send overrides, the list replaces the whole existing list, and [] clears it. Each override sets exactly one of handle or group, plus any of isInAppEnabled, isEmailEnabled and isSmsEnabled. Flags you leave out inherit defaultChannels. Templates that force delivery ignore these settings.

curl -X PATCH "https://api.wingspan.app/v3/platform/persons/Pq3mT8vLw2NzKc5xRb7HdA/notification-channel-settings" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "defaultChannels": { "isSmsEnabled": true },
    "overrides": [ { "handle": "InvoicePaid", "isEmailEnabled": false } ]
  }'

An override with both or neither of handle and group returns 422.

Route an Account's notifications with subscriptions

A subscription is a routing rule: notifications on an Account that match a handle or a group go to a recipient Person's inbox. Use List templates to see the valid values. The list is the same for every Account, and it rejects X-Wingspan-Account.

curl -X POST https://api.wingspan.app/v3/platform/notification-subscriptions \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "X-Wingspan-Account: Nw7kQ2pLx9RtVb3mHc5dZa" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "Nw7kQ2pLx9RtVb3mHc5dZa",
    "recipientPersonId": "Pq3mT8vLw2NzKc5xRb7HdA",
    "handle": "InvoicePaid"
  }'
FieldRequiredNotes
accountIdYesThe Account whose notifications are routed.
recipientPersonIdYesMust be a Stakeholder on that Account.
handle or groupExactly onehandle is an exact template handle. group is a coarser set.
externalId, metadataNoYour own reference and key-value data.

Subscriptions cannot be edited. To change routing, delete the subscription and create a new one. Delete is a soft delete: the record gets events.deletedAt, and List subscriptions hides it unless you pass filter[includeDeleted][eq]=true. List also filters by recipientPersonId, handle and group. It does not filter by externalId.

StatusCause
400A malformed request.
409 ResourceConflictA subscription with the same routing already exists. Create is not an upsert.
422You sent both or neither of handle and group, or another field is invalid.
404The subscription does not exist for this Account.

Webhook events

These events are published: Notification.Created, Notification.Sent, Notification.Delivered, Notification.Failed, Notification.Viewed, Notification.Dismissed, NotificationSubscription.Created and NotificationSubscription.Deleted. See Event types.


Did this page help you?