Nodea — logo

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:write pokrywa tworzenie, aktualizację oraz akcje nienszczące (test, every-fail); alerting:delete obejmuje 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 422 z 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: slackslack_webhook_url, mailemail_address, discorddiscord_webhook_url, ms_teamswebhook_url, google_chatgoogle_webhook_url, webhookwebhook_url, pagerdutyintegration_key, opsgenieapi_key (plus opcjonalny region: us|eu), smsphone_number (E.164), telegramchat_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żkaScopeOpis
GET/integrationsalerting:readLista integracji (filtry: type, search; sort, paginacja).
GET/integrations/{integration}alerting:readPojedyncza integracja.
POST/integrationsalerting:writeUtworzenie integracji.
PATCH / PUT/integrations/{integration}alerting:writeCzęściowa aktualizacja (typ niezmienny, Telegram odrzucany).
DELETE/integrations/{integration}alerting:deleteTrwałe usunięcie (204 No Content).
POST/integrations/{integration}/testalerting:writeWysłanie testowego powiadomienia.
POST/integrations/{integration}/every-failalerting:writePrzełą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 (lub missing_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.

NazwaScopeTrybOpis
integrations-listalerting:readread-onlyLista integracji użytkownika (filtr type, search, paginacja).
integration-getalerting:readread-onlyPojedyncza integracja po id.
integration-createalerting:writezapisUtworzenie integracji (Telegram niedozwolony).
integration-updatealerting:writezapisCzęściowa aktualizacja (typ niezmienny, Telegram niedozwolony).
integration-testalerting:writezapisWysłanie testowego powiadomienia.
integration-set-every-failalerting:writezapisPrzełączenie flagi every_fail.
integration-deletealerting:deletedestrukcyjnyTrwał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 }
  }
}