Polityki eskalacji — API v1 i MCP | Nodea
Polityka eskalacji to uporządkowana lista kroków, które decydują, kogo i po jakim opóźnieniu powiadamiamy w trakcie incydentu. Każdy krok wskazuje jeden cel powiadomienia — grupę powiadomień albo integrację — oraz opóźnienie liczone od otwarcia incydentu. Ten dokument opisuje operacje REST API v1 oraz komplet narzędzi MCP do zarządzania politykami.
Wszystkie endpointy działają pod ścieżką bazową https://app.nodea.io/api/v1. Uwierzytelnianie odbywa się osobistym tokenem Passport przekazywanym w nagłówku Authorization: Bearer <token>. Obowiązuje limit throttle:api-v1 = 240 żądań na minutę. Polityki eskalacji wymagają włączonego modułu Strony WWW (flaga Pennant websites) — trasy jadą pod tą samą flagą co monitoring stron, nie mają własnej.
Dostęp jest zawężony do właściciela: obcy lub nieznany identyfikator zawsze zwraca 404 (nie 403), aby API nie potwierdzało istnienia cudzego zasobu. Scope'y OAuth: odczyt wymaga alerting:read, zapis alerting:write, usuwanie alerting:delete.
API v1
| Metoda | Ścieżka | Scope | Opis |
|---|---|---|---|
| GET | /escalation-policies | alerting:read | Lista polityk właściciela (paginacja, wyszukiwanie, sortowanie). |
| GET | /escalation-policies/{escalationPolicy} | alerting:read | Pojedyncza polityka z krokami w kolejności pozycji. |
| POST | /escalation-policies | alerting:write | Utworzenie polityki z listą kroków (zwraca 201). |
| PATCH / PUT | /escalation-policies/{escalationPolicy} | alerting:write | Aktualizacja nazwy i/lub całego łańcucha kroków. |
| DELETE | /escalation-policies/{escalationPolicy} | alerting:delete | Trwałe usunięcie polityki i jej kroków (zwraca 204). |
Obiekt kroku (steps[]) i reguła XOR
Pole steps to tablica kroków. Każdy krok zawiera:
delay_minutes— liczba całkowita0–1440. Opóźnienie liczone od otwarcia incydentu (a nie od poprzedniego kroku), po którym ten krok się uruchamia. Wartość0oznacza natychmiastowe powiadomienie.notification_group_id— albo identyfikator Twojej grupy powiadomień (rozgłasza do wszystkich integracji w grupie).integration_id— albo identyfikator pojedynczej Twojej integracji.
Reguła XOR: każdy krok musi wskazywać dokładnie jeden z celów — notification_group_id LUB integration_id. Egzekwują to dwie warstwy walidacji:
- Przypadek brak celu (żaden z dwóch) — reguła
required_withoutna obu polach zwraca422. - Przypadek oba cele naraz — dodatkowy hook
withValidatordokłada błąd do kluczasteps.{index}i zwraca422z komunikatem, że krok ma wskazywać jeden cel, nie oba.
Cel każdego kroku musi należeć do właściciela tokenu. Regułą Rule::exists(...)->where('user_id', ...) obcy identyfikator grupy lub integracji również zwraca 422 (a nie 404) — dzięki temu eskalacja nie może przejść przez poświadczenia innego najemcy.
Pozycja i kolejność
Pole position nie jest przyjmowane w żądaniu — kolejność w tablicy steps staje się 0-based position (pierwszy element = 0, drugi = 1, …). To ta kolejność wyznacza łańcuch eskalacji. W odpowiedzi kroki są zawsze zwracane posortowane po position.
Kształt odpowiedzi
Zasób EscalationPolicyResource zwraca politykę z zagnieżdżonymi krokami:
{
"data": {
"id": 42,
"name": "Krytyczne API produkcyjne",
"steps": [
{
"id": 101,
"position": 0,
"delay_minutes": 0,
"notification_group_id": 7,
"integration_id": null
},
{
"id": 102,
"position": 1,
"delay_minutes": 15,
"notification_group_id": null,
"integration_id": 3
}
],
"steps_count": 2,
"created_at": "2026-07-15T09:00:00+00:00",
"updated_at": "2026-07-15T09:00:00+00:00"
}
}W każdym kroku dokładnie jedno z pól notification_group_id / integration_id jest wypełnione, drugie to null. Pole steps_count pojawia się, gdy kontroler doliczył relację.
GET /escalation-policies — parametry listy
Obsługiwane parametry zapytania: search (fraza w nazwie, max 255), sort (whitelista: name, created_at), direction (asc / desc), per_page (1–100, domyślnie 20), page. Domyślne sortowanie: alfabetycznie po name.
curl -s "https://app.nodea.io/api/v1/escalation-policies?search=API&sort=name&per_page=20" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"POST /escalation-policies — utworzenie z krokami
curl -s -X POST "https://app.nodea.io/api/v1/escalation-policies" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Krytyczne API produkcyjne",
"steps": [
{ "delay_minutes": 0, "notification_group_id": 7 },
{ "delay_minutes": 15, "integration_id": 3 }
]
}'Pierwszy krok (pozycja 0) rozgłasza natychmiast do grupy 7; drugi (pozycja 1) po 15 minutach uderza w integrację 3. Odpowiedź: 201 Created z pełnym zasobem.
PATCH /escalation-policies/{id} — aktualizacja
Aktualizacja jest częściowa: name i steps są opcjonalne. Nazwa zmienia się tylko, gdy wysłano klucz name. Lista steps ma semantykę zastąpienia całości — kontroler usuwa dotychczasowe kroki i odtwarza je z przesłanej tablicy w jej kolejności, ale tylko wtedy, gdy klucz steps był obecny. Pominięcie steps zachowuje istniejący łańcuch.
# Zmiana samej nazwy (kroki bez zmian)
curl -s -X PATCH "https://app.nodea.io/api/v1/escalation-policies/42" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "Krytyczne API — nowa nazwa" }'DELETE /escalation-policies/{id}
Trwałe usunięcie polityki i jej kroków, zwraca 204 No Content. Strony przypięte do polityki nie blokują usunięcia — ich klucz websites.escalation_policy_id jest zerowany przez bazę (nullOnDelete) i wracają do domyślnego zachowania „powiadom wszystkie kanały przy pierwszej awarii".
curl -s -X DELETE "https://app.nodea.io/api/v1/escalation-policies/42" \
-H "Authorization: Bearer $TOKEN"Kody błędów
| Kod | Znaczenie |
|---|---|
401 | Brak lub nieważny token Bearer. |
403 | Token bez wymaganego scope'u (alerting:read / write / delete) lub wyłączony moduł websites. |
404 | Polityka nie istnieje lub należy do innego użytkownika. |
422 | Błąd walidacji: brak name/steps, delay_minutes poza 0–1440, naruszenie reguły XOR (żaden lub oba cele), albo cel spoza własnych grup/integracji. |
MCP
Te same operacje udostępnia 5 narzędzi MCP. Egzekwują identyczne scope'y i wymagają modułu websites. W narzędziach identyfikatory polityk są przekazywane jako łańcuch znaków. Narzędzie usuwające jest oznaczone jako destrukcyjne i wymaga jawnego confirm: true.
| Nazwa | Scope | Tryb | Opis |
|---|---|---|---|
escalation-policies-list | alerting:read | tylko odczyt | Paginowana lista polityk z krokami; parametry search, page, per_page (max 50). |
escalation-policy-get | alerting:read | tylko odczyt | Jedna polityka z krokami po id; dokłada nazwy grup i integracji. |
escalation-policy-create | alerting:write | zapis | Utworzenie polityki z name i steps (kolejność = kolejność eskalacji). |
escalation-policy-update | alerting:write | zapis (idempotentny) | Aktualizacja name i/lub steps; podane steps zastępują cały łańcuch. |
escalation-policy-delete | alerting:delete | destrukcyjny | Trwałe usunięcie; wymaga confirm: true. |
Przekazywanie kroków
W narzędziach escalation-policy-create i escalation-policy-update parametr steps to tablica obiektów o polach delay_minutes (0–1440), notification_group_id oraz integration_id — z tą samą regułą XOR (dokładnie jeden cel na krok). Kolejność elementów staje się position. Cele spoza własnych grup/integracji są odrzucane (jeden obcy identyfikator przerywa całą operację).
tools/call — utworzenie
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "escalation-policy-create",
"arguments": {
"name": "Krytyczne API produkcyjne",
"steps": [
{ "delay_minutes": 0, "notification_group_id": 7 },
{ "delay_minutes": 15, "integration_id": 3 }
]
}
}
}tools/call — usunięcie (z potwierdzeniem)
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "escalation-policy-delete",
"arguments": {
"id": "42",
"confirm": true
}
}
}Bez confirm: true narzędzie zwraca błąd „Deletion requires confirm: true." i nie kasuje niczego. Po sukcesie zwraca { "deleted": true, "id": "42" }. Narzędzia zwracają dane w formie ustrukturyzowanej — polityka z krokami w kolejności pozycji, wraz z nazwami grup (notification_group_name) i integracji (integration_name).
