$ curl /api/openapi.json

riferimento api

Le 137 operazioni della REST API dell'hub, le stesse che usa l'interfaccia web. Ogni hub serve questo documento su /api/openapi.json e una Swagger UI interattiva su /api/docs, dove puoi provare le richieste con la tua sessione o un token. Scaricalo qui come openapi.json (OpenAPI 3.1, ultima versione su main) per generare un client. Le descrizioni degli endpoint vengono dal documento OpenAPI e sono in inglese.

──autenticazione

Crea un token in impostazioni → token api e mandalo come bearer token. I body sono JSON, gli orari sono millisecondi Unix, gli errori sono {"error": "..."}.

curl -H "Authorization: Bearer ptk_..." https://status.example.com/api/monitors
curl -X POST -H "Authorization: Bearer ptk_..." -H "Content-Type: application/json" \
-d '{"name":"Website","type":"http","target":"https://example.com"}' \
https://status.example.com/api/monitors

Ogni endpoint indica chi può chiamarlo:

  • pubblico: nessuna autenticazione
  • token di lettura: qualsiasi utente o token API, basta un token di lettura
  • token di scrittura · admin: un admin, con un token di scrittura o la sessione del browser; utenti in sola lettura e token di lettura ricevono 403
  • sessione del browser: solo sessione del browser, i token API ricevono 403
  • sessione admin: solo la sessione del browser di un admin

Gli utenti in sola lettura vedono le password nelle destinazioni dei monitor, negli header e nei canali di notifica come ********.

──monitors

Checks, their history and heartbeat (push) URLs.

get/api/monitorsList monitorstoken di lettura

Every monitor with its last 24 hours. Secrets (passwords in targets, headers, bodies, push tokens) are hidden from read-only users.

parametri
groupquery · stringGroup id, or none for monitors without a group.
tagquery · integerTag id.
risposta 200 · Monitors.
[
{
"name": null,
"type": null,
"target": null,
"interval_sec": null,
"timeout_ms": null,
"retries": null,
"method": null,
"expected_status": null,
"keyword": null,
"keyword_invert": null,
"dns_record": null,
"dns_server": null,
"dns_expected": null,
"ignore_tls": null,
"ip_family": null,
"headers": null,
"body": null,
"assertions": null,
"grace_sec": null,
"degraded_pct": null,
"locations": null,
"group_id": null,
"tag_ids": null,
"notifiers": null,
"cert_expiry_alert": null,
"domain_expiry_alert": null,
"paused": null,
"id": 1,
"push_token": "string",
"status": "up",
"status_since": 1761868800000,
"created_at": 1761868800000,
"uptime_24h": 12.5,
"avg_ms_24h": 12.5,
"last": {
"id": null,
"monitor_id": null,
"location": null,
"ts": null,
"ok": null,
"latency_ms": null,
"status_code": null,
"message": null,
"cert_expiry": null,
"maint": null,
"timing": null
},
"bars": [
{
"t": null,
"total": null,
"ok": null,
"degraded": null,
"maint": null,
"avg_ms": null
}
],
"expiry": [
{
"monitor_id": null,
"kind": null,
"subject": null,
"expires_at": null,
"issuer": null,
"source": null,
"error": null,
"checked_at": null
}
],
"maintenance": {
"id": 1,
"name": "string",
"end_at": 1761868800000
}
}
]
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired
post/api/monitorsCreate a monitortoken di scrittura · admin
body della richiesta · application/json
name*string
type*stringuno tra: http keyword tcp ping dns push postgres mysql redis mongodb docker grpc smtp mcp
targetstringWhat to check, depends on the type: an http(s) URL (http, keyword, mcp), host:port (tcp, IPv6 in brackets: [2001:db8::1]:443), a hostname or IP (ping, dns), a connection URL (postgres://, mysql://, redis://, mongodb://), a container name or id (docker), grpc[s]://host:port[/service], smtp[s]://host[:port]. Empty for push.
interval_secintegerSeconds between checks, 10 to 86400 (push: expected period, up to 7 days). 0 = default (60, push 3600).
timeout_msinteger500 to 60000. 0 = 10000.
retriesintegerConsecutive failures before a location counts as down, 1 to 10.
methodstringHTTP method for http/keyword (default GET). For mcp: the transport, auto, streamable or sse.
expected_statusstringAccepted HTTP status codes, e.g. "200-299" or "200,301". For mcp: the minimum number of tools.
keywordstringkeyword: text that must appear in the body. mcp: comma separated tool names that must be listed.
keyword_invertbooleankeyword: fail when the text is found.
dns_recordstringdns: record type (A, AAAA, CNAME, MX, TXT, NS...).
dns_serverstringdns: resolver to query, host[:port]. Empty = system resolver.
dns_expectedstringdns: value that must be in the answer.
ignore_tlsbooleanAccept invalid TLS certificates.
ip_familyinteger0 = instance default (GeneralSettings.ip_family), 1 = IPv4 or IPv6 (whichever connects first), 4 = IPv4 only, 6 = IPv6 only, 46 = IPv4 and IPv6 (both checked, the check fails when either fails). Locations without IPv6 check over IPv4 with 0 and 1; 6 and 46 are refused on them (see Location.ipv6). Ignored for push and docker.uno tra: 0 1 4 6 46
headersobjectRequest headers (http, keyword, mcp).
bodystringRequest body (http, keyword).
assertionsAssertion[]JSON response rules, http and keyword only, at most 20.
grace_secintegerpush: extra time after the period before the monitor goes down, 0 to 86400.
degraded_pctintegerShare of failing locations (percent) from which the monitor is degraded, 1 to 50. 0 = instance default.
locationsstring[]Where the check runs: "local" (the hub) and/or "agent:<id>". Empty = local. See GET /api/locations.
group_idintegerGroup, 0 = none.
tag_idsinteger[]
notifiersChannelLink[]Notification channels linked to this monitor one by one (notifier_id + events). Channels whose scope covers the monitor need no link. Left out on update: the links are kept; [] removes them.
cert_expiry_alertbooleanAlert before the TLS certificate expires (https targets).
domain_expiry_alertbooleanAlert before the domain registration expires.
pausedbooleanCreate the monitor paused. Ignored on update: use POST /api/monitors/{id}/pause.
esempio
{
"name": "Website",
"type": "http",
"target": "https://example.com",
"interval_sec": 60,
"timeout_ms": 10000,
"retries": 2,
"method": "GET",
"expected_status": "200-299",
"locations": [
"local"
],
"tag_ids": [],
"group_id": 0,
"assertions": [
{
"path": "status",
"op": "eq",
"value": "ok"
}
],
"cert_expiry_alert": true
}
risposta 201 · Created.
{
"name": "Website",
"type": "http",
"target": "https://example.com",
"interval_sec": 60,
"timeout_ms": 10000,
"retries": 2,
"method": "GET",
"expected_status": "200-299",
"locations": [
"local"
],
"tag_ids": [],
"group_id": 0,
"assertions": [
{
"path": "status",
"op": "eq",
"value": "ok"
}
],
"cert_expiry_alert": true,
"id": 7,
"headers": {},
"body": "",
"keyword": "",
"keyword_invert": false,
"dns_record": "",
"dns_server": "",
"dns_expected": "",
"ignore_tls": false,
"push_token": "",
"grace_sec": 0,
"degraded_pct": 0,
"ip_family": 0,
"domain_expiry_alert": false,
"paused": false,
"status": "up",
"status_since": 1761868800000,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/monitors/{id}Get a monitortoken di lettura

Includes 7 and 30 day uptime and the last result of each location.

parametri
id*path · integerId of the monitor.
risposta 200 · Monitor.
{
"id": null,
"push_token": null,
"status": null,
"status_since": null,
"created_at": null,
"uptime_24h": 12.5,
"avg_ms_24h": 12.5,
"last": null,
"bars": [
null
],
"expiry": [
null
],
"maintenance": {
"id": null,
"name": null,
"end_at": null
},
"uptime_7d": 12.5,
"uptime_30d": 12.5,
"location_status": [
{
"id": "string",
"name": "string",
"online": true,
"last": null
}
],
"push_url": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 404 not found
put/api/monitors/{id}Update a monitortoken di scrittura · admin

Replaces the monitor: send every field.

parametri
id*path · integerId of the monitor.
body della richiesta · application/json
name*string
type*stringuno tra: http keyword tcp ping dns push postgres mysql redis mongodb docker grpc smtp mcp
targetstringWhat to check, depends on the type: an http(s) URL (http, keyword, mcp), host:port (tcp, IPv6 in brackets: [2001:db8::1]:443), a hostname or IP (ping, dns), a connection URL (postgres://, mysql://, redis://, mongodb://), a container name or id (docker), grpc[s]://host:port[/service], smtp[s]://host[:port]. Empty for push.
interval_secintegerSeconds between checks, 10 to 86400 (push: expected period, up to 7 days). 0 = default (60, push 3600).
timeout_msinteger500 to 60000. 0 = 10000.
retriesintegerConsecutive failures before a location counts as down, 1 to 10.
methodstringHTTP method for http/keyword (default GET). For mcp: the transport, auto, streamable or sse.
expected_statusstringAccepted HTTP status codes, e.g. "200-299" or "200,301". For mcp: the minimum number of tools.
keywordstringkeyword: text that must appear in the body. mcp: comma separated tool names that must be listed.
keyword_invertbooleankeyword: fail when the text is found.
dns_recordstringdns: record type (A, AAAA, CNAME, MX, TXT, NS...).
dns_serverstringdns: resolver to query, host[:port]. Empty = system resolver.
dns_expectedstringdns: value that must be in the answer.
ignore_tlsbooleanAccept invalid TLS certificates.
ip_familyinteger0 = instance default (GeneralSettings.ip_family), 1 = IPv4 or IPv6 (whichever connects first), 4 = IPv4 only, 6 = IPv6 only, 46 = IPv4 and IPv6 (both checked, the check fails when either fails). Locations without IPv6 check over IPv4 with 0 and 1; 6 and 46 are refused on them (see Location.ipv6). Ignored for push and docker.uno tra: 0 1 4 6 46
headersobjectRequest headers (http, keyword, mcp).
bodystringRequest body (http, keyword).
assertionsAssertion[]JSON response rules, http and keyword only, at most 20.
grace_secintegerpush: extra time after the period before the monitor goes down, 0 to 86400.
degraded_pctintegerShare of failing locations (percent) from which the monitor is degraded, 1 to 50. 0 = instance default.
locationsstring[]Where the check runs: "local" (the hub) and/or "agent:<id>". Empty = local. See GET /api/locations.
group_idintegerGroup, 0 = none.
tag_idsinteger[]
notifiersChannelLink[]Notification channels linked to this monitor one by one (notifier_id + events). Channels whose scope covers the monitor need no link. Left out on update: the links are kept; [] removes them.
cert_expiry_alertbooleanAlert before the TLS certificate expires (https targets).
domain_expiry_alertbooleanAlert before the domain registration expires.
pausedbooleanCreate the monitor paused. Ignored on update: use POST /api/monitors/{id}/pause.
esempio
{
"name": "Website",
"type": "http",
"target": "https://example.com",
"interval_sec": 60,
"timeout_ms": 10000,
"retries": 2,
"method": "GET",
"expected_status": "200-299",
"locations": [
"local"
],
"tag_ids": [],
"group_id": 0,
"assertions": [
{
"path": "status",
"op": "eq",
"value": "ok"
}
],
"cert_expiry_alert": true
}
risposta 200 · Updated.
{
"name": "Website",
"type": "http",
"target": "https://example.com",
"interval_sec": 60,
"timeout_ms": 10000,
"retries": 2,
"method": "GET",
"expected_status": "200-299",
"locations": [
"local"
],
"tag_ids": [],
"group_id": 0,
"assertions": [
{
"path": "status",
"op": "eq",
"value": "ok"
}
],
"cert_expiry_alert": true,
"id": 7,
"headers": {},
"body": "",
"keyword": "",
"keyword_invert": false,
"dns_record": "",
"dns_server": "",
"dns_expected": "",
"ignore_tls": false,
"push_token": "",
"grace_sec": 0,
"degraded_pct": 0,
"ip_family": 0,
"domain_expiry_alert": false,
"paused": false,
"status": "up",
"status_since": 1761868800000,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/monitors/{id}Delete a monitortoken di scrittura · admin

Also deletes its history.

parametri
id*path · integerId of the monitor.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/monitors/{id}/expiryCheck expiry dates nowtoken di scrittura · admin

Looks up the TLS certificate and domain expiry.

parametri
id*path · integerId of the monitor.
risposta 200 · Expiry checks.
[
{
"monitor_id": 1,
"kind": "cert",
"subject": "string",
"expires_at": 1761868800000,
"issuer": "string",
"source": "tls",
"error": "string",
"checked_at": 1761868800000
}
]
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/monitors/{id}/pausePause or resumetoken di scrittura · admin

Pausing resolves the open incident.

parametri
id*path · integerId of the monitor.
body della richiesta · application/json
paused*boolean
esempio
{
"paused": true
}
risposta 200 · Monitor.
{
"name": "string",
"type": "http",
"target": "https://example.com/health",
"interval_sec": 1,
"timeout_ms": 1,
"retries": 1,
"method": "string",
"expected_status": "string",
"keyword": "string",
"keyword_invert": true,
"dns_record": "string",
"dns_server": "string",
"dns_expected": "string",
"ignore_tls": true,
"ip_family": 0,
"headers": {
"key": "string"
},
"body": "string",
"assertions": [
{
"path": null,
"op": null,
"value": null
}
],
"grace_sec": 1,
"degraded_pct": 1,
"locations": [
"local",
"agent:2"
],
"group_id": 1,
"tag_ids": [
1
],
"notifiers": [
{
"monitor_id": null,
"notifier_id": null,
"events": null
}
],
"cert_expiry_alert": true,
"domain_expiry_alert": true,
"paused": true,
"id": 1,
"push_token": "string",
"status": "up",
"status_since": 1761868800000,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/monitors/{id}/push-tokenRotate the heartbeat URLtoken di scrittura · admin

push monitors only: the old URL stops working.

parametri
id*path · integerId of the monitor.
risposta 200 · Monitor with the new push_token.
{
"name": "string",
"type": "http",
"target": "https://example.com/health",
"interval_sec": 1,
"timeout_ms": 1,
"retries": 1,
"method": "string",
"expected_status": "string",
"keyword": "string",
"keyword_invert": true,
"dns_record": "string",
"dns_server": "string",
"dns_expected": "string",
"ignore_tls": true,
"ip_family": 0,
"headers": {
"key": "string"
},
"body": "string",
"assertions": [
{
"path": null,
"op": null,
"value": null
}
],
"grace_sec": 1,
"degraded_pct": 1,
"locations": [
"local",
"agent:2"
],
"group_id": 1,
"tag_ids": [
1
],
"notifiers": [
{
"monitor_id": null,
"notifier_id": null,
"events": null
}
],
"cert_expiry_alert": true,
"domain_expiry_alert": true,
"paused": true,
"id": 1,
"push_token": "string",
"status": "up",
"status_since": 1761868800000,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
get/api/monitors/{id}/resultsLatest check resultstoken di lettura
parametri
id*path · integerId of the monitor.
limitquery · integerNumber of results.
beforequery · integerOnly results older than this time (unix ms), to load the next page.
fromquery · integerOnly results at or after this time (unix ms).
toquery · integerOnly results before this time (unix ms).
failedquery · booleanOnly failed checks.
risposta 200 · Results, newest first.
{
"results": [
{
"id": 1,
"monitor_id": 1,
"location": "string",
"ts": 1761868800000,
"ok": true,
"latency_ms": 12.5,
"status_code": 1,
"message": "string",
"cert_expiry": 1,
"maint": true,
"timing": {
"dns_ms": 12.5,
"connect_ms": 12.5,
"tls_ms": 12.5,
"ttfb_ms": 12.5,
"total_ms": 12.5,
"n": 1
}
}
],
"locations": {
"key": "string"
}
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired
get/api/monitors/{id}/seriesResponse time seriestoken di lettura

About 90 buckets per location over the range, or over a custom window with start and end. stats sums up the window and the one of the same length just before it.

parametri
id*path · integerId of the monitor.
rangequery · stringTime range.uno tra: 1h 6h 24h 7d 30d
startquery · integerCustom window start, unix ms. With end, replaces range; 5 minutes to 400 days long.
endquery · integerCustom window end, unix ms (capped at now).
risposta 200 · Series.
{
"from": 1761868800000,
"to": 1761868800000,
"size": 1,
"locations": [
{
"id": "string",
"name": "string"
}
],
"buckets": [
{
"t": 1761868800000,
"location": "string",
"total": 1,
"ok": 1,
"degraded": 1,
"maint": 1,
"avg_ms": 12.5,
"min_ms": 12.5,
"max_ms": 12.5,
"phases": {
"dns_ms": 12.5,
"connect_ms": 12.5,
"tls_ms": 12.5,
"ttfb_ms": 12.5,
"total_ms": 12.5,
"n": 1
}
}
],
"stats": {
"current": {
"from": 1,
"to": 1,
"uptime": 12.5,
"avg_ms": 12.5,
"percentiles": {
"n": 1,
"from": 1,
"p50": 12.5,
"p95": 12.5,
"p99": 12.5
}
},
"previous": {
"from": 1,
"to": 1,
"uptime": 12.5,
"avg_ms": 12.5,
"percentiles": {
"n": 1,
"from": 1,
"p50": 12.5,
"p95": 12.5,
"p99": 12.5
}
}
}
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired
post/api/monitors/{id}/testCheck nowtoken di scrittura · admin

Runs the saved monitor's check once at each of its locations and returns the results. They are not stored and do not change the status.

parametri
id*path · integerId of the monitor.
risposta 200 · One result per location of the monitor. Nothing is stored and no alert is sent.
{
"results": [
{
"location": "local",
"name": "hub",
"ok": true,
"latency_ms": 84.2,
"status_code": 200
},
{
"location": "agent:2",
"name": "fra · Frankfurt",
"ok": false,
"skipped": true,
"latency_ms": 0,
"message": "agent offline"
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/monitors/bulkChange several monitorstoken di scrittura · admin

Pauses, resumes, deletes or moves to a group several monitors at once. Pausing resolves their open incidents. With action group, group_id 0 removes the monitors from their group.

body della richiesta · application/json
ids*integer[]
action*stringuno tra: pause resume delete group
group_idintegerAction group only: the group, 0 for none.
esempio
{
"ids": [
1,
2,
3
],
"action": "pause"
}
risposta 200 · Number of monitors selected.
{
"count": 3
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/monitors/testTest an unsaved monitortoken di scrittura · admin

Runs the check once at each location of the monitor in the body and waits for the results (up to the timeout plus 5 seconds). Nothing is saved. Heartbeat (push) monitors cannot be tested.

body della richiesta · application/json
name*string
type*stringuno tra: http keyword tcp ping dns push postgres mysql redis mongodb docker grpc smtp mcp
targetstringWhat to check, depends on the type: an http(s) URL (http, keyword, mcp), host:port (tcp, IPv6 in brackets: [2001:db8::1]:443), a hostname or IP (ping, dns), a connection URL (postgres://, mysql://, redis://, mongodb://), a container name or id (docker), grpc[s]://host:port[/service], smtp[s]://host[:port]. Empty for push.
interval_secintegerSeconds between checks, 10 to 86400 (push: expected period, up to 7 days). 0 = default (60, push 3600).
timeout_msinteger500 to 60000. 0 = 10000.
retriesintegerConsecutive failures before a location counts as down, 1 to 10.
methodstringHTTP method for http/keyword (default GET). For mcp: the transport, auto, streamable or sse.
expected_statusstringAccepted HTTP status codes, e.g. "200-299" or "200,301". For mcp: the minimum number of tools.
keywordstringkeyword: text that must appear in the body. mcp: comma separated tool names that must be listed.
keyword_invertbooleankeyword: fail when the text is found.
dns_recordstringdns: record type (A, AAAA, CNAME, MX, TXT, NS...).
dns_serverstringdns: resolver to query, host[:port]. Empty = system resolver.
dns_expectedstringdns: value that must be in the answer.
ignore_tlsbooleanAccept invalid TLS certificates.
ip_familyinteger0 = instance default (GeneralSettings.ip_family), 1 = IPv4 or IPv6 (whichever connects first), 4 = IPv4 only, 6 = IPv6 only, 46 = IPv4 and IPv6 (both checked, the check fails when either fails). Locations without IPv6 check over IPv4 with 0 and 1; 6 and 46 are refused on them (see Location.ipv6). Ignored for push and docker.uno tra: 0 1 4 6 46
headersobjectRequest headers (http, keyword, mcp).
bodystringRequest body (http, keyword).
assertionsAssertion[]JSON response rules, http and keyword only, at most 20.
grace_secintegerpush: extra time after the period before the monitor goes down, 0 to 86400.
degraded_pctintegerShare of failing locations (percent) from which the monitor is degraded, 1 to 50. 0 = instance default.
locationsstring[]Where the check runs: "local" (the hub) and/or "agent:<id>". Empty = local. See GET /api/locations.
group_idintegerGroup, 0 = none.
tag_idsinteger[]
notifiersChannelLink[]Notification channels linked to this monitor one by one (notifier_id + events). Channels whose scope covers the monitor need no link. Left out on update: the links are kept; [] removes them.
cert_expiry_alertbooleanAlert before the TLS certificate expires (https targets).
domain_expiry_alertbooleanAlert before the domain registration expires.
pausedbooleanCreate the monitor paused. Ignored on update: use POST /api/monitors/{id}/pause.
esempio
{
"type": "http",
"target": "https://example.com/health",
"timeout_ms": 10000,
"locations": [
"local"
]
}
risposta 200 · One result per location of the monitor. Nothing is stored and no alert is sent.
{
"results": [
{
"location": "local",
"name": "hub",
"ok": true,
"latency_ms": 84.2,
"status_code": 200
},
{
"location": "agent:2",
"name": "fra · Frankfurt",
"ok": false,
"skipped": true,
"latency_ms": 0,
"message": "agent offline"
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/push/{token}Send a heartbeatpubblico

Heartbeat of a push monitor. Any HTTP method works (GET and POST shown here). The token in the URL is the authentication. curl -fsS https://status.example.com/api/push/<token>?status=up&msg=ok&ping=12

parametri
token*path · string
statusquery · stringResult of the job.uno tra: up down ok fail 0 1
msgquery · stringMessage shown in the history, up to 200 characters.
pingquery · numberDuration or latency in ms.
risposta 200 · Recorded.
{
"ok": true
}
errori: 400 invalid input · 404 not found
post/api/push/{token}Send a heartbeatpubblico

Heartbeat of a push monitor. Any HTTP method works (GET and POST shown here). The token in the URL is the authentication. curl -fsS https://status.example.com/api/push/<token>?status=up&msg=ok&ping=12

parametri
token*path · string
statusquery · stringResult of the job.uno tra: up down ok fail 0 1
msgquery · stringMessage shown in the history, up to 200 characters.
pingquery · numberDuration or latency in ms.
risposta 200 · Recorded.
{
"ok": true
}
errori: 400 invalid input · 404 not found

──incidents

Down periods of monitors.

get/api/incidentsList incidentstoken di lettura

The latest 100, open ones first.

parametri
monitorquery · integerOnly this monitor.
statequery · stringOnly open or only resolved incidents.uno tra: open resolved
sincequery · integerOnly incidents open at some point after this time (unix ms).
limitquery · integerMaximum number of incidents.
risposta 200 · Incidents.
[
{
"id": 1,
"monitor_id": 1,
"monitor_name": "string",
"started_at": 1761868800000,
"resolved_at": 1,
"cause": "string"
}
]
errori: 401 not logged in, or the token is invalid or expired

──maintenance

Windows during which monitors don't alert.

get/api/maintenancesList maintenance windowstoken di lettura
risposta 200 · Windows.
[
{
"name": "string",
"description": "string",
"all_monitors": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"tag_ids": [
1
],
"kind": "once",
"start_at": 1,
"end_at": 1,
"start_time": "02:00",
"duration_min": 1,
"weekdays": [
1
],
"month_days": [
1
],
"timezone": "Europe/Rome",
"enabled": true,
"id": 1,
"created_at": 1761868800000,
"active": true,
"active_end": 1761868800000,
"next_start": 1,
"next_end": 1761868800000
}
]
errori: 401 not logged in, or the token is invalid or expired
post/api/maintenancesCreate a maintenance windowtoken di scrittura · admin

Covered monitors don't alert and don't count as down.

body della richiesta · application/json
name*string
descriptionstring
all_monitorsbooleanCovers every monitor.
monitor_idsinteger[]
group_idsinteger[]Every monitor of these groups.
tag_idsinteger[]Every monitor with one of these tags.
kind*stringuno tra: once daily weekly monthly
start_atintegeronce: start. Recurring: first day the schedule is valid (0 = now).
end_atintegeronce: end. Recurring: last day the schedule is valid (0 = forever).
start_timestringRecurring: local start time, HH:MM.
duration_minintegerRecurring: length in minutes, up to 7 days.
weekdaysinteger[]weekly: 0 = Sunday … 6 = Saturday.
month_daysinteger[]monthly: 1 … 31.
timezonestringIANA time zone, default UTC.
enabledboolean
esempio
{
"name": "DB upgrade",
"description": "",
"all_monitors": false,
"monitor_ids": [
7
],
"group_ids": [],
"tag_ids": [],
"kind": "weekly",
"start_time": "02:00",
"duration_min": 60,
"weekdays": [
0
],
"month_days": [],
"timezone": "Europe/Rome",
"enabled": true
}
risposta 201 · Created.
{
"name": "string",
"description": "string",
"all_monitors": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"tag_ids": [
1
],
"kind": "once",
"start_at": 1,
"end_at": 1,
"start_time": "02:00",
"duration_min": 1,
"weekdays": [
1
],
"month_days": [
1
],
"timezone": "Europe/Rome",
"enabled": true,
"id": 1,
"created_at": 1761868800000,
"active": true,
"active_end": 1761868800000,
"next_start": 1,
"next_end": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/maintenances/{id}Update a maintenance windowtoken di scrittura · admin
parametri
id*path · integerId of the maintenance window.
body della richiesta · application/json
name*string
descriptionstring
all_monitorsbooleanCovers every monitor.
monitor_idsinteger[]
group_idsinteger[]Every monitor of these groups.
tag_idsinteger[]Every monitor with one of these tags.
kind*stringuno tra: once daily weekly monthly
start_atintegeronce: start. Recurring: first day the schedule is valid (0 = now).
end_atintegeronce: end. Recurring: last day the schedule is valid (0 = forever).
start_timestringRecurring: local start time, HH:MM.
duration_minintegerRecurring: length in minutes, up to 7 days.
weekdaysinteger[]weekly: 0 = Sunday … 6 = Saturday.
month_daysinteger[]monthly: 1 … 31.
timezonestringIANA time zone, default UTC.
enabledboolean
esempio
{
"name": "DB upgrade",
"description": "",
"all_monitors": false,
"monitor_ids": [
7
],
"group_ids": [],
"tag_ids": [],
"kind": "weekly",
"start_time": "02:00",
"duration_min": 60,
"weekdays": [
0
],
"month_days": [],
"timezone": "Europe/Rome",
"enabled": true
}
risposta 200 · Updated.
{
"name": "string",
"description": "string",
"all_monitors": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"tag_ids": [
1
],
"kind": "once",
"start_at": 1,
"end_at": 1,
"start_time": "02:00",
"duration_min": 1,
"weekdays": [
1
],
"month_days": [
1
],
"timezone": "Europe/Rome",
"enabled": true,
"id": 1,
"created_at": 1761868800000,
"active": true,
"active_end": 1761868800000,
"next_start": 1,
"next_end": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/maintenances/{id}Delete a maintenance windowtoken di scrittura · admin
parametri
id*path · integerId of the maintenance window.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication

──groups and tags

Organize monitors; status pages and maintenance windows can select them by group or tag.

get/api/groupsList groupstoken di lettura
risposta 200 · Groups.
[
{
"id": 1,
"name": "string",
"description": "string",
"monitors": 1,
"created_at": 1761868800000
}
]
errori: 401 not logged in, or the token is invalid or expired
post/api/groupsCreate a grouptoken di scrittura · admin
body della richiesta · application/json
idinteger
name*stringUnique, up to 64 characters.
descriptionstringUp to 500 characters.
monitorsintegerNumber of monitors in the group (read only).
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"name": "Production",
"description": "Customer facing"
}
risposta 201 · Created.
{
"id": 1,
"name": "string",
"description": "string",
"monitors": 1,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
put/api/groups/{id}Update a grouptoken di scrittura · admin
parametri
id*path · integerId of the group.
body della richiesta · application/json
idinteger
name*stringUnique, up to 64 characters.
descriptionstringUp to 500 characters.
monitorsintegerNumber of monitors in the group (read only).
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"id": 1,
"name": "string",
"description": "string",
"monitors": 1,
"created_at": 1761868800000
}
risposta 200 · Updated.
{
"id": 1,
"name": "string",
"description": "string",
"monitors": 1,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found · 409 already exists
delete/api/groups/{id}Delete a grouptoken di scrittura · admin

Its monitors are kept, without a group.

parametri
id*path · integerId of the group.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/groups/{id}/monitorsSet the monitors of a grouptoken di scrittura · admin

Monitors listed here move to this group; monitors of the group not listed leave it.

parametri
id*path · integerId of the group.
body della richiesta · application/json
monitor_ids*integer[]
esempio
{
"monitor_ids": [
7,
8
]
}
risposta 200 · Group.
{
"id": 1,
"name": "string",
"description": "string",
"monitors": 1,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
get/api/tagsList tagstoken di lettura
risposta 200 · Tags.
[
{
"id": 1,
"name": "string",
"color": "red",
"monitors": 1,
"created_at": 1761868800000
}
]
errori: 401 not logged in, or the token is invalid or expired
post/api/tagsCreate a tagtoken di scrittura · admin
body della richiesta · application/json
idinteger
name*stringUnique, up to 32 characters, no commas.
colorstringuno tra: "" red orange yellow green cyan blue purple pink gray
monitorsintegerNumber of tagged monitors (read only).
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"name": "critical",
"color": "red"
}
risposta 201 · Created.
{
"id": 1,
"name": "string",
"color": "red",
"monitors": 1,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
put/api/tags/{id}Update a tagtoken di scrittura · admin
parametri
id*path · integerId of the tag.
body della richiesta · application/json
idinteger
name*stringUnique, up to 32 characters, no commas.
colorstringuno tra: "" red orange yellow green cyan blue purple pink gray
monitorsintegerNumber of tagged monitors (read only).
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"id": 1,
"name": "string",
"color": "red",
"monitors": 1,
"created_at": 1761868800000
}
risposta 200 · Updated.
{
"id": 1,
"name": "string",
"color": "red",
"monitors": 1,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found · 409 already exists
delete/api/tags/{id}Delete a tagtoken di scrittura · admin
parametri
id*path · integerId of the tag.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication

──agents

Remote check locations connected to the hub.

get/api/agentsList agentstoken di lettura
risposta 200 · Agents.
{
"agents": [
{
"id": 1,
"name": "string",
"location": "string",
"version": "string",
"hostname": "string",
"platform": "string",
"remote_addr": "string",
"last_seen": 1761868800000,
"created_at": 1761868800000,
"ipv6": 0,
"location_id": "agent:2",
"online": true,
"monitors": 1,
"update_available": true,
"self_update": true,
"no_update_reason": "string",
"update_state": "updating",
"update_error": "string"
}
],
"hub_url": "string",
"hub_version": "string",
"auto_update": true
}
errori: 401 not logged in, or the token is invalid or expired
post/api/agentsCreate an agenttoken di scrittura · admin

The agent token is returned once.

body della richiesta · application/json
name*string
locationstring
esempio
{
"name": "fra-1",
"location": "Frankfurt"
}
risposta 201 · Created.
{
"agent": {
"id": 1,
"name": "string",
"location": "string",
"version": "string",
"hostname": "string",
"platform": "string",
"remote_addr": "string",
"last_seen": 1761868800000,
"created_at": 1761868800000,
"ipv6": 0,
"location_id": "agent:2",
"online": true,
"monitors": 1,
"update_available": true,
"self_update": true,
"no_update_reason": "string",
"update_state": "updating",
"update_error": "string"
},
"token": "string",
"hub_url": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/agents/{id}Rename an agenttoken di scrittura · admin
parametri
id*path · integerId of the agent.
body della richiesta · application/json
name*string
locationstring
esempio
{
"name": "string",
"location": "string"
}
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
delete/api/agents/{id}Delete an agenttoken di scrittura · admin

Disconnects it and removes it from monitor locations.

parametri
id*path · integerId of the agent.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/agents/{id}/monitorsPreview compatible monitorstoken di lettura

Monitors this agent can be added to, and the ones skipped with the reason. Heartbeat monitors have no locations and are left out.

parametri
id*path · integerId of the agent.
risposta 200 · Compatible and skipped monitors.
{
"compatible": [
{
"id": 1,
"name": "string",
"type": "string",
"target": "string",
"reason": "no_ipv6"
}
],
"skipped": [
{
"id": 1,
"name": "string",
"type": "string",
"target": "string",
"reason": "no_ipv6"
}
],
"already": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 404 not found
post/api/agents/{id}/monitorsAdd the agent to monitorstoken di scrittura · admin

Adds the agent's location to the given monitors. Monitors that are not compatible are skipped and returned with the reason.

parametri
id*path · integerId of the agent.
body della richiesta · application/json
monitor_ids*integer[]
esempio
{
"monitor_ids": [
1,
4,
7
]
}
risposta 200 · Done.
{
"added": 1,
"skipped": [
{
"id": 1,
"name": "string",
"type": "string",
"target": "string",
"reason": "no_ipv6"
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/agents/{id}/tokenRotate the agent tokentoken di scrittura · admin

The agent is disconnected until it uses the new token.

parametri
id*path · integerId of the agent.
risposta 200 · New token.
{
"token": "string",
"hub_url": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/agents/{id}/updateUpdate an agent nowtoken di scrittura · admin

Asks a connected agent to install the hub's version.

parametri
id*path · integerId of the agent.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
get/api/locationsList check locationstoken di lettura

The hub (when it runs checks) and every agent.

risposta 200 · Locations.
[
{
"id": "local",
"name": "hub",
"online": true,
"kind": "local",
"ipv6": 2
},
{
"id": "agent:2",
"name": "fra-1 · Frankfurt",
"online": true,
"kind": "agent",
"ipv6": 1
}
]
errori: 401 not logged in, or the token is invalid or expired
put/api/settings/agent-updatesAgent auto-update settingtoken di scrittura · admin
body della richiesta · application/json
auto_update*boolean
esempio
{
"auto_update": true
}
risposta 200 · Saved.
{
"auto_update": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication

──notifications

Alert channels: webhook, Discord, Slack, Telegram, ntfy, email.

get/api/mobile/configPush config for the mobile apptoken di lettura

Where the app enrolls its phone: it sends hub_id and its FCM token to {relay_url}/v1/devices and gives the handle it gets to POST /api/mobile/devices. live_activity is true when the hub also pushes Live Activity updates (PUT /api/mobile/live-activity/...). enabled is false (and the other fields empty) when push is off.

risposta 200 · Config.
{
"enabled": true,
"relay_url": "https://push.pingtxt.com",
"hub_id": "PrBlwRm8tbClvg8f5PEy4w",
"live_activity": true
}
errori: 401 not logged in, or the token is invalid or expired
get/api/mobile/devicesList my phonestoken di lettura
risposta 200 · Phones of the current user.
[
{
"id": 1,
"name": "string",
"created_at": 1761868800000,
"last_seen_at": 1761868800000
}
]
errori: 401 not logged in, or the token is invalid or expired
post/api/mobile/devicesRegister my phonetoken di lettura

Stores the device handle (prd_...) from the push relay for the app's sign-in. Only OAuth access tokens (pma_...) can call it; each sign-in keeps one handle, a new one replaces it. Revoking the sign-in removes the phone.

body della richiesta · application/json
device*string
namestring
esempio
{
"device": "prd_AeYWsf5y...",
"name": "Federico's iPhone"
}
risposta 200 · Saved.
{
"id": 3
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
delete/api/mobile/devices/{id}Remove my phonetoken di lettura

The phone stops getting notifications from this hub.

parametri
id*path · integerId of the phone.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 404 not found
put/api/mobile/live-activity/start-tokenSet my Live Activity push-to-start tokentoken di lettura

Stores the ActivityKit push-to-start token of the app (iOS 17.2+, Activity<OutageActivityAttributes>.pushToStartTokenUpdates) and the hub URL the app signed in with. When a monitor goes down and this phone has no activity running, the hub starts one through the push relay with attributes {"hub": hub_url}. Send it again whenever iOS gives a new one.

body della richiesta · application/json
token*string
hub_url*string
esempio
{
"token": "80f4c3...",
"hub_url": "https://status.example.com"
}
risposta 200 · Saved.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
delete/api/mobile/live-activity/start-tokenRemove my Live Activity push-to-start tokentoken di lettura

The hub no longer starts the activity on this phone (for example, Live Activities turned off in the app).

risposta 200 · Saved.
{
"ok": true
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
put/api/mobile/live-activity/tokenSet the token of my running Live Activitytoken di lettura

Stores the push token of the activity running on this phone (activity.pushTokenUpdates). The hub sends it update and end pushes when incidents open or close, and refreshes it every 15 minutes while incidents stay open. Send it again when it rotates.

body della richiesta · application/json
token*string
esempio
{
"token": "6a0d1e..."
}
risposta 200 · Saved.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
delete/api/mobile/live-activity/tokenRemove the token of my Live Activitytoken di lettura

Call it when the activity ends on the phone (ended by the app or dismissed by the user).

risposta 200 · Saved.
{
"ok": true
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
get/api/notifiersList notification channelstoken di lettura
risposta 200 · Channels.
[
{
"id": 1,
"name": "string",
"type": "webhook",
"config": {
"key": "string"
},
"enabled": true,
"delay_min": 1,
"repeat_min": 1,
"all_monitors": true,
"group_ids": [
1
],
"tag_ids": [
1
],
"events": [
"down"
],
"monitors": [
{
"monitor_id": 1,
"notifier_id": 1,
"events": [
null
]
}
],
"created_at": 1761868800000
}
]
errori: 401 not logged in, or the token is invalid or expired
post/api/notifiersCreate a notification channeltoken di scrittura · admin
body della richiesta · application/json
idinteger
name*string
type*stringuno tra: webhook discord slack telegram ntfy email app
config*objectwebhook, discord, slack, ntfy: {url}. telegram: {bot_token, chat_id}. email: {host, port, security (starttls|tls|none), username, password, from, to}. app: {users}, emails of the users whose phones get the alerts, comma separated (empty = every user). The email password is write-only: responses carry password_set="true" instead, and an empty password on update keeps the stored one. Read-only users see secrets as ********.
enabledboolean
delay_minintegerMinutes a monitor must stay down before this channel gets its first alert (0 = right away). Use it for an escalation contact: shorter outages never reach it, and it gets the recovery message only if it was alerted.
repeat_minintegerRepeat the alert every this many minutes while the monitor stays down (0 = once, otherwise at least 5). Reminders carry reminder=1, 2, ... and down_since in the webhook payload. Nothing is sent during maintenance windows.
all_monitorsbooleanThe channel covers every monitor, also the ones added later. Default true when left out on create.
group_idsinteger[]Without all_monitors: the channel covers the monitors of these groups.
tag_idsinteger[]Without all_monitors: the channel covers the monitors with one of these tags.
events"down" | "up" | "degraded" | "cert_expiry" | "domain_expiry"[]What the channel gets for the monitors it covers. Default on create: down, up, cert_expiry, domain_expiry. down = the monitor went down (and the reminders of repeat_min), up = it is back up (only to channels that got the down alert), degraded = some locations fail and when that ends, cert_expiry / domain_expiry = the TLS certificate or the domain registration expires soon, expired or was renewed.
monitorsChannelLink[]Monitors linked one by one (monitor_id + events), the same links as the monitors' notifiers. Left out on update: kept; [] removes them.
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"name": "ops",
"type": "slack",
"config": {
"url": "https://hooks.slack.com/services/T000/B000/XXXX"
},
"enabled": true
}
risposta 201 · Created.
{
"id": 1,
"name": "string",
"type": "webhook",
"config": {
"key": "string"
},
"enabled": true,
"delay_min": 1,
"repeat_min": 1,
"all_monitors": true,
"group_ids": [
1
],
"tag_ids": [
1
],
"events": [
"down"
],
"monitors": [
{
"monitor_id": 1,
"notifier_id": 1,
"events": [
"down"
]
}
],
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
put/api/notifiers/{id}Update a notification channeltoken di scrittura · admin
parametri
id*path · integerId of the channel.
body della richiesta · application/json
idinteger
name*string
type*stringuno tra: webhook discord slack telegram ntfy email app
config*objectwebhook, discord, slack, ntfy: {url}. telegram: {bot_token, chat_id}. email: {host, port, security (starttls|tls|none), username, password, from, to}. app: {users}, emails of the users whose phones get the alerts, comma separated (empty = every user). The email password is write-only: responses carry password_set="true" instead, and an empty password on update keeps the stored one. Read-only users see secrets as ********.
enabledboolean
delay_minintegerMinutes a monitor must stay down before this channel gets its first alert (0 = right away). Use it for an escalation contact: shorter outages never reach it, and it gets the recovery message only if it was alerted.
repeat_minintegerRepeat the alert every this many minutes while the monitor stays down (0 = once, otherwise at least 5). Reminders carry reminder=1, 2, ... and down_since in the webhook payload. Nothing is sent during maintenance windows.
all_monitorsbooleanThe channel covers every monitor, also the ones added later. Default true when left out on create.
group_idsinteger[]Without all_monitors: the channel covers the monitors of these groups.
tag_idsinteger[]Without all_monitors: the channel covers the monitors with one of these tags.
events"down" | "up" | "degraded" | "cert_expiry" | "domain_expiry"[]What the channel gets for the monitors it covers. Default on create: down, up, cert_expiry, domain_expiry. down = the monitor went down (and the reminders of repeat_min), up = it is back up (only to channels that got the down alert), degraded = some locations fail and when that ends, cert_expiry / domain_expiry = the TLS certificate or the domain registration expires soon, expired or was renewed.
monitorsChannelLink[]Monitors linked one by one (monitor_id + events), the same links as the monitors' notifiers. Left out on update: kept; [] removes them.
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"name": "ops",
"type": "slack",
"config": {
"url": "https://hooks.slack.com/services/T000/B000/XXXX"
},
"enabled": true
}
risposta 200 · Updated.
{
"id": 1,
"name": "string",
"type": "webhook",
"config": {
"key": "string"
},
"enabled": true,
"delay_min": 1,
"repeat_min": 1,
"all_monitors": true,
"group_ids": [
1
],
"tag_ids": [
1
],
"events": [
"down"
],
"monitors": [
{
"monitor_id": 1,
"notifier_id": 1,
"events": [
"down"
]
}
],
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
delete/api/notifiers/{id}Delete a notification channeltoken di scrittura · admin
parametri
id*path · integerId of the channel.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/notifiers/{id}/testTest a channeltoken di scrittura · admin
parametri
id*path · integerId of the channel.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found · 409 already exists · 502 the notification could not be delivered
post/api/notifiers/testTest an unsaved channeltoken di scrittura · admin

Sends a test alert with this configuration. With an id, empty secrets are taken from that saved channel.

body della richiesta · application/json
idinteger
name*string
type*stringuno tra: webhook discord slack telegram ntfy email app
config*objectwebhook, discord, slack, ntfy: {url}. telegram: {bot_token, chat_id}. email: {host, port, security (starttls|tls|none), username, password, from, to}. app: {users}, emails of the users whose phones get the alerts, comma separated (empty = every user). The email password is write-only: responses carry password_set="true" instead, and an empty password on update keeps the stored one. Read-only users see secrets as ********.
enabledboolean
delay_minintegerMinutes a monitor must stay down before this channel gets its first alert (0 = right away). Use it for an escalation contact: shorter outages never reach it, and it gets the recovery message only if it was alerted.
repeat_minintegerRepeat the alert every this many minutes while the monitor stays down (0 = once, otherwise at least 5). Reminders carry reminder=1, 2, ... and down_since in the webhook payload. Nothing is sent during maintenance windows.
all_monitorsbooleanThe channel covers every monitor, also the ones added later. Default true when left out on create.
group_idsinteger[]Without all_monitors: the channel covers the monitors of these groups.
tag_idsinteger[]Without all_monitors: the channel covers the monitors with one of these tags.
events"down" | "up" | "degraded" | "cert_expiry" | "domain_expiry"[]What the channel gets for the monitors it covers. Default on create: down, up, cert_expiry, domain_expiry. down = the monitor went down (and the reminders of repeat_min), up = it is back up (only to channels that got the down alert), degraded = some locations fail and when that ends, cert_expiry / domain_expiry = the TLS certificate or the domain registration expires soon, expired or was renewed.
monitorsChannelLink[]Monitors linked one by one (monitor_id + events), the same links as the monitors' notifiers. Left out on update: kept; [] removes them.
created_atintegerUnix time in milliseconds (0 = never / unknown).
esempio
{
"name": "ops",
"type": "slack",
"config": {
"url": "https://hooks.slack.com/services/T000/B000/XXXX"
},
"enabled": true
}
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists · 502 the notification could not be delivered

──reports

Periodic email reports: uptime and incidents of the last week or month, per monitor group.

get/api/reportsGet report settingstoken di lettura

Report settings, when the next reports go out and the last ones sent.

risposta 200 · Settings.
{
"weekly": true,
"monthly": true,
"hour": 1,
"timezone": "Europe/Rome",
"notifier_ids": [
1
],
"group_ids": [
1
],
"next": {
"key": 1
},
"last": {
"key": {
"from": 1,
"sent_at": 1
}
}
}
errori: 401 not logged in, or the token is invalid or expired
put/api/reportsSave report settingstoken di scrittura · admin

Turns the weekly and monthly reports on or off and picks the email channels, the groups, the hour and the time zone. A report that is turned on starts with the next period.

body della richiesta · application/json
weeklybooleanSend a report every Monday for the week before.
monthlybooleanSend a report on the 1st for the month before.
hourintegerHour of the day the reports are sent, in timezone.
timezonestringIANA time zone of the periods and of the times in the report.
notifier_idsinteger[]Email channels that receive the reports. Disabled channels are skipped.
group_idsinteger[]Only these monitor groups. Empty: every monitor.
esempio
{
"weekly": true,
"monthly": true,
"hour": 8,
"timezone": "Europe/Rome",
"notifier_ids": [
3
],
"group_ids": []
}
risposta 200 · Saved.
{
"weekly": true,
"monthly": true,
"hour": 1,
"timezone": "Europe/Rome",
"notifier_ids": [
1
],
"group_ids": [
1
],
"next": {
"key": 1
},
"last": {
"key": {
"from": 1,
"sent_at": 1
}
}
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/reports/previewPreview a reporttoken di lettura

The report of the last complete week (Monday to Sunday) or month, with the saved settings, as it would be sent now. text is the plain text body of the email.

parametri
kindquery · stringWhich report.uno tra: weekly monthly
risposta 200 · Report.
{
"kind": "weekly",
"from": 1,
"to": 1,
"timezone": "string",
"uptime": 12.5,
"prev_uptime": 12.5,
"incidents": 1,
"downtime_ms": 1,
"monitors": 1,
"groups": [
{
"id": 1,
"name": "string",
"uptime": 12.5,
"prev_uptime": 12.5,
"incidents": 1,
"downtime_ms": 1,
"monitors": [
null
],
"incident_list": [
null
]
}
],
"subject": "string",
"text": "string",
"url": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired
post/api/reports/sendSend a report nowtoken di scrittura · admin

Emails the report of the last complete period to the saved channels now. The schedule does not change.

body della richiesta · application/json
kindstringuno tra: weekly monthly
esempio
{
"kind": "monthly"
}
risposta 200 · Sent to at least one channel.
{
"ok": true,
"sent": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 502 the notification could not be delivered

──status pages

Public pages and their data.

get/api/badge/{slug}/{kind}Status page badgepubblico

SVG badge with the overall state of a status page (operational, degraded, partial outage, major outage), to embed in a README: ``markdown ![status](https://pingtxt.example.com/api/badge/acme/status.svg)

parametri
slug*path · stringSlug of a published status page.
kind*path · stringstatus, optionally with .svg.uno tra: status status.svg
labelquery · stringReplaces the left text (up to 60 characters).
stylequery · stringflat (default) or flat-square.uno tra: flat flat-square
risposta 200 · SVG badge.
errori: 404 not found badge
get/api/badge/{slug}/{monitor}/{kind}Monitor badgepubblico

SVG badge of one monitor shown on a published status page: its state (status), its uptime (uptime) or its average response time (response) over period. The label defaults to the monitor name, uptime 30d or response 24h. ``markdown ![uptime](https://pingtxt.example.com/api/badge/acme/12/uptime.svg?period=7d)

parametri
slug*path · stringSlug of a published status page.
monitor*path · integerMonitor id.
kind*path · stringstatus, uptime or response, optionally with .svg.uno tra: status uptime response status.svg uptime.svg response.svg
periodquery · stringWindow for uptime (default 30d) and response (default 24h).uno tra: 24h 7d 30d 90d
labelquery · stringReplaces the left text (up to 60 characters).
stylequery · stringflat (default) or flat-square.uno tra: flat flat-square
risposta 200 · SVG badge.
errori: 400 bad period badge · 404 not found badge
get/api/public/status/{slug}Public status page datapubblico

What /status/<slug> shows. Drafts answer 404 unless a user is logged in. Cached for 15 seconds. Published pages without a password answer with Access-Control-Allow-Origin: *, so any website can read them from the browser (for example to show a status dot).

parametri
slug*path · string
risposta 200 · Page.
{
"slug": "string",
"title": "string",
"description": "string",
"header_url": "string",
"logo": {
"svg": true,
"width": 1,
"height": 1,
"v": 1
},
"hide_title": true,
"published": true,
"status": "operational",
"days": 1,
"monitors": [
{
"id": 1,
"name": "string",
"group": "string",
"status": "string",
"uptime": 12.5,
"uptime_24h": 12.5,
"bars": [
{
"t": null,
"total": null,
"ok": null,
"degraded": null,
"maint": null,
"avg_ms": null
}
]
}
],
"show_incidents": true,
"incidents": [
{
"id": 1,
"monitor_name": "string",
"started_at": 1761868800000,
"resolved_at": 1761868800000
}
],
"updated_at": 1761868800000,
"reports": [
{
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
null
]
}
],
"subscribe": true
}
errori: 403 the page needs a password: unlock it with `post /api/public/status/{slug}/unlock` · 404 not found
post/api/public/status/{slug}/subscribeSubscribe to a status page by emailpubblico

Sends a confirmation link to the address; nothing else is sent until it is confirmed. The answer is the same for new, waiting and already confirmed addresses. On a custom domain the path is /api/public/status/subscribe. Limited to 10 requests per client address and 3 per email address every 15 minutes.

parametri
slug*path · string
body della richiesta · application/json
email*string
esempio
{
"email": "jane@example.com"
}
risposta 202 · Confirmation email queued (or already subscribed).
{
"ok": true
}
errori: 400 invalid input · 404 not found · 409 already exists · 429 too many failed attempts. password logins are limited to 10 failures per account and 30 per client address in 15 minutes; second factor codes to 10 wrong codes per user. wait for `retry-after` seconds
post/api/public/status/{slug}/unlockUnlock a password protected status pagepubblico

Checks the page password and sets a cookie that opens the page, its badges and its subscription form for 30 days. Changing or removing the password closes the page again for every visitor. On a custom domain the path is /api/public/status/unlock. Limited to 10 wrong passwords per client address and 100 per page every 15 minutes.

parametri
slug*path · string
body della richiesta · application/json
password*string
esempio
{
"password": "string"
}
risposta 200 · Unlocked (or the page has no password); the cookie is set.
{
"ok": true
}
errori: 400 invalid input · 403 wrong password · 404 not found · 429 too many failed attempts. password logins are limited to 10 failures per account and 30 per client address in 15 minutes; second factor codes to 10 wrong codes per user. wait for `retry-after` seconds
post/api/public/subscriptions/{token}/confirmConfirm an email subscriptionpubblico

Called by the status page when a visitor opens the link of the confirmation email. Links expire after 7 days.

parametri
token*path · stringToken of the links sent by email.
risposta 200 · Confirmed.
{
"ok": true,
"email": "string",
"page": "string"
}
errori: 404 not found
post/api/public/subscriptions/{token}/unsubscribeUnsubscribe from a status pagepubblico

Removes the address. Also the target of the List-Unsubscribe header of update emails (RFC 8058 one-click: the body may be a form, not JSON).

parametri
token*path · stringToken of the links sent by email.
risposta 200 · Unsubscribed.
{
"ok": true,
"email": "string",
"page": "string"
}
errori: 404 not found
get/api/status-pagesList status pagestoken di lettura
risposta 200 · Pages.
{
"pages": [
{
"id": 1,
"slug": "string",
"title": "string",
"description": "string",
"domain": "string",
"header_url": "string",
"hide_title": true,
"logo": {
"svg": true,
"width": 1,
"height": 1,
"v": 1
},
"published": true,
"show_incidents": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"created_at": 1761868800000,
"subscribe_notifier_id": 1,
"protected": true,
"password": "string"
}
],
"hub_url": "string"
}
errori: 401 not logged in, or the token is invalid or expired
post/api/status-pagesCreate a status pagetoken di scrittura · admin
body della richiesta · application/json
idinteger
slug*stringURL path: /status/<slug>. 1-50 lowercase letters, digits or dashes.
title*string
descriptionstring
domainstringOptional custom domain serving the page, e.g. status.example.com.
header_urlstringOptional http(s) address the page name links to, e.g. the company website. Empty = the name is not a link.
hide_titlebooleanShow only the logo in the page header, without the page name (it stays the browser tab title). Ignored when the page has no logo.
logoPageLogoThe page logo, only in the answer of GET /api/status-pages/{id}. Change it with the logo routes.
publishedbooleanDrafts are visible only to logged-in users.
show_incidentsboolean
monitor_idsinteger[]
group_idsinteger[]Every monitor of these groups, current and future.
created_atintegerUnix time in milliseconds (0 = never / unknown).
subscribe_notifier_idintegerEmail notification channel that sends incident updates to the page's subscribers (its SMTP server and sender are used, its recipients are not). 0 = visitors cannot subscribe.
protectedbooleanVisitors need a password to open the page, its badges and its subscription form. Logged-in users open it without one. On save, false removes the password and true keeps the current one.
passwordstringNew password for visitors (6-72 characters), stored hashed and never returned. Needed when protected is set on a page without one.
esempio
{
"slug": "acme",
"title": "Acme status",
"description": "",
"domain": "",
"published": true,
"show_incidents": true,
"monitor_ids": [
7
],
"group_ids": []
}
risposta 201 · Created.
{
"id": 1,
"slug": "string",
"title": "string",
"description": "string",
"domain": "string",
"header_url": "string",
"hide_title": true,
"logo": {
"svg": true,
"width": 1,
"height": 1,
"v": 1
},
"published": true,
"show_incidents": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"created_at": 1761868800000,
"subscribe_notifier_id": 1,
"protected": true,
"password": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
get/api/status-pages/{id}Get a status pagetoken di lettura
parametri
id*path · integerId of the status page.
risposta 200 · Page.
{
"id": 1,
"slug": "string",
"title": "string",
"description": "string",
"domain": "string",
"header_url": "string",
"hide_title": true,
"logo": {
"svg": true,
"width": 1,
"height": 1,
"v": 1
},
"published": true,
"show_incidents": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"created_at": 1761868800000,
"subscribe_notifier_id": 1,
"protected": true,
"password": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 404 not found
put/api/status-pages/{id}Update a status pagetoken di scrittura · admin
parametri
id*path · integerId of the status page.
body della richiesta · application/json
idinteger
slug*stringURL path: /status/<slug>. 1-50 lowercase letters, digits or dashes.
title*string
descriptionstring
domainstringOptional custom domain serving the page, e.g. status.example.com.
header_urlstringOptional http(s) address the page name links to, e.g. the company website. Empty = the name is not a link.
hide_titlebooleanShow only the logo in the page header, without the page name (it stays the browser tab title). Ignored when the page has no logo.
logoPageLogoThe page logo, only in the answer of GET /api/status-pages/{id}. Change it with the logo routes.
publishedbooleanDrafts are visible only to logged-in users.
show_incidentsboolean
monitor_idsinteger[]
group_idsinteger[]Every monitor of these groups, current and future.
created_atintegerUnix time in milliseconds (0 = never / unknown).
subscribe_notifier_idintegerEmail notification channel that sends incident updates to the page's subscribers (its SMTP server and sender are used, its recipients are not). 0 = visitors cannot subscribe.
protectedbooleanVisitors need a password to open the page, its badges and its subscription form. Logged-in users open it without one. On save, false removes the password and true keeps the current one.
passwordstringNew password for visitors (6-72 characters), stored hashed and never returned. Needed when protected is set on a page without one.
esempio
{
"slug": "acme",
"title": "Acme status",
"description": "",
"domain": "",
"published": true,
"show_incidents": true,
"monitor_ids": [
7
],
"group_ids": []
}
risposta 200 · Updated.
{
"id": 1,
"slug": "string",
"title": "string",
"description": "string",
"domain": "string",
"header_url": "string",
"hide_title": true,
"logo": {
"svg": true,
"width": 1,
"height": 1,
"v": 1
},
"published": true,
"show_incidents": true,
"monitor_ids": [
1
],
"group_ids": [
1
],
"created_at": 1761868800000,
"subscribe_notifier_id": 1,
"protected": true,
"password": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found · 409 already exists
delete/api/status-pages/{id}Delete a status pagetoken di scrittura · admin
parametri
id*path · integerId of the status page.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/status-pages/{id}/incidentsList the incidents of a status pagetoken di lettura

Incidents written on the page, open ones first, each with its updates (newest first).

parametri
id*path · integerId of the status page.
risposta 200 · Incidents.
{
"incidents": [
{
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
{
"id": null,
"incident_id": null,
"status": null,
"message": null,
"created_at": null
}
]
}
]
}
errori: 401 not logged in, or the token is invalid or expired · 404 not found
post/api/status-pages/{id}/incidentsCreate an incident on a status pagetoken di scrittura · admin

Opens an incident with its first update. With notify (default true) the update is emailed to the confirmed subscribers of the page, in the background.

parametri
id*path · integerId of the status page.
body della richiesta · application/json
titlestringOne line, at most 200 characters. Required to create and to edit.
impactstringDefault minor.uno tra: none minor major critical
statusstringStatus of the update. Default investigating when creating.uno tra: investigating identified monitoring resolved
messagestringText of the update, at most 5000 characters. Required to create and for updates.
notifybooleanEmail the update to the confirmed subscribers of the page (default true). Ignored when editing the title or impact.
esempio
{
"title": "Slow API responses",
"impact": "minor",
"status": "investigating",
"message": "We are looking into slow responses of the API.",
"notify": true
}
risposta 201 · Created.
{
"incident": {
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
{
"id": 1,
"incident_id": 1,
"status": "investigating",
"message": "string",
"created_at": 1761868800000
}
]
},
"notified": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
put/api/status-pages/{id}/incidents/{incident}Edit an incidenttoken di scrittura · admin

Changes the title and impact. Updates are added with POST …/updates.

parametri
id*path · integerId of the status page.
incident*path · integerId of the incident.
body della richiesta · application/json
titlestringOne line, at most 200 characters. Required to create and to edit.
impactstringDefault minor.uno tra: none minor major critical
statusstringStatus of the update. Default investigating when creating.uno tra: investigating identified monitoring resolved
messagestringText of the update, at most 5000 characters. Required to create and for updates.
notifybooleanEmail the update to the confirmed subscribers of the page (default true). Ignored when editing the title or impact.
esempio
{
"title": "Slow API responses in EU",
"impact": "major"
}
risposta 200 · Incident.
{
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
{
"id": 1,
"incident_id": 1,
"status": "investigating",
"message": "string",
"created_at": 1761868800000
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/status-pages/{id}/incidents/{incident}Delete an incidenttoken di scrittura · admin

Removes the incident and all its updates from the page.

parametri
id*path · integerId of the status page.
incident*path · integerId of the incident.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/status-pages/{id}/incidents/{incident}/updatesPost an incident updatetoken di scrittura · admin

Adds an update to the timeline; the incident takes its status (resolved closes it, any other status reopens it). With notify (default true) it is emailed to the confirmed subscribers.

parametri
id*path · integerId of the status page.
incident*path · integerId of the incident.
body della richiesta · application/json
titlestringOne line, at most 200 characters. Required to create and to edit.
impactstringDefault minor.uno tra: none minor major critical
statusstringStatus of the update. Default investigating when creating.uno tra: investigating identified monitoring resolved
messagestringText of the update, at most 5000 characters. Required to create and for updates.
notifybooleanEmail the update to the confirmed subscribers of the page (default true). Ignored when editing the title or impact.
esempio
{
"status": "resolved",
"message": "Response times are back to normal.",
"notify": true
}
risposta 201 · Added.
{
"incident": {
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
{
"id": 1,
"incident_id": 1,
"status": "investigating",
"message": "string",
"created_at": 1761868800000
}
]
},
"notified": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/status-pages/{id}/incidents/{incident}/updates/{update}Delete an incident updatetoken di scrittura · admin

Removes one update; the incident takes the status of the latest one left. The last update cannot be deleted (409): delete the incident instead.

parametri
id*path · integerId of the status page.
incident*path · integerId of the incident.
update*path · integerId of the update.
risposta 200 · Incident.
{
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
{
"id": 1,
"incident_id": 1,
"status": "investigating",
"message": "string",
"created_at": 1761868800000
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found · 409 already exists
get/api/status-pages/{id}/subscribersList the email subscribers of a status pagesessione admin

Addresses subscribed to incident updates, confirmed or waiting for confirmation (unconfirmed ones are dropped after 7 days). enabled is false when the page has no working email channel.

parametri
id*path · integerId of the status page.
risposta 200 · Subscribers.
{
"subscribers": [
{
"id": 1,
"page_id": 1,
"email": "string",
"confirmed_at": 1,
"created_at": 1761868800000
}
],
"enabled": true
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/status-pages/{id}/subscribers/{subscriber}Remove an email subscribersessione admin

The address gets no more emails from the page.

parametri
id*path · integerId of the status page.
subscriber*path · integerId of the subscriber.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/status-pages/previewPreview a status pagetoken di scrittura · admin

What visitors would see with these settings, without saving them. With the id of a saved page, the incidents written on it are included.

body della richiesta · application/json
idinteger
slug*stringURL path: /status/<slug>. 1-50 lowercase letters, digits or dashes.
title*string
descriptionstring
domainstringOptional custom domain serving the page, e.g. status.example.com.
header_urlstringOptional http(s) address the page name links to, e.g. the company website. Empty = the name is not a link.
hide_titlebooleanShow only the logo in the page header, without the page name (it stays the browser tab title). Ignored when the page has no logo.
logoPageLogoThe page logo, only in the answer of GET /api/status-pages/{id}. Change it with the logo routes.
publishedbooleanDrafts are visible only to logged-in users.
show_incidentsboolean
monitor_idsinteger[]
group_idsinteger[]Every monitor of these groups, current and future.
created_atintegerUnix time in milliseconds (0 = never / unknown).
subscribe_notifier_idintegerEmail notification channel that sends incident updates to the page's subscribers (its SMTP server and sender are used, its recipients are not). 0 = visitors cannot subscribe.
protectedbooleanVisitors need a password to open the page, its badges and its subscription form. Logged-in users open it without one. On save, false removes the password and true keeps the current one.
passwordstringNew password for visitors (6-72 characters), stored hashed and never returned. Needed when protected is set on a page without one.
esempio
{
"slug": "acme",
"title": "Acme status",
"description": "",
"domain": "",
"published": true,
"show_incidents": true,
"monitor_ids": [
7
],
"group_ids": []
}
risposta 200 · Page.
{
"slug": "string",
"title": "string",
"description": "string",
"header_url": "string",
"logo": {
"svg": true,
"width": 1,
"height": 1,
"v": 1
},
"hide_title": true,
"published": true,
"status": "operational",
"days": 1,
"monitors": [
{
"id": 1,
"name": "string",
"group": "string",
"status": "string",
"uptime": 12.5,
"uptime_24h": 12.5,
"bars": [
{
"t": null,
"total": null,
"ok": null,
"degraded": null,
"maint": null,
"avg_ms": null
}
]
}
],
"show_incidents": true,
"incidents": [
{
"id": 1,
"monitor_name": "string",
"started_at": 1761868800000,
"resolved_at": 1761868800000
}
],
"updated_at": 1761868800000,
"reports": [
{
"id": 1,
"page_id": 1,
"title": "string",
"impact": "none",
"status": "investigating",
"created_at": 1761868800000,
"updated_at": 1761868800000,
"resolved_at": 1,
"updates": [
null
]
}
],
"subscribe": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication

──system

Health, counters, metrics and this document.

get/api/docsInteractive API docspubblico

Redirects to the Swagger UI page of the web app.

errori: 302 redirect to /api-docs/
get/api/healthHealth checkpubblico

Liveness probe, also returns the hub version.

risposta 200 · Hub is running.
{
"ok": true,
"version": "v0.1.0"
}
get/api/openapi.jsonOpenAPI documentpubblico

This document, for the running version.

risposta 200 · OpenAPI 3.1 document.
{}
get/api/overviewDashboard counterstoken di lettura
risposta 200 · Counters.
{
"monitors": 12,
"status": {
"up": 10,
"down": 1,
"paused": 1
},
"agents": 2,
"agents_online": 2,
"open_incidents": 1,
"version": "v0.1.0"
}
errori: 401 not logged in, or the token is invalid or expired
get/api/telemetryAnonymous usage statssessione admin
risposta 200 · Usage stats status.
{
"enabled": true,
"asked": true,
"forced_off": true,
"report": null,
"sent_at": 1,
"error": "string"
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/telemetryTurn anonymous usage stats on or offsessione admin
body della richiesta · application/json
enabled*boolean
esempio
{
"enabled": true
}
risposta 200 · Usage stats status.
{
"enabled": true,
"asked": true,
"forced_off": true,
"report": null,
"sent_at": 1,
"error": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 usage stats are turned off on this hub (pingtxt_disable_telemetry or a development build)
get/api/versionVersion and update checktoken di lettura
risposta 200 · Version status.
{
"current": "string",
"check_enabled": true,
"check_disabled": true,
"latest": null,
"update_available": true,
"checked_at": 1,
"error": "string"
}
errori: 401 not logged in, or the token is invalid or expired
post/api/version/checkCheck for a new version nowsessione admin
risposta 200 · Version status.
{
"current": "string",
"check_enabled": true,
"check_disabled": true,
"latest": null,
"update_available": true,
"checked_at": 1,
"error": "string"
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 the check is off (settings, or a development build)
get/metricsPrometheus metricstoken di lettura

Metrics in the Prometheus text format. Public when *settings → general → metrics* is set to public.

risposta 200 · Metrics.
pingtxt_monitor_up{monitor="Website",type="http"} 1
errori: 401 not logged in, or the token is invalid or expired

──auth

Setup, login, password, single sign-on and two-factor. Browser oriented.

post/api/auth/2fa/disableDisable two-factorsessione del browser
body della richiesta · application/json
code*stringTOTP or recovery code.
esempio
{
"code": "string"
}
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 429 too many failed attempts. password logins are limited to 10 failures per account and 30 per client address in 15 minutes; second factor codes to 10 wrong codes per user. wait for `retry-after` seconds
post/api/auth/2fa/enableEnable two-factorsessione del browser
body della richiesta · application/json
code*string
esempio
{
"code": "123456"
}
risposta 200 · Enabled. Recovery codes are shown once.
{
"recovery_codes": [
"string"
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/auth/2fa/recovery-codesNew recovery codessessione del browser

Replaces the old codes.

body della richiesta · application/json
code*string
esempio
{
"code": "string"
}
risposta 200 · New codes.
{
"recovery_codes": [
"string"
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 429 too many failed attempts. password logins are limited to 10 failures per account and 30 per client address in 15 minutes; second factor codes to 10 wrong codes per user. wait for `retry-after` seconds
post/api/auth/2fa/setupStart two-factor setupsessione del browser

Returns a new TOTP secret; confirm it with /api/auth/2fa/enable.

risposta 200 · Secret and otpauth:// URI for the QR code.
{
"secret": "string",
"uri": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
delete/api/auth/identities/{provider}Unlink a single sign-on providersessione del browser
parametri
provider*path · stringuno tra: github google oidc
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/auth/loginLog in with passwordpubblico

Sets the pingtxt_session cookie. When the user has two-factor authentication, the response is {"two_factor": true, "challenge": "..."} instead: send the challenge with a code to /api/auth/login/2fa.

body della richiesta · application/json
email*string
password*string
esempio
{
"email": "admin@example.com",
"password": "correct horse"
}
risposta 200 · Logged in, or a two-factor challenge.
{
"id": 1,
"email": "string",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": true,
"identities": [
{
"provider": "string",
"email": "string",
"created_at": 1761868800000
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 429 too many failed attempts. password logins are limited to 10 failures per account and 30 per client address in 15 minutes; second factor codes to 10 wrong codes per user. wait for `retry-after` seconds
post/api/auth/login/2faComplete a two-factor loginpubblico
body della richiesta · application/json
challenge*string
code*string6 digit TOTP code or a recovery code.
esempio
{
"challenge": "string",
"code": "string"
}
risposta 200 · Logged in, session cookie set.
{
"id": 1,
"email": "string",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": true,
"identities": [
{
"provider": "string",
"email": "string",
"created_at": 1761868800000
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 429 too many failed attempts. password logins are limited to 10 failures per account and 30 per client address in 15 minutes; second factor codes to 10 wrong codes per user. wait for `retry-after` seconds
post/api/auth/logoutLog outpubblico

Ends the browser session.

risposta 200 · Done.
{
"ok": true
}
get/api/auth/meCurrent usertoken di lettura
risposta 200 · The user behind the session or token.
{
"user": {
"id": 1,
"email": "admin@example.com",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": false,
"identities": []
},
"version": "v0.1.0",
"recovery_codes_left": 10
}
errori: 401 not logged in, or the token is invalid or expired
get/api/auth/oauth/{provider}/callbackSingle sign-on callbackpubblico

Register <public url>/api/auth/oauth/<provider>/callback at the provider. Not meant to be called directly.

parametri
provider*path · stringuno tra: github google oidc
errori: 302 redirect to the app
get/api/auth/oauth/{provider}/startStart single sign-onpubblico

Browser redirect to the provider. ?next=/path returns there after login, ?link=1 links the provider to the logged-in account.

parametri
provider*path · stringuno tra: github google oidc
nextquery · stringLocal path to open after login.
linkquery · string1 to link to the current account.
errori: 302 redirect to the provider
get/api/auth/optionsLogin optionspubblico

What the login page shows: password form and single sign-on buttons.

risposta 200 · Options.
{
"password_login": true,
"providers": [
{
"id": "github",
"label": "GitHub"
}
]
}
post/api/auth/passwordChange passwordsessione del browser

Other sessions of the user are logged out. Accounts created with single sign-on can set a first password with an empty current.

body della richiesta · application/json
currentstring
new*stringAt least 8 characters.
esempio
{
"current": "string",
"new": "string"
}
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/setupSetup statepubblico

Whether the instance still needs its first admin account.

risposta 200 · State.
{
"needs_setup": false,
"version": "v0.1.0"
}
post/api/setupCreate the first adminpubblico

Works only while no user exists. Starts a session.

body della richiesta · application/json
email*string
password*stringAt least 8 characters.
esempio
{
"email": "admin@example.com",
"password": "correct horse"
}
risposta 201 · Admin created, session cookie set.
{
"id": 1,
"email": "admin@example.com",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": false,
"identities": []
}
errori: 400 invalid input · 409 already exists

──api tokens

Personal tokens and connected OAuth apps. Browser session only.

get/api/oauth/grantsList connected appssessione del browser

Apps connected through OAuth (the iOS app, MCP clients): one entry per sign-in.

risposta 200 · Grants.
[
{
"id": 1,
"client_id": "string",
"client_name": "string",
"scope": "string",
"expires_at": 1761868800000,
"created_at": 1761868800000,
"last_used_at": 1761868800000,
"push_device": "string"
}
]
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
delete/api/oauth/grants/{id}Disconnect an appsessione del browser
parametri
id*path · integerId of the grant.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
get/api/tokensList your API tokenssessione del browser
risposta 200 · Tokens of the current user.
[
{
"id": 1,
"name": "string",
"hint": "string",
"scope": "read",
"created_at": 1761868800000,
"last_used_at": 1761868800000,
"expires_at": 1
}
]
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/tokensCreate an API tokensessione del browser

The secret is returned once. Read-only users can only create read tokens. At most 50 tokens per user.

body della richiesta · application/json
name*stringUp to 100 characters.
scope*stringuno tra: read write
expires_in_daysinteger0 = never, up to 3650.
esempio
{
"name": "grafana",
"scope": "read",
"expires_in_days": 365
}
risposta 201 · Created.
{
"token": {
"id": 3,
"name": "grafana",
"hint": "x9Qa",
"scope": "read",
"created_at": 1761868800000,
"last_used_at": 0,
"expires_at": 1793404800000
},
"secret": "ptk_5uG...x9Qa"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
delete/api/tokens/{id}Revoke an API tokensessione del browser
parametri
id*path · integerId of the token.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found

──users

Accounts and roles. Admin browser session only.

get/api/usersList userssessione admin
risposta 200 · Users.
[
{
"id": 1,
"email": "string",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": true,
"identities": [
{
"provider": "string",
"email": "string",
"created_at": 1761868800000
}
]
}
]
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/usersCreate a usersessione admin

Without a password the user logs in with single sign-on (matched by verified email).

body della richiesta · application/json
email*string
passwordstringOptional, at least 8 characters.
role*stringuno tra: admin viewer
esempio
{
"email": "dev@example.com",
"role": "viewer"
}
risposta 201 · Created.
{
"id": 1,
"email": "string",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": true,
"identities": [
{
"provider": "string",
"email": "string",
"created_at": 1761868800000
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists
put/api/users/{id}Change a user's rolesessione admin

You cannot change your own role.

parametri
id*path · integerId of the user.
body della richiesta · application/json
role*stringuno tra: admin viewer
esempio
{
"role": "admin"
}
risposta 200 · Updated.
{
"id": 1,
"email": "string",
"role": "admin",
"created_at": 1761868800000,
"has_password": true,
"two_factor": true,
"identities": [
{
"provider": "string",
"email": "string",
"created_at": 1761868800000
}
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/users/{id}Delete a usersessione admin
parametri
id*path · integerId of the user.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/users/{id}/2faReset a user's two-factorsessione admin
parametri
id*path · integerId of the user.
risposta 200 · Done.
{
"ok": true
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found

──settings

Instance settings. Admin browser session only.

get/api/settingsGet instance settingssessione admin
risposta 200 · Settings.
{
"general": {
"public_url": "string",
"local_name": "string",
"local_enabled": true,
"retention_days": 1,
"raw_retention_days": 1,
"monitor_defaults": {
"interval_sec": 1,
"timeout_ms": 1,
"retries": 1
},
"expiry": {
"cert_days": [
1
],
"domain_days": [
1
]
},
"metrics": {
"public": true
},
"degraded_pct": 1,
"ip_family": 1,
"update_check": {
"disabled": true
}
},
"auth": {
"password_login": true,
"allow_signup": true,
"allowed_domains": [
"string"
],
"default_role": "string",
"providers": [
{
"id": "string",
"label": "string",
"enabled": true,
"client_id": "string",
"client_secret": "string",
"client_secret_set": true,
"callback_url": "string",
"name": "string",
"issuer": "string",
"scopes": "string"
}
]
},
"detected_url": "string"
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/settings/authSave login settingssessione admin
body della richiesta · application/json
password_loginboolean
allow_signupbooleanCreate accounts on first single sign-on login.
allowed_domainsstring[]Email domains allowed to sign up, empty = any.
default_rolestringuno tra: admin viewer
providersobjectKeyed by github, google, oidc.
esempio
{
"password_login": true,
"allow_signup": true,
"allowed_domains": [
"string"
],
"default_role": "admin",
"providers": {
"key": {
"enabled": true,
"client_id": "string",
"client_secret": "string",
"name": "string",
"issuer": "string",
"scopes": "string"
}
}
}
risposta 200 · Settings.
{
"general": {
"public_url": "string",
"local_name": "string",
"local_enabled": true,
"retention_days": 1,
"raw_retention_days": 1,
"monitor_defaults": {
"interval_sec": 1,
"timeout_ms": 1,
"retries": 1
},
"expiry": {
"cert_days": [
1
],
"domain_days": [
1
]
},
"metrics": {
"public": true
},
"degraded_pct": 1,
"ip_family": 1,
"update_check": {
"disabled": true
}
},
"auth": {
"password_login": true,
"allow_signup": true,
"allowed_domains": [
"string"
],
"default_role": "string",
"providers": [
{
"id": "string",
"label": "string",
"enabled": true,
"client_id": "string",
"client_secret": "string",
"client_secret_set": true,
"callback_url": "string",
"name": "string",
"issuer": "string",
"scopes": "string"
}
]
},
"detected_url": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/settings/generalSave general settingssessione admin
body della richiesta · application/json
public_urlstringPublic URL of the hub, used in links, agent setup and OAuth callbacks.
local_namestringName of the hub's own location.
local_enabledbooleanThe hub runs checks itself.
retention_daysintegerHourly history, up to 3650.
raw_retention_daysintegerEvery single check.
monitor_defaultsobject
expiryobject
metricsobject
degraded_pctintegerDefault degraded threshold, 1 to 50.
ip_familyintegerDefault IP family of monitors with ip_family 0: 1 IPv4 or IPv6 (default), 4 IPv4 only, 6 IPv6 only, 46 IPv4 and IPv6. Locations without IPv6 check those monitors over IPv4.uno tra: 1 4 6 46
update_checkobject
esempio
{
"public_url": "string",
"local_name": "string",
"local_enabled": true,
"retention_days": 1,
"raw_retention_days": 1,
"monitor_defaults": {
"interval_sec": 1,
"timeout_ms": 1,
"retries": 1
},
"expiry": {
"cert_days": [
1
],
"domain_days": [
1
]
},
"metrics": {
"public": true
},
"degraded_pct": 1,
"ip_family": 1,
"update_check": {
"disabled": true
}
}
risposta 200 · Settings.
{
"general": {
"public_url": "string",
"local_name": "string",
"local_enabled": true,
"retention_days": 1,
"raw_retention_days": 1,
"monitor_defaults": {
"interval_sec": 1,
"timeout_ms": 1,
"retries": 1
},
"expiry": {
"cert_days": [
1
],
"domain_days": [
1
]
},
"metrics": {
"public": true
},
"degraded_pct": 1,
"ip_family": 1,
"update_check": {
"disabled": true
}
},
"auth": {
"password_login": true,
"allow_signup": true,
"allowed_domains": [
"string"
],
"default_role": "string",
"providers": [
{
"id": "string",
"label": "string",
"enabled": true,
"client_id": "string",
"client_secret": "string",
"client_secret_set": true,
"callback_url": "string",
"name": "string",
"issuer": "string",
"scopes": "string"
}
]
},
"detected_url": "string"
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/settings/pushGet mobile app push settingssessione admin
risposta 200 · Push settings.
{
"enabled": true,
"relay_url": "string",
"hub_id": "string",
"registered": true,
"devices": 1
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/settings/pushSave mobile app push settingssessione admin

Turning push on registers the hub with the relay the first time, and again when the relay no longer accepts the hub token (its secret changed): the phones then enroll again. A different relay URL drops the registration and every phone (they enroll again).

body della richiesta · application/json
enabledboolean
relay_urlstring
esempio
{
"enabled": true,
"relay_url": "https://push.pingtxt.com"
}
risposta 200 · Saved.
{
"enabled": true,
"relay_url": "string",
"hub_id": "string",
"registered": true,
"devices": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 502 the notification could not be delivered
post/api/settings/push/testTest the push relaysessione admin

Checks the hub token at the relay and that the relay can reach Firebase.

risposta 200 · The relay accepts this hub.
{
"ok": true,
"hub_id": "string"
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 409 already exists · 502 the notification could not be delivered

──backups

Database backups and configuration export/import.

get/api/backupsList backupssessione admin
risposta 200 · Backups and settings.
{
"settings": {
"enabled": true,
"interval_hours": 1,
"keep": 1
},
"backups": [
{
"name": "string",
"kind": "auto",
"size": 1,
"created_at": 1761868800000
}
],
"dir": "string",
"pending_restore": {
"name": "string",
"staged_at": 1761868800000
},
"driver": "string",
"file_backups": true
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/backupsBack up nowsessione admin
risposta 201 · Backup file.
{
"name": "string",
"kind": "auto",
"size": 1,
"created_at": 1761868800000
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/backups/{name}Download a backupsessione admin
parametri
name*path · stringBackup file name.
risposta 200 · The file.
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/backups/{name}Delete a backupsessione admin
parametri
name*path · stringBackup file name.
risposta 200 · Done.
{
"ok": true
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
post/api/backups/{name}/restoreStage a restoresessione admin

The backup replaces the database at the next start of the hub.

parametri
name*path · stringBackup file name.
risposta 200 · Staged.
{
"pending_restore": {
"name": "string",
"staged_at": 1761868800000
},
"info": {
"schema_version": 1,
"monitors": 1,
"users": 1
}
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication · 404 not found
delete/api/backups/restoreCancel a staged restoresessione admin
risposta 200 · Done.
{
"ok": true
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/backups/uploadUpload a backupsessione admin

Raw SQLite file as the body (Content-Type: application/octet-stream), up to 4 GB. SQLite only.

body della richiesta · application/octet-stream
risposta 201 · Stored.
{
"backup": {
"name": "string",
"kind": "auto",
"size": 1,
"created_at": 1761868800000
},
"info": {
"schema_version": 1,
"monitors": 1,
"users": 1
}
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
get/api/config/exportExport the configurationtoken di lettura

Admins only. Without secrets by default; ?secrets=1 needs a browser session (API tokens get 403).

parametri
secretsquery · string1 to include passwords and tokens.
risposta 200 · JSON download.
{
"format": "string",
"version": 1,
"hub_version": "string",
"exported_at": "string",
"secrets": true,
"settings": {},
"agents": [
{}
],
"groups": [
{}
],
"tags": [
{}
],
"notifiers": [
{}
],
"monitors": [
{}
],
"maintenances": [
{}
],
"status_pages": [
{}
]
}
errori: 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/config/importImport a configurationsessione admin

A backup is taken first. Body up to 64 MB.

parametri
modequery · stringreplace deletes what is not in the document.uno tra: merge replace
settingsquery · string0 to leave instance settings alone.
body della richiesta · application/json
formatstringAlways "pingtxt-config".
versioninteger
hub_versionstring
exported_atstring
secretsbooleanPasswords and tokens are included.
settingsobject
agentsobject[]
groupsobject[]
tagsobject[]
notifiersobject[]
monitorsobject[]
maintenancesobject[]
status_pagesobject[]
esempio
{
"format": "string",
"version": 1,
"hub_version": "string",
"exported_at": "string",
"secrets": true,
"settings": {},
"agents": [
{}
],
"groups": [
{}
],
"tags": [
{}
],
"notifiers": [
{}
],
"monitors": [
{}
],
"maintenances": [
{}
],
"status_pages": [
{}
]
}
risposta 200 · Result.
{
"mode": "merge",
"backup": "string",
"created": {
"key": 1
},
"updated": {
"key": 1
},
"deleted": {
"key": 1
},
"skipped": {
"key": 1
},
"settings": true,
"warnings": [
"string"
]
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
post/api/import/uptime-kumaImport from Uptime Kumasessione admin

Creates monitors from an Uptime Kuma 1.x backup file (Settings → Backup → Export in Uptime Kuma). Kuma groups become groups, tags become tags, paused monitors stay paused. Monitors whose name already exists are left alone; unsupported types are skipped with a reason. Notification channels are not imported. With dry_run=1 nothing is created and the answer is the preview.

parametri
dry_runquery · booleanPreview only.
body della richiesta · application/json
versionstring
monitorList*object[]
esempio
{
"version": "string",
"monitorList": [
{}
]
}
risposta 200 · What was (or would be) done with each monitor.
{
"version": "string",
"monitors": [
{
"name": "string",
"kuma_type": "string",
"type": "string",
"target": "string",
"group": "string",
"paused": true,
"action": "create",
"reason": "string",
"note": "string"
}
],
"groups": [
"string"
],
"tags": [
"string"
],
"warnings": [
"string"
],
"created": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication
put/api/settings/backupsSave backup schedulesessione admin
body della richiesta · application/json
enabledboolean
interval_hoursinteger
keepintegerScheduled backups to keep.
esempio
{
"enabled": true,
"interval_hours": 24,
"keep": 7
}
risposta 200 · Saved.
{
"enabled": true,
"interval_hours": 1,
"keep": 1
}
errori: 400 invalid input · 401 not logged in, or the token is invalid or expired · 403 not allowed for this role, token scope or kind of authentication

──oauth

OAuth 2.1 authorization server for native apps and MCP clients. Form bodies, OAuth error format.

get/.well-known/oauth-authorization-serverAuthorization server metadatapubblico

RFC 8414 metadata: endpoints, scopes, PKCE methods.

risposta 200 · Metadata.
{}
get/oauth/authorizeStart a sign-inpubblico

Open in a browser (ASWebAuthenticationSession on iOS). The user logs in on the hub if needed and allows the app on a consent page; the browser then goes to redirect_uri with code, state and iss, or with error.

parametri
response_type*query · stringcode.
client_id*query · stringpingtxt-ios for the iOS app.
redirect_uri*query · stringpingtxt://oauth for the iOS app.
code_challenge*query · stringBASE64URL(SHA256(code_verifier)), no padding.
code_challenge_method*query · stringS256.
state*query · stringRandom value, checked on return.
scopequery · stringread, write or read write: write is preselected on the consent page for admins.
resourcequery · stringOptional (RFC 8707): <hub>/api or <hub>/mcp.
risposta 200 · Consent page (HTML).
errori: 302 to the login page, or back to `redirect_uri` · 400 unknown client or redirect uri not registered (html, no redirect)
post/oauth/revokeSign outpubblico

Ends the sign-in of the token (access or refresh token, RFC 7009). Always answers 200.

body della richiesta · application/x-www-form-urlencoded
token*stringRefresh or access token.
client_id*stringpingtxt-ios for the iOS app.
risposta 200 · Done (also when the token was unknown).
post/oauth/tokenGet or refresh tokenspubblico

grant_type=authorization_code exchanges the code (single use, 5 minutes) for tokens. grant_type=refresh_token returns a new access token and a new refresh token: the old one stops working, and using it again revokes the whole sign-in, so refresh one request at a time and store the new refresh token before using it.

body della richiesta · application/x-www-form-urlencoded
grant_type*stringauthorization_code or refresh_token.
client_id*stringpingtxt-ios for the iOS app.
codestringauthorization_code: the code from the redirect.
redirect_uristringauthorization_code: same as in the authorization request.
code_verifierstringauthorization_code: the PKCE verifier.
refresh_tokenstringrefresh_token: the latest refresh token.
risposta 200 · Tokens.
{
"access_token": "string",
"token_type": "Bearer",
"expires_in": 1,
"refresh_token": "string",
"scope": "read"
}
errori: 400 oauth error