Integracje powiadomień — API v1 i MCP | Nodea
Integracje to kanały powiadomień, przez które Nodea informuje o awariach monitorowanych zasobów: Slack, e-mail, Discord, MS Teams, Google Chat, generyczny webhook, PagerDuty, OpsGenie, SMS oraz Telegram. Każda integracja należy do jednego użytkownika i przechowuje poświadczenia (URL webhooka, klucz API, adres e-mail, numer telefonu). Ten dokument opisuje REST API v1 oraz serwer MCP, które pozwalają zarządzać integracjami programowo. Powiązane zasoby to grupy powiadomień oraz polityki eskalacji, które kierują alerty do tych kanałów.
Uwierzytelnianie i wymagania
Wszystkie endpointy działają pod prefiksem /api/v1 (pełny przykład hosta: https://app.nodea.io/api/v1). Uwierzytelnianie odbywa się osobistym tokenem dostępu Passport w nagłówku Authorization: Bearer <token>. Limit zapytań: throttle:api-v1 = 240 żądań na minutę.
- Scope'y: odczyt =
alerting:read, zapis =alerting:write, usuwanie =alerting:delete.alerting:writepokrywa tworzenie, aktualizację oraz akcje nienszczące (test, every-fail);alerting:deleteobejmuje wyłącznie usuwanie. - Flaga funkcji: trasy integracji wymagają włączonej flagi Pennant
integrations. - Zakres właściciela: integracja jest zawsze ograniczona do właściciela tokenu. Obcy lub nieznany identyfikator zwraca
404(nigdy nie potwierdza istnienia zasobu innego użytkownika). - Błędy walidacji → HTTP
422z ciałem{ "message": ..., "errors": { pole: [..] } }.
Typy integracji: slack, mail, telegram, discord, ms_teams, google_chat, webhook, pagerduty, opsgenie, sms. Każdy typ ma jeden kanoniczny klucz konfiguracji: slack → slack_webhook_url, mail → email_address, discord → discord_webhook_url, ms_teams → webhook_url, google_chat → google_webhook_url, webhook → webhook_url, pagerduty → integration_key, opsgenie → api_key (plus opcjonalny region: us|eu), sms → phone_number (E.164), telegram → chat_id + integration_code.
Telegram jest tylko dla interfejsu WWW. Konfiguracja Telegrama to interaktywny proces parowania bota (przekierowanie do telegram.me z jednorazowym integration_code), którego klient headless nie potrafi ukończyć. Dlatego tworzenie i edycja Telegrama przez API/MCP są odrzucane — obsługiwane są tylko odczyt, test i usunięcie.
Maskowanie sekretów — najważniejsza zasada
Poświadczenia NIGDY nie wracają w postaci jawnej. Każda odpowiedź (API i MCP) przechodzi przez IntegrationResource, które maskuje wszystkie klucze sekretów: slack_webhook_url, discord_webhook_url, webhook_url, google_webhook_url, integration_key, api_key, integration_code. Format maski: **** + ostatnie 4 znaki; sekrety o długości 8 znaków lub krótsze zwijają się do samego **** (maska nigdy nie ujawnia połowy krótkiego poświadczenia). Klucze routingowe pozostają czytelne: email_address, phone_number, chat_id (Telegram — bezużyteczny bez tokenu bota), region (wybór centrum danych OpsGenie).
Odesłanie zamaskowanej wartości przy aktualizacji = brak zmiany. Przy PATCH/PUT wartości sekretów, które przychodzą puste lub zamaskowane (zaczynają się od ****), są usuwane PRZED walidacją. Dzięki temu pobranie integracji i odesłanie jej z powrotem jest dla sekretu operacją pustą (zostaje zapisane oryginalne poświadczenie), a maska nigdy nie trafia na regułę url pola webhooka. Aby wymienić sekret, przekaż pełną nową wartość.
API v1
| Metoda | Ścieżka | Scope | Opis |
|---|---|---|---|
| GET | /integrations | alerting:read | Lista integracji (filtry: type, search; sort, paginacja). |
| GET | /integrations/{integration} | alerting:read | Pojedyncza integracja. |
| POST | /integrations | alerting:write | Utworzenie integracji. |
| PATCH / PUT | /integrations/{integration} | alerting:write | Częściowa aktualizacja (typ niezmienny, Telegram odrzucany). |
| DELETE | /integrations/{integration} | alerting:delete | Trwałe usunięcie (204 No Content). |
| POST | /integrations/{integration}/test | alerting:write | Wysłanie testowego powiadomienia. |
| POST | /integrations/{integration}/every-fail | alerting:write | Przełączenie flagi every_fail. |
Kształt odpowiedzi
Każdy zasób integracji zawiera pola: id, name, type, every_fail (bool), is_ready (bool — czy poświadczenia są gotowe do wysyłki), config (obiekt z zamaskowanymi sekretami), created_at, updated_at (ISO 8601).
GET /integrations — lista
Parametry zapytania: search (string, max 255 — dopasowanie po nazwie i typie), type (jeden z typów integracji), sort (name|type|created_at), direction (asc|desc), per_page (1–100, domyślnie 20), page. Odpowiedź jest paginowana (koperta data + meta/links).
curl -s https://app.nodea.io/api/v1/integrations?type=slack&per_page=20 \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"POST /integrations — utworzenie
Ciało: name (wymagane, max 100), type (wymagane; telegram odrzucany z 422), every_fail (opcjonalne, bool), oraz kanoniczny klucz konfiguracji dla wybranego typu (patrz tabela typów wyżej). Reguły konfiguracji są per-typ: URL-e webhooków muszą być poprawnymi, bezpiecznymi publicznymi adresami; email_address waliduje się przez email:rfc,dns; phone_number musi być w formacie E.164 (+ i 7–15 cyfr); integration_key/api_key mają min. 10 znaków.
Kody błędów tworzenia: 402 z { "code": "plan_limit_exceeded" } gdy plan wyczerpał limit integracji; 422 z { "code": "missing_config" } gdy brakuje wymaganego klucza konfiguracji dla wybranego typu. Sukces zwraca 201 Created z zamaskowanym zasobem.
curl -s -X POST https://app.nodea.io/api/v1/integrations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Ops Slack",
"type": "slack",
"every_fail": false,
"slack_webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX"
}'PATCH /integrations/{integration} — aktualizacja
Aktualizacja jest częściowa: pomijane pola pozostają bez zmian. type jest niezmienny (reguła prohibited — zmiana dostawcy osierociłaby zapisaną konfigurację; utwórz nową integrację). Integracje telegram są odrzucane z 422 i { "code": "telegram_not_supported" }. Zamaskowane lub puste sekrety są ignorowane (patrz sekcja Maskowanie sekretów).
curl -s -X PATCH https://app.nodea.io/api/v1/integrations/42 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "name": "Ops Slack (prod)", "every_fail": true }'POST /integrations/{integration}/test — test powiadomienia
Wysyła testowe powiadomienie tym samym serwisem, którego używa interfejs WWW. Obsługiwane typy: slack, mail, telegram, ms_teams, discord, google_chat. Pozostałe typy (webhook, pagerduty, opsgenie, sms) zwracają 422 z { "code": "test_not_supported" }.
Ochrona przed danymi seedera: jeśli integracja przechowuje poświadczenia zastępcze (słownictwo seedera), test zwraca 422 z { "code": "placeholder_credentials" } BEZ wysyłania czegokolwiek do zewnętrznego API. Gdy dostawca odrzuci wysyłkę (zły webhook, cofnięty token), zwracane jest 502 z { "code": "test_failed", "reason": ... }. Sukces: { "message": "Test notification sent." }.
curl -s -X POST https://app.nodea.io/api/v1/integrations/42/test \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json"POST /integrations/{integration}/every-fail — flaga every_fail
Ciało: enabled (wymagane, bool). true = powiadomienie przy KAŻDYM nieudanym teście; false = tylko przy zmianach stanu (awaria/przywrócenie). Zwraca zaktualizowany zasób.
curl -s -X POST https://app.nodea.io/api/v1/integrations/42/every-fail \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "enabled": true }'Kody błędów
401— brak lub nieprawidłowy token.403— token bez wymaganego scope'u.404— integracja nie istnieje lub należy do innego użytkownika.422— błąd walidacji (lubmissing_config,telegram_not_supported,placeholder_credentials,test_not_supported).402— przekroczony limit planu przy tworzeniu (plan_limit_exceeded).502— dostawca odrzucił test (test_failed).
MCP
Serwer MCP udostępnia 7 narzędzi do zarządzania integracjami. Wszystkie wymagają włączonej flagi integrations i odpowiedniego scope'u. Sekrety są maskowane identycznie jak w API. Narzędzia oznaczone jako destrukcyjne wymagają jawnego confirm: true.
| Nazwa | Scope | Tryb | Opis |
|---|---|---|---|
integrations-list | alerting:read | read-only | Lista integracji użytkownika (filtr type, search, paginacja). |
integration-get | alerting:read | read-only | Pojedyncza integracja po id. |
integration-create | alerting:write | zapis | Utworzenie integracji (Telegram niedozwolony). |
integration-update | alerting:write | zapis | Częściowa aktualizacja (typ niezmienny, Telegram niedozwolony). |
integration-test | alerting:write | zapis | Wysłanie testowego powiadomienia. |
integration-set-every-fail | alerting:write | zapis | Przełączenie flagi every_fail. |
integration-delete | alerting:delete | destrukcyjny | Trwałe usunięcie — wymaga confirm: true. |
integrations-list
Parametry: type (opcjonalny filtr typu), search (opcjonalny fragment nazwy), page (min 1), per_page (1–50, domyślnie 15). Zwraca data (zamaskowane integracje) + meta (paginacja).
{
"method": "tools/call",
"params": {
"name": "integrations-list",
"arguments": { "type": "slack", "per_page": 15 }
}
}integration-create
Parametry: name (wymagane), type (wymagane; Telegram wykluczony z enuma), config (wymagany obiekt z kluczem poświadczenia dla typu), every_fail (domyślnie false). Ten sam limit planu (create-integration) co w API.
{
"method": "tools/call",
"params": {
"name": "integration-create",
"arguments": {
"name": "Ops Slack",
"type": "slack",
"config": { "slack_webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX" }
}
}
}integration-update
Parametry: id (wymagane), oraz opcjonalnie name, config, every_fail. Przekazanie zamaskowanej wartości konfiguracji (****..., tak jak zwracają ją narzędzia odczytu) zachowuje zapisany sekret; przekaż pełną nową wartość, aby go wymienić.
{
"method": "tools/call",
"params": {
"name": "integration-update",
"arguments": {
"id": 42,
"config": { "slack_webhook_url": "****XXXX" },
"every_fail": true
}
}
}integration-test
Parametry: id (wymagane). Poświadczenia zastępcze (seeder) są odrzucane bez dotknięcia zewnętrznego API. Typy bez wysyłacza testu (webhook, pagerduty, opsgenie, sms) zwracają jawny błąd (inaczej niż interfejs WWW, który po cichu pokazuje sukces).
{
"method": "tools/call",
"params": { "name": "integration-test", "arguments": { "id": 42 } }
}integration-delete (destrukcyjne)
Parametry: id (wymagane) oraz confirm (wymagane, musi być true). Bez confirm: true usunięcie jest odrzucane, aby agent nie skasował integracji na luźno zinterpretowanej instrukcji. Grupy powiadomień i kroki eskalacji odwołujące się do niej tracą ten kanał. Operacja jest nieodwracalna.
{
"method": "tools/call",
"params": {
"name": "integration-delete",
"arguments": { "id": 42, "confirm": true }
}
}