API reference menu
Getting started
OverviewAuthentication and rate limitExamplesSending
Send a notificationPriority and repeatLinks, images and buttonsSourcesScheduled sendsWebhook templatesReceipts and replies
Receipts and callbacksRepliesTeams
Teams, roles and endpointsChannels and escalationWebhooks and emailAlert email and timelineTeam formsPlans, audit log and transferCompany sign‑in and SCIMThe web consoleAccount
Identity and moving phonesDevices, keys and historyThe Upgrade PassCompatibility
ntfy's publish APIProwl's APIAppendix
Endpoint indexErrors and status codesLimitsPriorities and fieldsGlossaryChannels and escalation
Sending to a channel#
A channel key is an nlk_ key that can send to one channel and nothing else. Use it exactly as
any send key: POST /v1/notify. One send is one thread, delivered as one copy per channel member.
- Each copy is the member's own and goes through the same path as a personal notification, so their
mute, priority cap, tone and read state apply to it. One member muting does not mute the team. The
source appears in their list as
<Team name> / <source>, so the team's sources are muted and coloured apart from their own. - The owner's pass decides images and buttons, not each member's. A member on a free account receives them.
idin the response is the thread's,membersis how many it went to, anddeliveredanddevicesadd up across them.- Ack policy. On
any, the first member to open their copy ends repeating (Urgent priority) for everyone. Onall, each member keeps being alerted until they open their own. Which applied is fixed when the thread is sent. GET /v1/receipts/{id}on a thread says how many members it reached, who has opened it (by the names they chose for the team), the policy, and whether the policy is met (acknowledged).- Scheduling, recurring sends,
ttl,tagsanddevicesall work on a channel send.dedupe_keyis per channel.callback_urlis refused (400), not ignored: read the receipt instead. - A channel key is narrow on purpose. It shares its maker's account but not their data: it cannot
register sources, cannot read or cancel anything of its maker's, does not appear in their key list,
and reads receipts only for its own channel's threads. It carries its maker's authority, judged each
time it is used: it stops working the moment its maker leaves or is removed from the team, is demoted
below
sender, leaves the channel (unless an admin or owner), or the key is revoked or the channel deleted. A scheduled or recurring send it made is judged the same way when it fires, and fails then. - A personal key reads a thread's receipt if its account is an admin or owner of the team, or a sender on that thread's channel.
Escalation#
A channel can notify one group at once and others later, if nobody has opened the alert.
curl -X PUT https://nowlark.com/v1/channels/chn_…/escalation -H "Authorization: Bearer nla_…" \
-H 'Content-Type: application/json' -d '{"tiers":[
{"members":["acct_…"], "after":0},
{"members":["acct_…","acct_…"], "after":600},
{"members":"all", "after":1800}],
"repeat":2, "repeat_after":900}'
- Tier one is notified when the send arrives (
afteris0). Each later tier is notifiedafterseconds into the alert, strictly later than the one before: 60 s to 24 h, up to 5 tiers.membersis a list of member ids on the channel (themember_idfromGET /v1/teams/{id}), or"all"for everyone on it when the tier fires. - Opened by anyone, by any route, cancels it. Whether to escalate is read from the members'
own copies at the moment a tier is due: if any has been read or acknowledged, the tier is skipped.
Nothing has to cancel it, so no route can forget to. Once a later tier opens it, every tier's
repeats stop (the channel's
anypolicy). - Evaluated when it fires. A member who has left the channel by then is not paged. The policy is copied when the alert is sent, so editing or clearing it does not change one in flight.
- Needs a channel whose
ack_policyisany(409 escalation_needs_anyotherwise): onallevery member must open it, so there is no "nobody has" to escalate on. - Repeat the steps.
repeat(0 to 3, default 0) runs every tier again that many times until someone opens it, startingrepeat_afterseconds (60 s to 24 h, required whenrepeatis set) after the last tier of the pass before. With the example above: tier two at 10 min, tier three at 30 min, then tier one again at 45 min, tier two at 55 min, and so on. Someone already holding the alert is pinged again on the alert they have, not sent a second one; someone who joined the channel since gets it for the first time. Anyone who has muted the source is not pinged again. With one tier, a repeat pings the same people again.GETreturns{"tiers", "repeat", "repeat_after", "until_opened"}. - Repeat until someone opens it.
"until_opened": true, in place ofrepeat, runs the whole ladder again, each pass startingrepeat_afterseconds after the last tier of the one before, for as long as nobody has opened it, by any route (reading, taking or answering it). It stops 24 hours after the alert was sent or after 48 repeats, whichever comes first. - Works on scheduled and recurring channel sends. The receipt gives
tier(the tier last notified, 1 being the send itself),repeat(which pass that was, 0 the first) andnext_escalation_at(null once opened). - Delivered within one scheduler tick (15 seconds) after the tier's time. An interrupted escalation picks up where it stopped, and nobody is pushed twice for one tier.