Skip to content

REST API Documentation

Notifly provides a REST API for managing channels, clients, messages, monitoring, metrics, and users. All examples use the base URL https://notifly.ru (you can substitute it using the $NOTIFLY_URL variable). The admin UI (web interface) lives at https://app.notifly.ru/.

Notifly uses three types of tokens:

ТипПрефиксНазначение
App-токенAТолько отправка сообщений (POST /message, POST /ask)
Client-токенCУправление ресурсами и получение сообщений
MCP-кодMМашинный доступ (read или read+write), см. MCP

The token can be passed in three ways:

Окно терминала
# 1. Header X-Notifly-Key
curl -H "X-Notifly-Key: CaQw5lL_L.yiRbN" https://notifly.ru/application
# 2. Query parameter
curl "https://notifly.ru/application?token=CaQw5lL_L.yiRbN"
# 3. Bearer token
curl -H "Authorization: Bearer CaQw5lL_L.yiRbN" https://notifly.ru/application

Basic Auth (username/password) is also supported wherever a client token is accepted.


Endpoints are available without authentication.

Окно терминала
curl https://host/health
{"health": "green", "database": "green"}
Окно терминала
curl https://host/version
{"version": "ya-1.0.0", "commit": "...", "buildDate": "..."}
Окно терминала
curl https://host/serverinfo
{"version": "ya-1.0.0", "register": false, "oidc": false}

POST /auth/local/login — login with username/password

Section titled “POST /auth/local/login — login with username/password”

Creates a client session. Returns a client token and sets a cookie.

Окно терминала
curl -u admin:admin https://host/auth/local/login \
-X POST -d "name=my-cli-client"
{
"id": 1,
"name": "my-cli-client",
"token": "CaQw5lL_L.yiRbN",
"user_id": 1,
"platform": "web"
}
Окно терминала
curl -H "X-Notifly-Key: CaQw5lL_L.yiRbN" \
https://host/auth/logout -X POST

POST /user/reset-password — request password reset

Section titled “POST /user/reset-password — request password reset”

Public endpoint (no authentication). Sends an email to the specified address with a password reset link. The response is always 200, even if the user does not exist — this avoids revealing which addresses are registered.

Окно терминала
curl https://host/user/reset-password \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com"}'

POST /user/reset-password/confirm — confirm password reset

Section titled “POST /user/reset-password/confirm — confirm password reset”

Public endpoint. Accepts the token from the email and a new password pass.

Окно терминала
curl https://host/user/reset-password/confirm \
-H "Content-Type: application/json" \
-d '{"token": "<из письма>", "pass": "новый-пароль"}'

Public endpoint. Opened via a link from the verification email (/user/verify?token=...) and activates the user’s address.

Окно терминала
curl "https://host/user/verify?token=<из письма>"

A channel (application in the API URL — for compatibility with the Gotify protocol) is a source of messages. Each channel has its own app token for sending.

Окно терминала
curl -u admin:admin https://host/application
[
{
"id": 1,
"token": "AGdjfk_L.dKe8q",
"name": "Мониторинг",
"description": "Оповещения от системы мониторинга",
"internal": false,
"image": "image/appicon/1.png",
"defaultPriority": 5,
"lastUsed": "2025-01-15T12:00:00Z"
}
]
Окно терминала
curl -u admin:admin https://host/application \
-H "Content-Type: application/json" \
-d '{"name": "CI/CD", "description": "Уведомления о сборках", "defaultPriority": 5}'

Request fields:

ПолеТипОбязательноеОписание
namestringChannel name
descriptionstringDescription
defaultPriorityintegerDefault priority

PUT /application/{id} — update a channel

Section titled “PUT /application/{id} — update a channel”
Окно терминала
curl -u admin:admin https://host/application/1 \
-X PUT -H "Content-Type: application/json" \
-d '{"name": "CI/CD v2", "description": "Обновлённое описание"}'

DELETE /application/{id} — delete a channel

Section titled “DELETE /application/{id} — delete a channel”
Окно терминала
curl -u admin:admin https://host/application/1 -X DELETE

GET /application/{id}/status — aggregated channel status

Section titled “GET /application/{id}/status — aggregated channel status”

Returns the aggregated status of the channel (heartbeat summary, last activity).

Окно терминала
curl -u admin:admin https://host/application/1/status

POST /application/{id}/delivery/test — test delivery to external integrations

Section titled “POST /application/{id}/delivery/test — test delivery to external integrations”

Immediately (bypassing escalation) sends a test notification through the channel’s enabled outgoing adapters (Slack, Telegram, webhook) and returns the result for each. An optional body {"adapter": "slack"} limits the check to a single adapter.

Окно терминала
curl -u admin:admin https://host/application/1/delivery/test \
-H "Content-Type: application/json" -d '{"adapter": "telegram"}'
{"results": {"telegram": {"ok": true}, "slack": {"ok": false, "error": "..."}}}

Окно терминала
curl "https://host/message?token=AGdjfk_L.dKe8q" \
-H "Content-Type: application/json" \
-d '{"message": "Сборка #42 завершена", "title": "CI/CD", "priority": 5}'

Or via form-data:

Окно терминала
curl "https://host/message?token=AGdjfk_L.dKe8q" \
-F "title=CI/CD" -F "message=Сборка #42 завершена" -F "priority=5"

Request fields:

ПолеТипОбязательноеОписание
messagestringMessage text
titlestringTitle
priorityintegerPriority (0–10)
extrasobjectAdditional fields for clients (see. msgextras)

Example with extras (markdown content):

Окно терминала
curl "https://host/message?token=AGdjfk_L.dKe8q" \
-H "Content-Type: application/json" \
-d '{
"message": "**Готово!** Подробности: [ссылка](https://example.com)",
"title": "Сборка",
"priority": 5,
"extras": {
"client::display": {"contentType": "text/markdown"}
}
}'

Response:

{
"id": 123,
"appid": 1,
"message": "Сборка #42 завершена",
"title": "CI/CD",
"priority": 5,
"extras": {},
"date": "2025-06-01T10:30:00Z"
}

GET /message — all messages (with pagination)

Section titled “GET /message — all messages (with pagination)”
Окно терминала
curl -u admin:admin "https://host/message?limit=20"

Parameters:

ПараметрТипПо умолчаниюОписание
limitinteger100Number of messages (1–200)
sinceintegerPagination cursor: return messages older (with ID less) than the specified. Taken from paging.next of the previous page

Response:

{
"paging": {
"size": 20,
"limit": 20,
"since": 0,
"next": "https://host/message?limit=20&since=20"
},
"messages": [
{
"id": 1,
"appid": 1,
"message": "Текст сообщения",
"title": "Заголовок",
"priority": 5,
"extras": {},
"date": "2025-06-01T10:30:00Z"
}
]
}

GET /application/{id}/message — channel messages

Section titled “GET /application/{id}/message — channel messages”
Окно терминала
curl -u admin:admin "https://host/application/1/message?limit=50"

Searches the user’s messages. The q parameter is required (minimum 2 characters). Optional appId limits the search to a single channel. Supports pagination (limit, since).

Окно терминала
curl -u admin:admin "https://host/message/search?q=ошибка&limit=20"
curl -u admin:admin "https://host/message/search?q=deploy&appId=1"

POST /message/read — mark messages as read

Section titled “POST /message/read — mark messages as read”

Body: {"ids": [1, 2, 3]} — list of message IDs.

Окно терминала
curl -u admin:admin https://host/message/read \
-H "Content-Type: application/json" -d '{"ids": [1, 2, 3]}'

POST /application/{id}/message/read — mark entire channel as read

Section titled “POST /application/{id}/message/read — mark entire channel as read”
Окно терминала
curl -u admin:admin https://host/application/1/message/read -X POST
Окно терминала
curl -u admin:admin https://host/message -X DELETE
Окно терминала
curl -u admin:admin https://host/message/123 -X DELETE

DELETE /application/{id}/message — delete all messages in a channel

Section titled “DELETE /application/{id}/message — delete all messages in a channel”
Окно терминала
curl -u admin:admin https://host/application/1/message -X DELETE

A client is a device or application that receives messages and manages resources.

Окно терминала
curl -u admin:admin https://host/client
[
{
"id": 1,
"name": "firefox",
"token": "CaQw5lL_L.yiRbN",
"lastUsed": "2025-06-01T10:00:00Z"
}
]
Окно терминала
curl -u admin:admin https://host/client \
-H "Content-Type: application/json" \
-d '{"name": "my-script"}'
Окно терминала
curl -u admin:admin https://host/client/1 \
-X PUT -H "Content-Type: application/json" \
-d '{"name": "renamed-client"}'
Окно терминала
curl -u admin:admin https://host/client/1 -X DELETE
Метод и путьОписание
GET /client/onlineList of client tokens with an active WS connection
PUT /client/{id}/statusChange device status, body {"status": "active|suspended|revoked"}
GET /client/{id}/activityDevice activity log (?from=&to=&type=&limit=)
GET /client/{id}/subscriptionsDevice subscriptions to channels
PUT /client/{id}/subscriptionsBulk replace subscriptions, body {"channelIds": [1, 2]}

Device self-service (authentication using the device’s device token):

Метод и путьОписание
GET /device/me/subscriptionsOwn channel subscriptions
POST /device/me/subscriptionsSubscribe, body {"channelId": 1}
DELETE /device/me/subscriptions/{channel_id}Unsubscribe from a channel

GET /current/user — current user information

Section titled “GET /current/user — current user information”
Окно терминала
curl -u admin:admin https://host/current/user
{"id": 1, "email": "admin", "admin": true, "verified": true, "plan": "free", "balanceKopecks": 0}

POST /current/user/password — change password

Section titled “POST /current/user/password — change password”
Окно терминала
curl -u admin:admin https://host/current/user/password \
-H "Content-Type: application/json" \
-d '{"pass": "new-secure-password"}'

Details about plans and limits are on the Quotas and tariffs page.

Метод и путьОписание
GET /user/quota-breakdownDetailed breakdown of event consumption per day (?day=YYYY-MM-DD), hourly and per-minute
POST /current/user/planChange plan, body {"plan": "free|pro|business"}
POST /current/user/topupTop up balance, body {"amountRubles": N}
Окно терминала
curl -u admin:admin "https://host/user/quota-breakdown?day=2026-06-23"
curl -u admin:admin https://host/current/user/plan \
-H "Content-Type: application/json" -d '{"plan": "pro"}'

Окно терминала
curl -u admin:admin https://host/user
[
{"id": 1, "email": "admin", "admin": true, "verified": true, "plan": "free"},
{"id": 2, "email": "user1@example.com", "admin": false, "verified": true, "plan": "free"}
]
Окно терминала
curl -u admin:admin https://host/user \
-H "Content-Type: application/json" \
-d '{"email": "newuser@example.com", "pass": "password123", "admin": false}'
Окно терминала
curl -u admin:admin https://host/user/2 -X DELETE

Dead-man-switch: an external task (cron, script) periodically sends a “ping”; if a ping doesn’t arrive on time, Notifly sends an alert. More details — Heartbeat.

Public ping (authentication by ping token H… in the URL, without a client token):

Окно терминала
curl https://host/heartbeat/ping/HxxxxxxxxToken # GET — convenient from cron
curl -X POST https://host/heartbeat/ping/HxxxxxxxxToken \
-H "Content-Type: application/json" -d '{"fail_reason": "backup failed"}'

Management (client token):

Метод и путьОписание
GET /heartbeatList of heartbeats
POST /heartbeatCreate
PUT /heartbeat/{id}Update
DELETE /heartbeat/{id}Delete
POST /heartbeat/{id}/pause · /resumePause / resume
POST /heartbeat/{id}/test-alert · /test-recoveryTest alert / recovery notification

Active availability and content checks. Each type has its own page with details.

Метод и путьОписание
GET /monitor · POST /monitorList / create
POST /monitor/testTest configuration without saving
PUT /monitor/{id} · DELETE /monitor/{id}Update / delete
POST /monitor/{id}/pause · /resumePause / resume
Метод и путьОписание
GET /http-monitor · POST /http-monitorList / create
POST /http-monitor/testTest request
PUT /http-monitor/{id} · DELETE /http-monitor/{id}Update / delete
POST /http-monitor/{id}/pause · /resumePause / resume
Метод и путьОписание
GET /content-monitor · POST /content-monitorList / create
POST /content-monitor/suggest-selectorAI-assisted CSS selector suggestion
POST /content-monitor/test-ruleTest a rule
PUT /content-monitor/{id} · DELETE /content-monitor/{id}Update / delete
POST /content-monitor/{id}/pause · /resumePause / resume
Метод и путьОписание
GET /port-monitor · POST /port-monitorList / create
POST /port-monitor/testTest a port
PUT /port-monitor/{id} · DELETE /port-monitor/{id}Update / delete
POST /port-monitor/{id}/pause · /resumePause / resume
Метод и путьОписание
GET /port-scan · GET /port-scan/{id}List / single scan
POST /port-scanStart a scan
PATCH /port-scan/{id} · DELETE /port-scan/{id}Update / delete
POST /port-scan/{id}/cancel · /restartCancel / restart
POST /port-scan/{id}/to-monitorConvert a found port into a monitor
Метод и путьОписание
GET /workflow-monitor · POST /workflow-monitorList / create
POST /workflow-monitor/build-stepAI build step
POST /workflow-monitor/testRun a scenario
PUT /workflow-monitor/{id} · DELETE /workflow-monitor/{id}Update / delete
POST /workflow-monitor/{id}/pause · /resumePause / resume
Метод и путьОписание
GET /browser-workflow · POST /browser-workflowList / create
POST /browser-workflow/build-stepAI-assisted action suggestion
POST /browser-workflow/loginCapture authorization cookie
POST /browser-workflow/test-stepTest a step
PUT /browser-workflow/{id} · DELETE /browser-workflow/{id}Update / delete
POST /browser-workflow/{id}/pause · /resumePause / resume

Host ownership verification before scanning/monitoring.

Метод и путьОписание
GET /verified-hostList
POST /verified-host/start · /checkStart / check verification
DELETE /verified-host/{id}Delete

{kind} — monitor type (monitor, http-monitor, content-monitor, port-monitor, etc.).

Метод и путьОписание
GET /monitor-history/{kind}/{id}Uptime %, response time, aggregates
GET /monitor-history/{kind}/{id}/logDetailed log of individual checks

An incoming email to the inbox address is turned into a notification. More details — Email Inbox.

Метод и путьОписание
GET /email-inbox · POST /email-inboxList / create inbox
PUT /email-inbox/{id} · DELETE /email-inbox/{id}Update / delete
GET /email-inbox/{id}/rules · POST /email-inbox/{id}/rulesEmail processing rules
PUT /email-inbox/{id}/rules/{rid} · DELETE /email-inbox/{id}/rules/{rid}Update / delete rule
GET /email-inbox/eventIncoming email history
GET /email-inbox/event/{eid} · DELETE /email-inbox/event/{eid}Email / delete
POST /email-inbox/rule/from-event/{eid}AI suggestion for rule from an email

JS snippets for the website: error tracking (console_errors), events, etc. More details — Web script.

Public ingest (authentication by token in URL, sending from the browser):

Окно терминала
curl -X POST https://host/script/<token> \
-H "Content-Type: application/json" -d '{ ... }'

Management (client token):

Метод и путьОписание
GET /web-script · POST /web-scriptList / create
PUT /web-script/{id} · DELETE /web-script/{id}Update / delete
GET /web-script/{id}/sourcemaps · POST /web-script/{id}/sourcemapsSource maps
DELETE /web-script/{id}/sourcemaps/{smid}Delete source map
GET /web-script/{id}/issuesGrouped errors (issues)
POST /web-script/{id}/issues/{iid}/resolveMark issue as resolved
DELETE /web-script/{id}/issues/{iid}Delete issue

Accepts incoming webhooks and routes them to channels according to rules. It’s a per-user singleton with path-based routing. More details — Webhook router.

Public endpoint (authentication by token in URL, any path after the token):

Окно терминала
curl -X POST https://host/router/<token>/любой/путь \
-H "Content-Type: application/json" -d '{ ... }'

Management (client token):

Метод и путьОписание
GET /webhook-router · PUT /webhook-routerGet / update router
POST /webhook-router/rotate-tokenRotate public token
GET /webhook-router/rule · POST /webhook-router/ruleRouting rules
PUT /webhook-router/rule/{rid} · DELETE /webhook-router/rule/{rid}Update / delete rule
GET /webhook-router/event · GET /webhook-router/event/{eid}Event history
DELETE /webhook-router/event/{eid}Delete event
GET /webhook-router/message · DELETE /webhook-router/message/{mid}Routed messages
POST /webhook-router/rule/from-event/{eid}AI suggestion for rule from an event

Numeric time series with alerts. More details — Metrics.

Public metric ingest (authentication by token M… in URL):

Окно терминала
curl -X POST https://host/metric/<token> \
-H "Content-Type: application/json" -d '{ ... }'

Management (client token):

Метод и путьОписание
GET /metric-source · POST /metric-sourceMetric sources
PUT /metric-source/{id} · DELETE /metric-source/{id}Update / delete source
GET /metric-source/{id}/metricsSource metrics
PATCH /metric-source/{id}/metrics/{mid} · DELETE /metric-source/{id}/metrics/{mid}Update / delete metric
GET /metric-source/{id}/metrics/{mid}/seriesTime series of values
GET /metric-source/{id}/alerts · POST /metric-source/{id}/alertsMetric alerts
PUT /metric-source/{id}/alerts/{aid} · DELETE /metric-source/{id}/alerts/{aid}Update / delete alert

Granting other users access to a channel by email. More details — Channel access.

Метод и путьОписание
GET /application/{id}/share · POST /application/{id}/shareList / create a share on a channel
PUT /share/{id} · DELETE /share/{id}Update / revoke a share
GET /share/incomingShares granted to me
GET /share/recipientsAddresses I’ve already shared with (hints)
POST /share/{id}/accept · /declineAccept / decline a share
POST /share/joinJoin by token

Machine access tokens (M…) for integration via MCP. Generated from the admin UI.

Метод и путьОписание
GET /mcp/token · POST /mcp/tokenList / create token
PUT /mcp/token/{id} · DELETE /mcp/token/{id}Update / delete token

Interactive questions: the channel asks — the user answers from the interface. More details — Ask.

Sending a question uses an app token:

Метод и путьАутентификацияОписание
POST /askapp-токенAsk a question on behalf of a channel
GET /ask/pending-answersapp-токенFetch ready answers
POST /ask/ackapp-токенAcknowledge receipt of answers
GET /ask-question/{id}app-токенGet the answer to a specific question
POST /ask-question/{id}/answerclient-токенAnswer a question from the UI
DELETE /ask-question/{id}client-токенCancel a question
POST /message/{id}/answerclient-токенAnswer a question from a message

Chat co-pilot for onboarding and help. More details — Assistant.

Метод и путьОписание
GET /assistant/threadsList of threads
GET /assistant/threads/{id}/messagesThread message history
DELETE /assistant/threads/{id}Delete a thread
POST /assistant/chatSend a message to the assistant

There are two independent live update channels. More details — on the WebSocket page.

The main channel for delivering real-time push messages. Connect using a client token in the token query parameter:

Окно терминала
# Using wscat
wscat -c "wss://host/ws?token=CaQw5lL_L.yiRbN"
const ws = new WebSocket("wss://host/ws?token=CaQw5lL_L.yiRbN");
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(`[${msg.title}] ${msg.message} (приоритет: ${msg.priority})`);
};

Each incoming event is a JSON object Message:

{
"id": 124,
"appid": 1,
"message": "Новое сообщение",
"title": "Заголовок",
"priority": 5,
"extras": {},
"date": "2025-06-01T10:31:00Z"
}

A separate endpoint for Server-Sent Events (GET /stream, Content-Type: text/event-stream) for live UI updates. It’s a regular HTTP GET stream—use EventSource in the browser (authentication via cookie session or client token). The server sends named events (for example connected, channel:status_changed) and periodic keepalive comments.

const es = new EventSource("https://host/stream", { withCredentials: true });
es.addEventListener("connected", () => console.log("подключено"));
es.onmessage = (event) => console.log(event.data);

import requests
# Send a message
requests.post("https://host/message?token=AGdjfk_L.dKe8q", json={
"title": "Бэкап",
"message": "Резервное копирование завершено",
"priority": 2,
})
# Get all messages
resp = requests.get("https://host/message", auth=("admin", "admin"))
for msg in resp.json()["messages"]:
print(f"[{msg['title']}] {msg['message']}")
package main
import (
"net/http"
"net/url"
)
func main() {
http.PostForm("https://host/message?token=AGdjfk_L.dKe8q",
url.Values{
"title": {"Deploy"},
"message": {"Версия 2.0 развёрнута"},
})
}
// Send message
const resp = await fetch("https://host/message?token=AGdjfk_L.dKe8q", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
title: "CI",
message: "Тесты пройдены",
priority: 3,
}),
});
console.log(await resp.json());
Окно терминала
# Send message
Invoke-RestMethod -Uri "https://host/message?token=AGdjfk_L.dKe8q" `
-Method POST -Body @{
title = "Отчёт"
message = "Ежедневный отчёт сгенерирован"
priority = 1
}

КодЗначение
200Success
400Bad request (invalid parameters)
401Unauthorized (missing or invalid token)
403Forbidden (insufficient permissions)
404Resource not found