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/v1Authorization: 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:
| Rodzaj | Co monitoruje |
|---|---|
ping | Zadanie cron lub zaplanowany task wysyłający pingi |
http_check | Endpoint HTTP sprawdzany według harmonogramu |
ssl_check | Certyfikat 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
curl -H "Authorization: Bearer $API_KEY" \ https://app.cronitorex.com/api/v1/monitorsOpcjonalny filtr: ?kind=ping, ?kind=http_check lub ?kind=ssl_check.
{ "monitors": [ { "uuid": "3b0043f4-...", "manifest_version": 1, "kind": "ping", "name": "db-backup", ... } ]}Pobranie monitora
curl -H "Authorization: Bearer $API_KEY" \ https://app.cronitorex.com/api/v1/monitors/<uuid>Zwraca manifest z uuid. Nieznany uuid zwraca 404.
Utworzenie monitora
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/monitorsZwraca 201 Created z zapisanym manifestem wraz z jego uuid. Zduplikowane nazwy i przekroczony limit planu są odrzucane z kodem 422.
Aktualizacja monitora
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:
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
curl -H "Authorization: Bearer $CRONITOREX_MANAGEMENT_KEY" \ https://app.cronitorex.com/api/v1/monitors/export > monitors.jsonWynik 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
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ę
orphanedi zostają nietknięte. Usunięcie monitora pozostaje świadomą decyzją:DELETE ?confirm=truealbo panel. - Wszystko albo nic. Cały bundle jest najpierw walidowany. Jeśli którykolwiek wpis jest nieprawidłowy, żądanie zwraca
422i 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
unchangedi 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/applyKlient shell zamiast curla
Od wersji 1.3 klient obudowuje oba endpointy:
cronitorex export -o monitors.json # pobranie konta jako bundlecronitorex apply -f monitors.json --dry-runcronitorex apply -f monitors.jsonKlient 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
| Status | Znaczenie |
|---|---|
401 | Brak lub nieprawidłowy klucz API |
404 | Monitor nie istnieje (lub należy do innego konta) |
422 | Nieprawidłowy manifest, zduplikowana nazwa, niezmienne pole lub osiągnięty limit planu |
403 | DELETE bez ?confirm=true albo apply na planie bez config as code |
429 | Przekroczony 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