Skip to content
cronitorex.com

Management API

Twórz, odczytuj i aktualizuj monitory ze skryptów, pipeline’ów CI i narzędzi infrastructure-as-code. API używa tego samego formatu manifestu, który eksportujesz i importujesz w panelu, więc manifest pobrany z panelu działa jako payload API i odwrotnie.

Adres bazowy i autoryzacja

https://app.cronitorex.com/api/v1
Authorization: Bearer <api_key>

Management API używa własnego klucza (prefiks mk_), osobnego od klucza Ingest API służącego do pingów. Wygenerujesz go w panelu w Ustawienia → Klucz API (sekcja Klucz Management API). Wszystkie żądania i odpowiedzi są w formacie application/json. Komunikaty błędów są zawsze po angielsku.

Limit żądań

60 żądań na minutę na klucz API. Po przekroczeniu limitu API zwraca 429 Too Many Requests. Każda odpowiedź zawiera nagłówki X-RateLimit-Limit i X-RateLimit-Remaining.

Format manifestu

Każdy monitor jest opisany manifestem z manifest_version: 1 i jednym z trzech rodzajów:

RodzajCo monitoruje
pingZadanie cron lub zaplanowany task wysyłający pingi
http_checkEndpoint HTTP sprawdzany według harmonogramu
ssl_checkCertyfikat SSL sprawdzany pod kątem wygaśnięcia

Monitor ping

{
"manifest_version": 1,
"kind": "ping",
"name": "db-backup",
"enabled": true,
"timeout_seconds": 60,
"expected_interval_seconds": 86400,
"grace_seconds": 300,
"tags": ["prod", "backup"]
}

Pole name to slug, do którego pingujesz (a-zA-Z0-9_-, maks. 64 znaki) i po utworzeniu jest niezmienne. expected_interval_seconds i grace_seconds są opcjonalne.

Check HTTP

{
"manifest_version": 1,
"kind": "http_check",
"name": "Website health",
"enabled": true,
"schedule": "*/5 * * * *",
"tags": ["prod"],
"config": {
"url": "https://example.com/health",
"method": "GET",
"timeout": 30,
"expected_status": 200,
"expected_content": ""
}
}

schedule przyjmuje albo standardowe 5-polowe wyrażenie cron (*/5 * * * *), albo skrócony interwał (30s, 5m, 1h, 1d, 7d). Co najmniej jedno z pól expected_status lub expected_content musi być ustawione.

Check SSL

{
"manifest_version": 1,
"kind": "ssl_check",
"name": "example.com certificate",
"enabled": true,
"schedule": "0 6 * * *",
"config": {
"domain": "example.com",
"warning_days": 30,
"alert_days": 7
}
}

Endpointy

Odpowiedzi API dodają do manifestu pole uuid (tylko do odczytu). uuid wysłany w body żądania jest ignorowany.

Lista monitorów

Okno terminala
curl -H "Authorization: Bearer $API_KEY" \
https://app.cronitorex.com/api/v1/monitors

Opcjonalny filtr: ?kind=ping, ?kind=http_check lub ?kind=ssl_check.

{
"monitors": [
{ "uuid": "3b0043f4-...", "manifest_version": 1, "kind": "ping", "name": "db-backup", ... }
]
}

Pobranie monitora

Okno terminala
curl -H "Authorization: Bearer $API_KEY" \
https://app.cronitorex.com/api/v1/monitors/<uuid>

Zwraca manifest z uuid. Nieznany uuid zwraca 404.

Utworzenie monitora

Okno terminala
curl -X POST \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"manifest_version":1,"kind":"ping","name":"db-backup","timeout_seconds":60}' \
https://app.cronitorex.com/api/v1/monitors

Zwraca 201 Created z zapisanym manifestem wraz z jego uuid. Zduplikowane nazwy i przekroczony limit planu są odrzucane z kodem 422.

Aktualizacja monitora

Okno terminala
curl -X PUT \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"manifest_version":1,"kind":"ping","name":"db-backup","timeout_seconds":120}' \
https://app.cronitorex.com/api/v1/monitors/<uuid>

Wysyłaj pełny manifest, nie częściowy patch. Rodzaj (kind) musi zgadzać się z istniejącym monitorem, a nazwa monitora ping jest niezmienna; oba naruszenia zwracają 422.

Usunięcie monitora

Usunięcie jest nieodwracalne: skasowanie monitora ping usuwa też jego historię zdarzeń, oczekiwane wykonania i powiązane powiadomienia. Samo DELETE jest więc odrzucane z kodem 403 i linkiem do panelu, żeby literówka w skrypcie albo generyczny klient CRUD nie skasowały danych przypadkiem:

{
"message": "Deleting a monitor is irreversible. Repeat the request with ?confirm=true, or delete it from the web panel.",
"panel_url": "https://app.cronitorex.com/monitors/<uuid>/edit"
}

Dodaj ?confirm=true, żeby faktycznie usunąć. Odpowiedź to 204 No Content z pustym ciałem:

Okno terminala
curl -sS -X DELETE \
-H "Authorization: Bearer $CRONITOREX_MANAGEMENT_KEY" \
"https://app.cronitorex.com/api/v1/monitors/<uuid>?confirm=true"

Działa dla wszystkich trzech rodzajów. Przy http_check i ssl_check znika sam check i historia jego wykonań; przy monitorach ping zwalniana jest też nazwa, więc monitor utworzony później pod tą samą nazwą startuje z czystą historią.

Config as code

Zamiast sterować powyższymi endpointami monitor po monitorze, możesz trzymać całą konfigurację monitoringu w jednym pliku, wersjonować ją w repozytorium i jednym żądaniem doprowadzać konto do stanu z pliku.

Bundle to format manifestu opakowany w tablicę:

{
"manifest_version": 1,
"monitors": [
{ "manifest_version": 1, "kind": "ping", "name": "db-backup", "timeout_seconds": 60 },
{ "manifest_version": 1, "kind": "http_check", "name": "Website health", "schedule": "5m",
"config": { "url": "https://example.com/health", "expected_status": 200 } }
]
}

Monitory dopasowywane są po kind i name, nie po uuid, więc bundle jest przenośny między kontami i czytelny w pull requeście. Monitory ping i checki mają osobne przestrzenie nazw: ping o nazwie api i http_check o nazwie api to dwa różne monitory i nie kolidują ze sobą.

Eksport konta do bundle’a

Okno terminala
curl -H "Authorization: Bearer $CRONITOREX_MANAGEMENT_KEY" \
https://app.cronitorex.com/api/v1/monitors/export > monitors.json

Wynik to gotowy do zaaplikowania bundle bez pól uuid. To najszybszy sposób przejścia na config as code na koncie zbudowanym klikaniem w panelu: wyeksportuj raz, zacommituj plik i zarządzaj nim dalej z repozytorium.

Aplikowanie bundle’a

Okno terminala
curl -X POST \
-H "Authorization: Bearer $CRONITOREX_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
--data-binary @monitors.json \
"https://app.cronitorex.com/api/v1/monitors/apply?dry_run=true"

dry_run=true raportuje, co by się zmieniło, i nic nie zapisuje. Bez tego parametru zmiany są aplikowane. Oba tryby zwracają 200 i ten sam raport:

{
"dry_run": true,
"summary": { "create": 1, "update": 1, "unchanged": 5, "orphaned": 2 },
"changes": [
{ "name": "db-backup", "kind": "ping", "action": "update", "uuid": "3b0043f4-...",
"diff": { "grace_seconds": [300, 600] } },
{ "name": "etl-job", "kind": "ping", "action": "create" }
],
"orphaned": [
{ "name": "old-cleanup-job", "kind": "ping", "uuid": "9c1f77a2-..." }
]
}

Trzy własności, na których można polegać:

  • Apply nigdy nie usuwa. Monitory, które istnieją na koncie, ale nie ma ich w bundle’u, trafiają na listę orphaned i zostają nietknięte. Usunięcie monitora pozostaje świadomą decyzją: DELETE ?confirm=true albo panel.
  • Wszystko albo nic. Cały bundle jest najpierw walidowany. Jeśli którykolwiek wpis jest nieprawidłowy, żądanie zwraca 422 i nic nie zostaje zapisane, więc literówka w dziesiątym monitorze nie zostawi dziewięciu pierwszych zaaplikowanych w połowie.
  • Idempotencja. Zaaplikowanie niezmienionego bundle’a raportuje wszystko jako unchanged i nie wykonuje żadnych zapisów, więc można to uruchamiać przy każdym pushu.

Błędy raportowane są per pozycja w bundle’u:

{
"message": "The given data was invalid.",
"errors": {
"monitors.3": ["The \"schedule\" field must be a cron expression (5 fields) or an interval such as 5m, 1h, 1d."]
}
}

Przykład: synchronizacja monitorów z CI

Dry-run na pull requestach, żeby recenzenci widzieli różnicę, apply po merge’u:

- name: Check monitor changes
if: github.event_name == 'pull_request'
run: |
curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer ${{ secrets.CRONITOREX_MANAGEMENT_KEY }}" \
-H "Content-Type: application/json" \
--data-binary @monitors.json \
"https://app.cronitorex.com/api/v1/monitors/apply?dry_run=true"
- name: Apply monitors
if: github.ref == 'refs/heads/main'
run: |
curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer ${{ secrets.CRONITOREX_MANAGEMENT_KEY }}" \
-H "Content-Type: application/json" \
--data-binary @monitors.json \
https://app.cronitorex.com/api/v1/monitors/apply

Klient shell zamiast curla

Od wersji 1.3 klient obudowuje oba endpointy:

Okno terminala
cronitorex export -o monitors.json # pobranie konta jako bundle
cronitorex apply -f monitors.json --dry-run
cronitorex apply -f monitors.json

Klient czyta klucz zarządzający z CRONITOREX_MANAGEMENT_KEY, a w razie jego braku z ~/.cronitorex-management.conf (zapisywanego przez cronitorex configure --management-key, uprawnienia 600). Ten plik jest celowo oddzielony od ~/.cronitorex.conf: klucz ingest z natury leży na każdym monitorowanym serwerze i bywa rozsyłany narzędziami do zarządzania konfiguracją, a klucz zarządzający potrafi usunąć monitor razem z historią zdarzeń. Rozdzielenie ich sprawia, że dystrybucja konfiguracji ingest nigdy nie rozsiewa poświadczenia niszczącego.

Podanie klucza niewłaściwego rodzaju jest wykrywane przed wysłaniem żądania, więc dostajesz wyjaśnienie zamiast gołego 401. Kod wyjścia to 0 przy udanym apply i 1 przy dowolnym błędzie, czyli dokładnie to, czego potrzebuje CI.

Config as code jest domyślnie dostępny na każdym planie. Jeśli został dla Twojego planu wyłączony, apply zwraca 403 z linkiem do cennika; export działa niezależnie od tego.

Odpowiedzi błędów

StatusZnaczenie
401Brak lub nieprawidłowy klucz API
404Monitor nie istnieje (lub należy do innego konta)
422Nieprawidłowy manifest, zduplikowana nazwa, niezmienne pole lub osiągnięty limit planu
403DELETE bez ?confirm=true albo apply na planie bez config as code
429Przekroczony limit żądań

Błędy walidacji mają taki kształt:

{
"message": "A Ping monitor name is immutable. To use a different name, import the manifest as a new monitor.",
"errors": {
"manifest": ["A Ping monitor name is immutable. To use a different name, import the manifest as a new monitor."]
},
"error_codes": {
"manifest": ["name_immutable"]
}
}

Kody błędów do odczytu maszynowego

errors jest przeznaczone dla ludzi i jego treść zmienia się w czasie. Kod, który podejmuje decyzje, powinien czytać error_codes — mapę odpowiadającą errors klucz w klucz i pozycja w pozycję, ze stabilnymi identyfikatorami. Błędy o jednej przyczynie (na przykład powyższe 403) niosą zamiast tego płaskie pole code.

W bundle’ach klucz zawiera pozycję, zgodnie z formatem walidacji tablic w Laravelu:

{
"message": "The given data was invalid.",
"errors": { "monitors.3": ["The \"schedule\" field must be a cron expression (5 fields) or an interval such as 5m, 1h, 1d."] },
"error_codes": { "monitors.3": ["schedule_invalid"] }
}

Obecne kody: manifest_version_unsupported, invalid_json, kind_invalid, name_invalid, name_charset_invalid, timeout_out_of_range, interval_out_of_range, grace_out_of_range, schedule_invalid, domain_invalid, url_invalid, method_invalid, check_timeout_invalid, http_assertion_required, kind_mismatch, name_immutable, name_already_exists, name_taken_by_other_kind, plan_limit_reached, bundle_invalid, monitors_missing, entry_not_object, duplicate_entry, delete_requires_confirm, config_as_code_disabled.

Nowe kody będą dochodzić z czasem, a istniejące nigdy nie zmienią nazwy ani znaczenia — nierozpoznaną wartość traktuj więc jako błąd ogólny, zamiast odrzucać odpowiedź.

Opis API do odczytu maszynowego

Pełny opis OpenAPI 3 znajduje się pod docs.cronitorex.com/openapi.yaml i obejmuje zarówno Ingest API, jak i Management API. Wskaż go generatorowi, żeby dostać typowanego klienta w swoim języku. Dostępna jest też kolekcja Postmana.

Przykład: tworzenie monitora z CI

Krok GitHub Actions rejestrujący monitor po każdym deployu (idempotentny: odpowiedź 422 o duplikacie oznacza, że monitor już istnieje):

- name: Ensure deploy monitor exists
run: |
STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
-H "Authorization: Bearer ${{ secrets.CRONITOREX_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"manifest_version":1,"kind":"ping","name":"nightly-report","expected_interval_seconds":86400}' \
https://app.cronitorex.com/api/v1/monitors)
if [ "$STATUS" != "201" ] && [ "$STATUS" != "422" ]; then
echo "Unexpected status $STATUS"; exit 1
fi