API reference

notifi API documentation

One endpoint, seven parameters. One source generates this page, /openapi.json and the client collections, so they cannot disagree.

View as Markdown

Quickstart Authentication Request Parameters Response Errors Rate limits Clients and import For agents and crawlers Recipes

Quickstart

Install notifi on iPhone or iPad or Mac, allow notifications, open Keys and copy the Device key. It starts with nk_.

curl -X POST https://notifi.it/send \
  -H "Authorization: Bearer $NOTIFI_KEY" \
  -d "title=Hello from notifi" \
  -d "message=Your first notification." \
  -d "link=https://notifi.it/docs" \
  -d "image=https://notifi.it/anaglyph-bell.png"

Authentication

Use a bearer token. A key parameter works too, but ends up in server logs. Use it for a quick test only, then rotate the key.

MethodSent asNotes
Bearer token Authorization: Bearer nk_yourkey The send key from the app’s Keys tab, as Authorization: Bearer nk_yourkey. Preferred: edge logs and shell history do not record a header.
Parameter key=nk_yourkey The send key as a parameter. It appears in edge logs, in shell history and in any proxy in between, which makes it the weaker option. Use it only for a quick test, and rotate the key afterwards.

Request

POST https://notifi.it/send as JSON, form-encoded or multipart. GET takes the same parameters in the query string, for quick tests only: rotate the key afterwards. Query parameters win over body fields.

POST /send HTTP/1.1
Host: notifi.it
Authorization: Bearer nk_yourkey
Content-Type: application/json
Accept-Language: en-GB

{"title":"Hello from notifi","message":"Your first notification.","link":"https://notifi.it/docs","image":"https://notifi.it/anaglyph-bell.png"}

Parameters

key is required unless the request carries a bearer token.

NameTypeRequiredLimitDescription
key string conditional nk_… The send key, unless you send it as a bearer token. The key picks the device that receives the notification. Two keys, comma-separated, send to two devices in one request, one per platform.
title string required 1–200 chars The notification title. notifi crops a longer title and adds a warning to the response.
message string optional ≤ 16,000 chars The notification body, in Markdown. notifi crops a longer body and adds a warning.
link string (uri) optional ≤ 2,048 chars A link to a website or internal app. Opens when you tap the notification. https always opens; another scheme (shortcuts://run-shortcut?name=Deploy, or an app’s own deep link) opens only when the key’s Open any link switch is on in the app, and the app hides the link otherwise.
image string (uri) optional ≤ 2,048 chars URL of an image shown with the notification. The receiving device fetches it; the server never does. By default the app loads it only when you tap it.
occurred_at integer optional unix ms When the event happened, as unix milliseconds. For a queued or retried send. Only changes the timestamp shown in the app; defaults to the time the server accepted the request.
is_critical boolean optional none Breaks through Focus. The key must also have urgent alerts switched on in the app, or notifi delivers an ordinary notification.

Response

202 means accepted. Delivery is best-effort, per the terms. Every status the endpoint can answer:

accepted
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8

{"ok":true}

The response carries a warnings array only when notifi delivered the notification differently from the request: a cropped title or body, or is_critical on a key without urgent alerts. The status stays 202: notifi sent the notification, in the altered form each warning describes.

HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8

{"ok":true,"warnings":["Title shortened to 200 characters."]}

Two devices in one request

Join two keys with a comma to send to both, one per platform: an iPhone or iPad and a Mac. notifi delivers to each device separately, with its own rate limit. The response then carries sent, how many devices received it, and results, one entry per key named by the prefix the Keys tab shows. The status is 202 if at least one device received the notification, otherwise the first error's. Two keys on the same platform get 400 invalid_request.

curl -X POST https://notifi.it/send \
  -H "Authorization: Bearer $NOTIFI_KEY_PHONE,$NOTIFI_KEY_MAC" \
  -d "title=Deploy finished"
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8

{"ok":true,"sent":1,"results":[{"key":"nk_abcd","ok":true},{"key":"nk_wxyz","ok":false,"error":{"code":"rate_limited","message":"Not sent. Daily limit of 25 notifications reached. Resets at midnight UTC."}}]}

notifi crops over-length text

notifi crops a title over 200 characters or a body over 16000 and adds a warning. With Reject invalid sends on in the app's Settings, the server answers 422 invalid_content instead and stores nothing. The switch is off by default.

The Settings screen, showing the Reject invalid sends switch turned off.
Settings → Permissions → Reject invalid sends. Off by default.

Urgent alerts are per key

is_critical=1 asks for a Time Sensitive notification, which breaks through Focus. It works only if the key has Urgent alerts on, in the app. Otherwise notifi delivers an ordinary notification.

A key's screen in the app, showing the Urgent alerts switch turned on.
Keys → a key → Urgent alerts. Per key.

link accepts any URL scheme, so it can deep-link into another app. The app opens only https until you switch on Open any link for the key, and only the person holding the device can do that.

A key's screen in the app, showing the Open any link switch.
Keys → a key → Open any link. Off, only https opens.

Errors

Every error nests the code one level down: read error.code. The message is translated for a human reader, so match on the code.

Statuserror.codeMeaning
400 invalid_request A parameter is missing or malformed.
401 unknown_key The key is unknown or revoked.
422 invalid_content The device is set to refuse a notification it cannot deliver as written.
429 rate_limited Over the daily device limit or the per-minute IP limit. Carries a Retry-After header with the seconds until the window resets.
429 uncollected_limit The device has 500 uncollected notifications. No Retry-After: the limit clears when the device next collects. Open the app on the device.
404 not_found No such path.
500 internal_error The server hit an unexpected error.

Rate limits

A 429 carries Retry-After in seconds.

Clients and import

These come from the same source as this page. Set NOTIFI_KEY and send.

postman
# Import → Link, then paste this. Postman keeps it in sync from there.
https://notifi.it/notifi.postman_collection.json

For agents and crawlers

The site also serves every page as Markdown: send Accept: text/markdown, or append .md.

One endpoint and a bearer token make up the whole surface. There is no MCP server and no OAuth.

Recipes

The same request in 15 languages and tools. Each expects NOTIFI_KEY in the environment.

send.sh
curl -X POST https://notifi.it/send \
  -H "Authorization: Bearer $NOTIFI_KEY" \
  -d "title=Hello from notifi" \
  -d "message=Your first notification." \
  -d "link=https://notifi.it/docs" \
  -d "image=https://notifi.it/anaglyph-bell.png"

Questions

The FAQ covers cost, limits, what the server can read and what happens when you delete the app. If yours isn't there, write to hello@notifi.it.