Healthchecks-API: Checks per API v2 anlegen und abfragen
Mit der Healthchecks-API (Teil der API v2 von IPv64.net) legst du Checks per Skript an, änderst, pausierst und löschst sie, fragst Messwerte, Ereignisse und Störungen ab und verwaltest Benachrichtigungskanäle, Wartungsfenster und Nodes. Die Feldnamen sind dieselben wie in der API von Node64, sodass Skripte gegen beide gleich aussehen.
Überblick: Basis-URL, Format und Fehler
Alle Pfade dieser Seite beginnen mit /hc2 und hängen an die Basis-URL der API v2:
https://ipv64.net/api/v2
- Methoden: GET, POST, PATCH und DELETE. Wer nur GET und POST senden kann, schickt POST mit dem Header
X-HTTP-Method-Override: PATCH(bzw.DELETE). - Anfragen als JSON (
Content-Type: application/json), höchstens 1 MB.PATCHändert nur die mitgeschickten Felder. - Antworten als JSON im Umschlag
{"data": …, "meta": {…}};metagibt es nur bei Listen mit Seitenangaben.DELETEantwortet mit204ohne Inhalt. - Zeiten im Format ISO 8601 mit Zeitzone, in Antworten immer UTC (z. B.
2026-10-26T08:15:00.000Z). - Die vollständige Beschreibung als OpenAPI 3.1 (Bereich „Healthchecks 2.0“) gibt es unter ipv64.net/api_v2_docs.
Fehler
Fehler kommen nach RFC 9457 als application/problem+json mit einem festen Fehlercode in code:
{
"type": "https://ipv64.net/api/v2/errors#limit_reached",
"title": "Forbidden",
"status": 403,
"detail": "Online-Limit erreicht: 10 von 10 Messstellen belegt, benötigt werden 2 weitere. …",
"code": "limit_reached",
"errors": ["Online-Limit erreicht: …"]
}
| HTTP | Codes (Auswahl) | Bedeutung |
|---|---|---|
| 401 | unauthenticated, invalid_token | API-Key fehlt, ist ungültig oder abgelaufen, oder das Konto ist nicht aktiv |
| 403 | limit_reached | Messstellen-Limit der Kontoklasse erreicht |
| 404 | not_found | Check, Kanal, Wartungsfenster, Testlauf oder Node nicht gefunden |
| 409 | move_requires_test, unchanged, not_verified, disabled, node_channel | Aktion im aktuellen Zustand nicht möglich (Details in detail) |
| 422 | invalid_healthcheck, private_target, invalid_type, move_rejected, invalid_channel, invalid_code … | Eingabe ungültig; bei Checks und Kanälen stehen alle Meldungen in errors |
| 429 | rate_limited, sms_limit | zu viele Anfragen bzw. Tageslimit für SMS erreicht |
| 502 | delivery_failed | Nachricht konnte nicht zugestellt werden |
Authentifizierung und Limits
Die API nutzt deine API-Keys aus Account > API (siehe Konto: API-Keys). Den Key schickst du nur im Header – nie in der URL:
curl "https://ipv64.net/api/v2/hc2/account" -H "Authorization: Bearer DEIN_API_KEY"
curl "https://ipv64.net/api/v2/hc2/account" -H "X-API-Key: DEIN_API_KEY"
Ein API-Key darf alles im Konto, nicht nur Healthchecks. Für einen Cronjob, der nur einen Push melden soll, brauchst du keinen API-Key – dafür gibt es die Push-URL mit dem Token des Checks.
Limits
- Allgemein: je Konto bis 300 Anfragen auf einmal, danach 10 pro Sekunde; je IP-Adresse 600 auf einmal, danach 20 pro Sekunde. Fehlgeschlagene Anmeldungen: 20, danach 12 pro Minute je IP. Die Header
RateLimit-LimitundRateLimit-Remainingzeigen den Stand; bei429nenntRetry-Afterdie Wartezeit in Sekunden. - Testnachrichten: eine pro 30 Sekunden je Kanal.
- Bestätigungscodes: 5 Codes pro Stunde, 10 Eingabeversuche pro Stunde – gemeinsam mit dem Portal.
- Versand über einen IPv64-Kanal (
/send): 30 auf einmal, danach 30 pro Stunde, höchstens 200 pro Tag; SMS zusätzlich nach dem Tageslimit deiner Kontoklasse. - Die Grenzen der Kontoklasse für Healthchecks (Online-Messstellen, Online-Messungen pro Tag, Standorte je Check) gelten auch per API, siehe Limits.
Konto und Einstellungen
GET /hc2/account
Kontoklasse, Limits und Verbrauch:
{"data": {
"plan": "Supporter",
"online_measuring_points": {"used": 6, "limit": 10},
"locations_per_check": 2,
"checks_per_day": {"used": 2817, "limit": 8192},
"sms_per_day": 50,
"locations": [{"code": "fsn", "name": "Falkenstein"}, {"code": "nbg", "name": "Nürnberg"}],
"nodes": {"total": 1, "online": 1},
"checks": 12
}}
limit: null heißt unbegrenzt; bei sms_per_day steht dafür 0.
GET und PATCH /hc2/settings
Ruhezeiten und Sammelmeldung des Kontos (siehe Benachrichtigungen). Erlaubte Schlüssel:
| Schlüssel | Wert |
|---|---|
notify.quiet_enabled | true/false (gespeichert als 1/0) |
notify.quiet_from, notify.quiet_to | Uhrzeit HH:MM |
notify.quiet_days | Wochentage 1 (Mo) bis 7 (So), als Liste oder "1,2,3" |
notify.quiet_tz | Zeitzone, z. B. Europe/Berlin |
notify.rate_per_hour | 0 bis 1000 (0 = unbegrenzt) |
notify.batch_threshold | 0 bis 100 |
notify.batch_window_seconds | 0 bis 600 |
curl -X PATCH "https://ipv64.net/api/v2/hc2/settings" -H "Authorization: Bearer DEIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"notify.quiet_enabled": true, "notify.quiet_from": "23:00", "notify.quiet_to": "06:30"}'
Checks verwalten
| Methode und Pfad | Wirkung |
|---|---|
GET /hc2/checks | alle Checks; Filter: type, state, execution, node_id, tag, group, q (Suche in Name und Ziel) |
POST /hc2/checks | Check anlegen → 201 mit dem Check |
GET /hc2/checks/{token} | ein Check mit Messstellen (sources) und Verfügbarkeit (availability_percent für 24h, 30d, 1y) |
PATCH /hc2/checks/{token} | Felder ändern (siehe unten zum Ausführungsort) |
DELETE /hc2/checks/{token} | Check mit allen Messdaten löschen → 204; war er Monitor im DNS Failover, nennt der Header Warning: 299 die Policies |
POST /hc2/checks/{token}/pause, /resume | pausieren bzw. fortsetzen; Antwort: der Check |
POST /hc2/checks/{token}/run | sofort prüfen: lokale und hybride Checks → 202 mit command_id je Node; Online-Checks → 200 mit queued: false (sie laufen im Intervall); Push-Checks → 422 not_applicable |
Felder eines Checks
| Feld | Standard beim Anlegen | Hinweis |
|---|---|---|
type | http | http, keyword, json, dns, icmp, tcp, port, cert, push, docker, whois |
name | – | Pflicht, bis 200 Zeichen |
target | – | URL, Host, IP, Domain oder Container – je nach Typ; bei push leer |
params | {} | Einstellungen des Typs (siehe Parameter je Typ) |
interval_seconds | 60 | lokal ab 5, online/hybrid ab 20, bis 86400; WHOIS ab 3600 |
retry_interval_seconds | 20 | ab 5, höchstens das Intervall |
retries, stabilize | 1, 3 | 0–10 bzw. 1–20 |
connect_timeout_seconds, timeout_seconds | 5, 10 | 0,5–60 bzw. 1–120 (online höchstens 30 bzw. 60) |
ip_mode | auto | auto, ipv4, ipv6, both |
execution | online | online, local, both |
nodes bzw. node_id | – | messende Nodes (Liste von IDs) bzw. eine Node; Pflicht bei local/both |
locations | alle Standorte | z. B. ["nbg","fsn"]; gekürzt auf die Standorte deiner Kontoklasse |
policy | all | all, any, majority |
notify_down, notify_up, notify_degraded | true, true, false | wofür benachrichtigt wird |
channels | [] | Kanal-IDs; leer = Standardkanäle |
repeat_minutes | 0 | Erinnerung, 0–10080 |
critical, invert, paused | false | |
group, tags, description | leer | Gruppe bis 100 Zeichen; Tags als Liste oder Text |
parent | leer | Token des übergeordneten Checks |
Die Antwort enthält zusätzlich token, node_id, node_name, nodes (mit Namen), revision, created_at, updated_at und state mit state, since, last_check_at, last_status, last_latency_ms, last_reason, last_message, down_since und last_push_at. Push-Checks haben dazu ein Objekt push (siehe Push-URL). Der Zustand ist einer von up, down, degraded, flapping, stabilizing, dependent, pending und paused; „nicht überwacht“ und „Kontingent aufgebraucht“ erkennst du an pending mit last_reason unchecked bzw. quota_exhausted.
Parameter je Typ (params)
| Typ | Schlüssel in params |
|---|---|
http, keyword, json | method, accept_status (z. B. "200-299,301"), follow_redirects, max_redirects, basic_user, basic_password, headers (Objekt), body, insecure_tls, cert_min_days (per API ohne Standard, also aus); nur keyword: keyword, keyword_absent; nur json: json_rules, json_any |
dns | record_type, resolver (system, server, authoritative), server, expect (any, contains, equals, regex, nxdomain, public_ip), values (Liste), min_ttl, dnssec |
icmp | count, max_loss_percent, max_latency_ms |
tcp | port, send, expect, tls |
port | port, expect (open oder closed) |
cert | port (Standard 443), min_days, server_name, skip_chain, skip_hostname |
whois | source (auto, rdap, whois), min_days, contains (Liste) |
push | period_seconds, grace_seconds |
json_rules ist eine Liste aus Objekten {"path": "status", "op": "eq", "value": "ok"} mit den Vergleichen eq, ne, lt, le, gt, ge, contains, not_contains, regex, exists, not_exists – oder die Textform wie im Formular. Grenzen und Bedeutung aller Werte stehen unter Check-Typen.
Beispiele
HTTPS-Check von beiden Standorten anlegen:
curl -X POST "https://ipv64.net/api/v2/hc2/checks" -H "Authorization: Bearer DEIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "http", "name": "Webseite", "target": "https://example.com/",
"interval_seconds": 60, "locations": ["nbg", "fsn"],
"params": {"accept_status": "200-299", "cert_min_days": 14}}'
Push-Check für ein nächtliches Backup:
curl -X POST "https://ipv64.net/api/v2/hc2/checks" -H "Authorization: Bearer DEIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "push", "name": "Backup NAS", "params": {"period_seconds": 86400, "grace_seconds": 3600}}'
Gestörte Checks auflisten, einen Check pausieren:
curl "https://ipv64.net/api/v2/hc2/checks?state=down" -H "Authorization: Bearer DEIN_API_KEY"
curl -X POST "https://ipv64.net/api/v2/hc2/checks/DEIN_CHECK_TOKEN/pause" -H "Authorization: Bearer DEIN_API_KEY"
Fehler beim Anlegen: 422 invalid_healthcheck (ungültige Eingabe), 422 private_target (privates Ziel online), 403 limit_reached (Messstellen-Limit).
Ausführungsort ändern (Umhängen)
Ändert ein PATCH execution, die Nodes oder die Standorte, speichert die API alle anderen Felder, lässt den Ausführungsort aber unverändert und antwortet mit 409 move_requires_test. Den Wechsel machst du mit einem Testlauf – oder du schickst "force_move": true mit, dann wird ohne Test umgestellt.
| Methode und Pfad | Wirkung |
|---|---|
POST /hc2/checks/{token}/move | Testlauf starten; Body: execution (Pflicht), nodes oder node_id, locations → 202 mit dem Testlauf |
GET /hc2/testruns/{id} | Stand des Testlaufs |
curl -X POST "https://ipv64.net/api/v2/hc2/checks/DEIN_CHECK_TOKEN/move" -H "Authorization: Bearer DEIN_API_KEY" \
-H "Content-Type: application/json" -d '{"execution": "both", "nodes": ["DEINE_NODE_ID"], "locations": ["nbg", "fsn"]}'
{"data": {"id": 4711, "status": "ok", "target": "both", "applied": true,
"results": [{"source": "ipv64 Nürnberg", "ok": true, "message": "ipv4 up 23.4 ms"}, …]}}
Frage den Testlauf alle 2 Sekunden ab, höchstens 60 Sekunden lang. status ist pending, ok (Wechsel übernommen, applied: true), failed (bleibt wie bisher) oder expired (keine Antwort in 60 Sekunden, dann mit error). Fehler beim Start: 409 unchanged (läuft schon so), 422 move_rejected (z. B. Node offline, Fernverwaltung aus, privates Ziel, Limit, Docker-Check).
Messwerte, Ereignisse, Störungen und Statistik
| Methode und Pfad | Parameter | Inhalt |
|---|---|---|
GET /hc2/checks/{token}/measurements | limit (1–5000, Standard 200), since, until, source | Einzelmessungen, neueste zuerst: time, source, source_label, status (up/down), latency_ms, reason, message, family, details |
GET /hc2/checks/{token}/events, GET /hc2/events | limit (1–1000, Standard 100), before, after, since | Ereignisse eines Checks bzw. aller Checks: id, token, source, kind, time, from_state, to_state, reason, message, duration_seconds, flaps, silent, incident_id |
GET /hc2/checks/{token}/incidents | limit (1–500, Standard 50) | Störungen eines Checks |
GET /hc2/incidents | limit (1–1000, Standard 100), open=true, since | Störungen aller Checks: id, token, name, status (open/closed), started_at, ended_at, duration_seconds, reason, message, sources |
GET /hc2/checks/{token}/stats | range: 24h (Standard), 7d, 30d, 1y | Verfügbarkeit und Latenz (min, Mittel, max) gesamt und je Messstelle, dazu eine Zeitreihe je Stunde (24h, 7d) bzw. je Tag (30d, 1y) |
- Messstellen (
source):loc:nbgbzw.loc:fsnfür die IPv64-Standorte,node:NODE_IDfür eine Node,pushfür Pushes. - Einzelmessungen hebt IPv64.net nur kurz auf; für längere Zeiträume nimm
/stats. - Seiten bei Ereignissen:
metaenthältlimit,has_moreundnext_before(bzw.next_after, wenn du mitaftervorwärts blätterst). Den Wert gibst du bei der nächsten Anfrage alsbeforebzw.aftermit. silent: trueheißt: Zu diesem Ereignis wurde keine Nachricht verschickt.
curl "https://ipv64.net/api/v2/hc2/checks/DEIN_CHECK_TOKEN/stats?range=30d" -H "Authorization: Bearer DEIN_API_KEY"
curl "https://ipv64.net/api/v2/hc2/incidents?open=true" -H "Authorization: Bearer DEIN_API_KEY"
Push-URL für Cronjobs
Pushes laufen nicht über die API v2 und brauchen keinen API-Key. Jeder Push-Check hat in der Antwort ein Objekt push:
| Feld | Inhalt |
|---|---|
url | https://ipv64.net/health.php?token=TOKEN – die Push-URL |
hub_url | eine gleichwertige Adresse direkt am Healthchecks-Server |
node_path | Pfad an der Node (/api/push/TOKEN) bei lokalen und hybriden Push-Checks, sonst null |
# OK melden
curl -fsS -m 10 "https://ipv64.net/health.php?token=DEIN_PUSH_TOKEN"
# Störung melden
curl -fsS -m 10 "https://ipv64.net/health.php?token=DEIN_PUSH_TOKEN&status=down&msg=backup+fehlgeschlagen"
Parameter: status=down oder fail für eine Störung, msg bzw. message für eine Meldung (bis 500 Zeichen). Die Antwort ist OK. Höchstens 60 Pushes pro Minute je Token; Pushes zählen gegen das Tageskontingent. Mehr unter Push-Checks.
Benachrichtigungskanäle
| Methode und Pfad | Wirkung |
|---|---|
GET /hc2/channel-types | alle Kanaltypen mit ihren Feldern (key, label, kind, required, secret, options, default) und needs_verification |
GET /hc2/channels, GET /hc2/channels/{id} | Kanäle; Geheimnisse fehlen in config, secrets_set nennt die gesetzten |
POST /hc2/channels | Kanal anlegen: type, name, config, enabled (Standard true), default (Standard false), lang (de/en), notify_down, notify_up → 201, bei E-Mail/SMS mit verification_required: true |
PATCH /hc2/channels/{id} | ändern; weggelassene Geheimnisse bleiben. Bei Kanälen einer Node nur Name und Schalter (config → 409 node_channel) |
DELETE /hc2/channels/{id} | löschen und aus allen Checks entfernen → 204 |
POST /hc2/channels/{id}/test | Testnachricht → {"sent": true, "queued_at_node": false}; nur bestätigte Kanäle |
POST /hc2/channels/{id}/verify/send | Bestätigungscode an E-Mail bzw. Handynummer senden (gilt 15 Minuten) |
POST /hc2/channels/{id}/verify | mit {"code": "123456"} bestätigen; falsch oder abgelaufen: 422 invalid_code |
POST /hc2/channels/{id}/send | eigene Nachricht über einen bestätigten, aktiven Kanal ipv64_mail, ipv64_sms oder app: subject, text (Pflicht), optional kind, event_id, source |
Kanaltypen und ihre config-Schlüssel: ipv64_mail (email), ipv64_sms (number), app (device_key, critical), telegram (bot_token, chat_id, silent), discord (webhook_url, username), slack und teams (webhook_url), matrix (server, token, room), ntfy (server, topic, token, user, password, priority_down, priority_up), gotify (server, app_token, priority), pushover (user_key, app_token, device, priority_down, priority_up), webhook (url, method, headers, body, insecure_tls), smtp (host, port, security, user, password, from, to). Bedeutung und Standardwerte: Kanaltypen. URLs und der SMTP-Host müssen öffentlich sein, SMTP nur über Port 25, 465, 587 oder 2525; sonst 422 invalid_channel mit den Meldungen in errors. Interne Ziele gehen nur über einen Kanal der Node.
curl -X POST "https://ipv64.net/api/v2/hc2/channels" -H "Authorization: Bearer DEIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "ntfy", "name": "ntfy Handy", "default": true, "config": {"server": "https://ntfy.sh", "topic": "mein-geheimes-topic"}}'
Bei /send wird eine event_id, die in den letzten 24 Stunden schon erfolgreich verschickt wurde, nicht erneut gesendet (Antwort duplicate: true). Die Antwort nennt bei SMS in sms_left, wie viele SMS heute noch gehen (null = unbegrenzt).
Wartungsfenster
| Methode und Pfad | Wirkung |
|---|---|
GET /hc2/maintenance, GET /hc2/maintenance/{id} | Wartungsfenster |
POST /hc2/maintenance | anlegen → 201 |
PATCH /hc2/maintenance/{id} | ändern |
DELETE /hc2/maintenance/{id} | löschen → 204 |
Felder: name, start_at und end_at (ISO 8601, Pflicht, Ende nach Beginn), repeat (none, daily, weekly, monthly), repeat_until, tokens (Liste von Check-Tokens, leer = alle Checks) und active (Standard true).
curl -X POST "https://ipv64.net/api/v2/hc2/maintenance" -H "Authorization: Bearer DEIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Proxmox-Updates", "start_at": "2026-11-01T03:00:00+01:00", "end_at": "2026-11-01T04:00:00+01:00", "repeat": "weekly"}'
Nodes
| Methode und Pfad | Wirkung |
|---|---|
GET /hc2/nodes | Nodes mit Healthchecks-Sync: node_id, name, location, version, timezone, modules, remote_mgmt, online, last_seen, last_sync, outbox_size, conflicts, linked_at |
GET /hc2/nodes/{node_id} | eine Node mit ihren lokalen und hybriden Checks |
PATCH /hc2/nodes/{node_id} | name, location, remote_mgmt (off, read, full) |
POST /hc2/nodes/link | Node per Code verknüpfen: code (8 Zeichen), optional location, remote_mgmt (Standard full) → 202; die Node holt ihren Zugang in etwa 10 Sekunden selbst. Unbekannter oder abgelaufener Code: 404 code_unknown |
DELETE /hc2/nodes/{node_id} | Healthchecks-Sync trennen; keep_checks im JSON-Body (Standard true) führt Checks nur dieser Node online weiter, soweit möglich → {"unlinked": true, "checks_kept_online": 2, "checks_deleted": 1} |
POST /hc2/nodes/{node_id}/commands | Befehl an die Node: name = run_check, pause, resume (je mit args.token), repair (Vollabgleich) oder resolve_conflict (args.id, args.keep = server/local) → 202 |
GET /hc2/nodes/{node_id}/commands | letzte Befehle (limit 1–200, Standard 20) mit done_at, ok, output |
GET /node64/nodes | die Node-Übersicht: alle Node64-Container des Kontos mit Modulen, Merkmalen (Healthchecks-Sync, Honeypot-Sensor, CDN64-Tunnel, DynDNS), Zustand des Syncs und removed |
Befehle nimmt die Node nur an, wenn ihre Fernverwaltung es erlaubt (siehe Fernverwaltung). Mit POST /node64/hello melden sich die Nodes selbst an; das brauchst du in eigenen Skripten nicht.
Fehler gefunden oder etwas fehlt? Schreibt uns im v64.tech-Forum. · Stand: 2026-11-04