Push Notifications EndpointsView Markdown ↗

Send Push Notification

Sends a push notification to devices matched by API key scope and optional target channels. Supports optional redirection URL, optional media preview or playback when the notification is expanded, and up to 4 interactive actions. media cannot be combined with actions. Optional icon shows a custom image, such as a logo or avatar, next to a smaller app icon. Optional interruption_level sets how urgently iOS presents the notification. Optional tags to organize and filter notification history.

POST https://activitysmith.com/api/push-notification

Authentication#

Use your API key in the request header.

Authorization: Bearer $YOUR_API_KEY

Request examples#

import ActivitySmith from "activitysmith";
const activitysmith = new ActivitySmith({
apiKey: process.env.ACTIVITYSMITH_API_KEY,
});
await activitysmith.notifications.send({
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
});

Bodyapplication/json

metadataMetadata
titlestringrequired
messagestring
subtitlestring
iconstring<uri>
Optional HTTPS image URL without credentials for a custom notification icon. If the image cannot be loaded, the app icon is used. iOS may omit subtitle when displaying a custom icon.
Pattern: ^https://
interruption_levelPushInterruptionLevel
Optional. How urgently iOS presents the notification: passive (quiet, no sound or screen wake), active (default), or time-sensitive (can break through Focus and Scheduled Summary when allowed). Omit for normal delivery.
mediastring<uri>
Optional HTTPS URL for an image, audio file, or video that users can preview or play when they expand the notification. If redirection is omitted, tapping the notification opens this URL. Cannot be combined with actions.
Pattern: ^https://
redirectionstring<uri>
Optional HTTP, HTTPS, Shortcuts, or installed app URL opened when the user taps the notification body. Custom schemes such as spotify:// and spotify:track:123 require iOS 1.13.4 build 2 or later and an installed handler; no web fallback is provided. Internal and executable schemes are blocked. Overrides the default tap target from media.
Pattern: ^[A-Za-z][A-Za-z0-9+.-]*:
Max Length: 2048
actionsarray of PushNotificationAction
Optional interactive actions shown when users expand the notification. Cannot be combined with media.
Max Items: 4
payloadobject
Additional Properties: true
badgeinteger
soundstring
targetChannelTarget
tagsTagSlugs

Additional Properties: false

default

{
"title": "New subscription 💸",
"message": "Customer upgraded to Pro plan"
}

channel targeted

{
"title": "New subscription 💸",
"message": "Customer upgraded to Pro plan",
"target": {
"channels": [
"devs",
"ops"
]
}
}

redirection

{
"title": "Incident Resolved ✅",
"message": "All systems operational",
"redirection": "https://status.example.com/incidents/abc-123"
}

media preview

{
"title": "Homepage ready",
"message": "Your agent finished the redesign.",
"media": "https://cdn.example.com/output/homepage.png"
}

media preview with redirection

{
"title": "Homepage ready",
"message": "Your agent finished the redesign.",
"media": "https://cdn.example.com/output/homepage.png",
"redirection": "https://github.com/acme/web/pull/482"
}

actions open url

{
"title": "Release Candidate Ready 🚀",
"message": "v2.14.0-rc.1 deployed to staging",
"actions": [
{
"title": "View CI Run",
"type": "open_url",
"url": "https://github.com/activitysmithhq/backend/actions/runs/1234567890"
},
{
"title": "Release Notes",
"type": "open_url",
"url": "https://github.com/activitysmithhq/backend/releases/tag/v2.14.0-rc.1"
}
]
}

actions webhook

{
"title": "Build Failed 🚨",
"message": "Tap and hold for remediation actions",
"redirection": "https://ci.example.com/builds/8842",
"actions": [
{
"title": "Retry Build",
"type": "webhook",
"url": "https://hooks.example.com/activitysmith/build-retry",
"method": "POST",
"body": {
"build_id": "8842",
"source": "push_action"
}
}
]
}

Organize notification history with tags

{
"title": "New subscription 💸",
"message": "Customer upgraded to Pro plan",
"tags": [
"user:382",
"billing"
]
}

Show a custom icon

{
"title": "MRR just crossed $10,000 🎉",
"message": "Up 18% this month from 31 new subscriptions.",
"icon": "https://cdn.activitysmith.com/integrations/icons/stripe.png"
}

Deliver as Time Sensitive

{
"title": "🚨 checkout-api is down",
"message": "500 errors on 62% of requests. Customers can't complete payments.",
"interruption_level": "time-sensitive"
}

Responses#

200#

Push notification sent

Content type: application/json

Schema: PushNotificationResponse#

Apple APNs acceptance result. Acceptance does not confirm device delivery or presentation. Alerts remain eligible for APNs delivery retries for 24 hours; device settings and APNs storage policies still apply.

successbooleanrequired
True when APNs accepts the notification for at least one targeted device.
notification_idstring
ID of this Push Notification. Pass it to PUT /push-notification/{notification_id} to replace the notification later.
devices_notifiedinteger
Number of device tokens for which APNs accepted the notification, without confirming on-device delivery.
users_notifiedinteger
effective_channel_slugsarray of string or null
tagsTagSlugs
timestampstring<date-time>required
devices_targetedinteger
Number of device tokens targeted.
devices_deactivatedinteger
Number of device tokens deactivated because APNs reported them unregistered.
devices_unregisteredinteger
Number of targeted device tokens APNs reported as unregistered.
credential_testboolean
True when the request was an integration connection test and no paired devices were available.
messagestring

Additional Properties: false

default

{
"success": true,
"notification_id": "Xk3pQ8mV2nR7tL9wB4yZ",
"devices_notified": 2,
"users_notified": 1,
"timestamp": "2025-08-12T12:00:00.000Z"
}

channel targeted

{
"success": true,
"notification_id": "Xk3pQ8mV2nR7tL9wB4yZ",
"devices_notified": 2,
"users_notified": 1,
"effective_channel_slugs": [
"devs",
"ops"
],
"timestamp": "2025-08-12T12:00:00.000Z"
}

tagged

{
"success": true,
"notification_id": "Xk3pQ8mV2nR7tL9wB4yZ",
"devices_notified": 2,
"users_notified": 1,
"effective_channel_slugs": null,
"tags": [
"user:382",
"billing"
],
"timestamp": "2025-08-12T12:00:00.000Z"
}

400#

Bad request (invalid payload or channel targeting input)

Content type: application/json

Schema: BadRequestError#

errorstringrequired
messagestringrequired

Additional Properties: true

invalid target

{
"error": "Invalid channel targeting",
"message": "target.channels must be an array of channel slugs"
}

invalid tags

{
"error": "Invalid tags",
"code": "invalid_tags",
"message": "tags must use 1-64 lowercase letters, numbers, dashes, underscores, periods, or colons"
}

402#

Billing access required

Content type: application/json

Schema: BillingBlockedError#

errorstringrequired
Enum: ["trial_expired","trial_exhausted","billing_overage_cap_reached"]
messagestringrequired
trial_periodobject
trial_period.started_atstring<date-time>required
trial_period.ends_atstring<date-time>required
upgrade_urlstring<uri>required

Additional Properties: true

403#

Forbidden (API key scope or channel assignment violation)

Content type: application/json

Schema: ForbiddenError#

errorstringrequired
messagestringrequired

Additional Properties: true

channel scope violation

{
"error": "Invalid channel targeting",
"message": "This API key can only target assigned channels. Requested channels include channels outside this key scope."
}

422#

No recipients found for effective channel target

Content type: application/json

Schema: NoRecipientsError#

errorstringrequired
messagestringrequired
effective_channel_slugsarray of string or null

Additional Properties: true

no devices

{
"error": "No recipients found",
"message": "No devices matched the effective channel target",
"effective_channel_slugs": [
"marketing"
]
}

429#

Rate limit exceeded

Content type: application/json

oneOf

Schema: RateLimitError

Schema: LiveActivityLimitError

rate limited

{
"error": "Rate limit exceeded",
"message": "Too many requests, please try again later."
}

Download the OpenAPI specification