Skip to content

Notification API reference

The notification API runs on port 9876 and exposes a single endpoint for sending a notification to a specific member. The agent binds the port on all interfaces, and access is gated by a bearer-token API key.

All requests require a bearer token in the Authorization header:

Authorization: Bearer <api-key>

The API key is generated automatically on first startup, stored in the agent’s data volume, and rotatable from the dashboard. See the Notification API overview for details.

POST /v1/notify

Send a notification to a single member. The agent encrypts the payload to that member’s identity key (libsodium sealed-box) and relays it to atreoLINK for delivery to their phones and browsers.

{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"userEmail": "alice@example.com",
"title": "Backup complete",
"body": "Daily backup finished. 4.2 GB synced.",
"html": "<p>Daily backup finished. <strong>4.2 GB synced.</strong></p>",
"plaintext": "Daily backup finished. 4.2 GB synced.\n\nDuration: 12m 47s.",
"contentType": "text/html",
"severity": "info",
"emailFrom": "backup@home.example.com",
"emailSubject": "Daily backup report"
}
FieldTypeRequiredDescription
userIdstringone ofRecipient’s atreoLINK user ID. Mutually exclusive with userEmail.
userEmailstringone ofRecipient’s atreoLINK account email. Mutually exclusive with userId.
titlestringyesNotification title. Shown on the lockscreen and in the inbox.
bodystringyesPlain body. The first 200 characters seed the lockscreen excerpt; the inbox falls back to this if no html or plaintext is sent.
htmlstringnoOptional rich HTML body. Rendered in a sandboxed dark-themed view. JavaScript blocked.
plaintextstringnoOptional full plaintext body. Rendered with monospace formatting in the inbox.
contentTypestringnotext/html or text/plain. Tells the inbox which view to default to. Inferred from which fields are sent if omitted.
severitystringnoinfo, warning, or error. Defaults to info.
emailFromstringnoOptional sender metadata, surfaced in the inbox under the title.
emailSubjectstringnoOptional subject metadata.

Exactly one of userId / userEmail is required.

{
"userId": "550e8400-e29b-41d4-a716-446655440000",
"sent": true
}

401 when the bearer token is missing or wrong, 400 when the request is malformed, 404 when no member matches the address, 413 when the request body exceeds 64 KiB, 500 on relay failure. See Rate limits for over-budget behavior.

The total request body is capped at 64 KiB. The bulk of that budget is typically the html field; trim or skip it if you’re getting 413 responses.

Two caps apply to the notify path. A request must pass both, or it’s rejected.

ScopeLimitKeyed by
Per server (all senders on this agent)120 / minutethe agent’s server identity
Per recipient60 / minuteuserId (resolved from userEmail if you sent that instead)

The per-recipient bucket is shared across every server a recipient is linked to and every device they’ve paired — one member can’t receive more than 60 notifications per minute in total, no matter how many servers or apps are sending.

If you hit a limit, back off and retry; the agent doesn’t queue rejected requests.

The agent encrypts the three content fields separately using libsodium sealed-box (crypto_box_seal, X25519 plus XChaCha20-Poly1305) to the recipient’s identity public key. atreoLINK never sees plaintext. See Encryption for the full story.

atreoLINK’s archive keeps the 100 most recent notifications per recipient.

Terminal window
# Send to one member by email
curl -X POST http://127.0.0.1:9876/v1/notify \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"userEmail": "alice@example.com",
"title": "Download complete",
"body": "your-file.zip is ready",
"severity": "info"
}'

Other Docker containers on the same host can reach the API via the host network. The agent runs with network_mode: host, so any other container can hit host.docker.internal:9876 or the host’s LAN IP.

Terminal window
curl -X POST http://host.docker.internal:9876/v1/notify \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"userEmail":"alice@example.com","title":"Disk usage","body":"/data is 92% full","severity":"warning"}'

WireGuard is a registered trademark of Jason A. Donenfeld.