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 fieldsGlossaryLinks, images and buttons
A notification can carry a link two ways, and both end up in the same place.
Links#
The url field is the notification's link. It appears as a button on the detail screen, and
as the Open Link button on the notification itself when you also send actions: ["open"].
A URL written inside title or body becomes tappable on its own. The app detects addresses
in the text the way Messages and Mail do, which matters because a sender has one url field and
routinely has two things worth pointing at:
{
"source": "CI",
"title": "Build 4181 failed",
"body": "Log: https://ci.yourcompany.com/b/4181 Commit: https://git.yourcompany.com/c/9f3a1c"
}
Both links are live, without spending the url field on either.
Tapping the notification itself opens its link. A notification with a url goes straight to the page when its banner is tapped, the way Prowl did; one without opens the app on that notification. The same rule applies to a row in the app's feed.
Where they open is the person's choice, not yours. In Settings › Links they pick Nowlark's own in‑app browser or their default browser, and every link in the app honours it: the detail screen's button, an address inside the text, and the Open Link button on the notification, which is tapped without the app being open at all. A sender cannot override this, and there is no field to ask.
Only http and https. Prowl passed any scheme through. A link is something a phone opens on
a tap, so the scheme is not a remote sender's to choose: anything else is refused 400
invalid_request. The same rule applies to a URL detected inside the text, where the app
additionally allows mailto: and tel:, which the phone, not a browser, handles.
Images#
A notification can show a picture: on the notification itself and in the app.
An image already on the web: put its https address in image. The phone fetches it when the
notification arrives; if it cannot, the notification arrives without the picture.
A screenshot or any file on your machine: upload it, then send with the id you get back. You need no server or file host of your own.
id=$(curl -sf https://nowlark.com/v1/images -H "X-Nowlark-Key: nlk_…" \
--data-binary @failed-step.png | jq -er .id) || { echo "upload refused"; exit 1; }
curl https://nowlark.com/v1/notify -H "X-Nowlark-Key: nlk_…" -H 'Content-Type: application/json' \
-d "{\"source\":\"Job applications\",\"title\":\"Application not sent\",\"image_id\":\"$id\"}"
POST /v1/images takes the file as the request body, or as the one file of a
multipart/form-data form (curl -F file=@shot.png). It answers:
{"id": "img_…", "content_type": "image/png", "size": 48213, "expires_unused_at": 1789752000.0}
size is in bytes; expires_unused_at is in epoch seconds.
- PNG or JPEG, up to 5 MB. Nowlark checks the file's contents, so any
Content-Typewill do, and a file that is not a real PNG or JPEG is refused415 unsupported_imagewhatever its name or header says. Over 5 MB is413 image_too_large. - Private by link. Each image gets an unguessable address that only its notification carries, to your devices. Images are never listed, and they are served with headers that tell search engines not to index them and caches not to store them.
- Tied to your account. Any of your send keys can use an id. An id another account uploaded,
or one that has expired, is refused
400 invalid_request, and so is a send with bothimageandimage_id. - A day to send it. An id you have not sent with yet expires 24 hours after the upload
(
expires_unused_at). Until then you can send it as many times as you like. - Then kept as long as the notification. Once sent, the image stays for as long as any notification showing it is in your history, or a scheduled send is waiting to show it. When the last of them is deleted, or leaves your history, Nowlark deletes the image. A notification already on a phone keeps its picture until it is cleared there.
- Needs the Upgrade Pass, bought in the Nowlark app, like
image. Without it,POST /v1/imagesreturns402 upgrade_required. - 50 MB of images per account. Past that,
POST /v1/imagesreturns409 image_store_full. Space frees up as notifications with images are deleted or leave your history. Sends, including ones with an id you already have, are not affected.
Buttons#
actions puts up to three buttons on the notification, chosen from a fixed
vocabulary. It is fixed because iOS renders buttons from a category the app
registered before the notification arrived. Nothing in a payload can name a
button, so the set has to be knowable in advance.
| verb | button | what it does |
|---|---|---|
open |
Open Link |
opens url. Requires url, or the send is refused |
copy |
Copy |
puts copy_text on the clipboard without opening the app |
mute |
Mute Source |
mutes this source |
done |
Mark as Read |
marks it read from the Lock Screen |
{
"source": "Staging",
"title": "Sign-in code for the new build",
"body": "Valid for ten minutes",
"url": "https://staging.yourcompany.com/login",
"actions": ["copy", "open"],
"copy_text": "4K2P-99MX-TTQ1"
}
copy is the one worth reaching for. A code you were sent is most useful
copied straight off the Lock Screen, without unlocking anything.