/v1/account/webhook-endpoints

account/webhook-endpoints

Webhooki: dokąd Monitoring wysyła nowe Signals i jak je weryfikujesz.

Koszty i limity

Koszty i limity
Co Kredyty
Zarządzanie endpointami webhooków i dostarczeniami bezpłatnie

Limit: 30 zapytań na minutę. Tworzenie, zmiana i usuwanie: 10 na minutę. Sprawdzenie, test i nowy secret: 6 na minutę.

Token admina lub klucz API

Endpointy

Metoda
Metoda Ścieżka Cel Dostęp
GET /v1/account/webhook-endpoints Wszystkie endpointy webhooków, bez zarchiwizowanych. Klucz API lub token admina
POST /v1/account/webhook-endpoints Utwórz endpoint webhooka. Token admina
POST /v1/account/webhook-endpoints/{id}/verify Zweryfikuj. Klucz API lub token admina
POST /v1/account/webhook-endpoints/{id}/test Wyślij wiadomość testową. Klucz API lub token admina
POST /v1/account/webhook-endpoints/{id}/rotate-secret Nowy secret do podpisów. Token admina
POST /v1/account/webhook-endpoints/{id}/enable Włącz. Token admina
POST /v1/account/webhook-endpoints/{id}/disable Wyłącz. Token admina
DELETE /v1/account/webhook-endpoints/{id} Zarchiwizuj. Token admina
GET /v1/account/webhook-deliveries Ostatnie 50 dostarczeń. Klucz API lub token admina
POST /v1/account/webhook-deliveries/{id}/retry Wyślij ponownie nieudane dostarczenie. Klucz API lub token admina
GET /v1/account/webhook-events Ostatnie 50 zdarzeń. Klucz API lub token admina

Utwórz endpoint webhooka

curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints" \
  -H "Authorization: Bearer TWOJ_TOKEN_ADMINA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM-Sync",
    "url": "https://hooks.example.com/handelsregister",
    "headers": {
        "X-Receiver-Token": "TWOJ_TOKEN_ODBIORCY"
    }
}'
Parametry
Nazwa Typ Opis Przykład
Idempotency-KeyHeader stringwymagany Unikalna wartość na operację, najlepiej UUID. Zobacz Idempotency-Key.Granice: od 1 do 128 znaków req-20260802-01
nameBody stringwymagany Nazwa na twój własny użytek.Granice: od 1 do 120 znaków CRM-Sync
urlBody string (uri)wymagany Adres twojego serwera: publicznie dostępny, https na porcie 443, z nazwą hosta zamiast adresu IP.Granice: od 1 do 2 048 znaków https://hooks.example.com/handelsregister
headersBody obiektopcjonalny Własne nagłówki wysyłane z każdą wiadomością, np. token dla twojego serwera.Granice: najwyżej 10 pozycji {"X-Receiver-Token":"TWOJ_TOKEN_ODBIORCY"}
1{2  "endpoint": {3    "id": "wep_01m6b3j1g0cdz98hw8zdefbf52",4    "name": "CRM-Sync",5    "url": "hooks.example.com/…",6    "status": "pending_verification",7    "verified_at": null,8    "header_names": [9      "X-Receiver-Token"10    ],11    "consecutive_failures": 0,12    "created_at": "2026-11-01T08:28:01+00:00"13  },14  "signing_secret": "whsec_…",15  "meta": {16    "message": "Endpoint created. Store the signing secret now — it is shown only once.",17    "request_credit_cost": 0,18    "credits_remaining": 14519  }20}
201 · Przykładowa odpowiedź: nowy endpoint webhooka, secret tu skrócony

Weryfikacja

1{2  "id": "msg_01m6b3jsqq7ntwzkdj099ayraz",3  "type": "endpoint.verification",4  "timestamp": "2026-11-01T08:28:26.743Z",5  "schema_version": 1,6  "data": {7    "challenge": "189fb34b2af819bb13cb47d9806dbf30"8  }9}
Wiadomość, którą twój serwer dostaje podczas weryfikacji
curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints/wep_01m6b3j1g0cdz98hw8zdefbf52/verify" \
  -H "x-api-key: TWOJ_KLUCZ_API" \
  -H "Idempotency-Key: $(uuidgen)"
1{2  "verified": true,3  "endpoint": {4    "id": "wep_01m6b3j1g0cdz98hw8zdefbf52",5    "name": "CRM-Sync",6    "url": "hooks.example.com/…",7    "status": "active",8    "verified_at": "2026-11-01T08:28:26+00:00",9    "header_names": [10      "X-Receiver-Token"11    ],12    "consecutive_failures": 0,13    "created_at": "2026-11-01T08:28:01+00:00"14  },15  "meta": {16    "request_credit_cost": 0,17    "credits_remaining": 14518  }19}
200 · Przykładowa odpowiedź na udaną weryfikację
1{2  "delivery": {3    "id": "del_01m6b3jsyrnc3sz1mt31dq6107",4    "message_id": "msg_01m6b3jsynxzhvagm7n2nq7mpv",5    "event_id": "evt_01m6b3jsynxzhvagm7n2nq7mpt",6    "event_type": "endpoint.test",7    "endpoint_id": "wep_01m6b3j1g0cdz98hw8zdefbf52",8    "status": "succeeded",9    "attempts": 1,10    "last_status_code": 200,11    "last_error_category": null,12    "next_attempt_at": "2026-11-01T08:28:26+00:00",13    "succeeded_at": "2026-11-01T08:28:26+00:00",14    "created_at": "2026-11-01T08:28:26+00:00"15  },16  "meta": {17    "request_credit_cost": 0,18    "credits_remaining": 14519  }20}
200 · Przykładowa odpowiedź na wiadomość testową

Weryfikacja podpisu

Nagłówek
Nagłówek Znaczenie
webhook-id ID wiadomości (msg_…). Pozostaje takie samo przy ponowieniach. Użyj go do wykrywania duplikatów.
webhook-timestamp Czas tej próby dostarczenia w sekundach Unix.
webhook-signature Jeden lub więcej podpisów w formie v1,<Base64>, rozdzielonych spacjami.
import base64, hashlib, hmac, time

def verify_webhook(secret: str, headers: dict, body: bytes) -> bool:
    msg_id = headers["webhook-id"]
    timestamp = headers["webhook-timestamp"]
    # Odrzucaj wiadomości starsze niż pięć minut
    if abs(time.time() - int(timestamp)) > 300:
        return False
    key = base64.b64decode(secret.removeprefix("whsec_"))
    signed = f"{msg_id}.{timestamp}.".encode() + body
    expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()
    # Podczas rotacji secretu w nagłówku są dwa podpisy
    for part in headers["webhook-signature"].split(" "):
        version, _, signature = part.partition(",")
        if version == "v1" and hmac.compare_digest(signature, expected):
            return True
    return False

Payload

Pole
Pole Znaczenie
id ID wiadomości, równe nagłówkowi webhook-id.
event_id ID zdarzenia (evt_…).
type Typ zdarzenia, zobacz niżej.
timestamp Kiedy wykryliśmy zdarzenie, w UTC.
schema_version Wersja struktury, obecnie 1.
data Dane zdarzenia.
Typy zdarzeń
Typ zdarzenia Znaczenie
organization.signal.detected Monitor znalazł nowy sygnał. data.signal ma tę samą strukturę co sygnał w signals, plus data.monitor i, pod data.links.signal, link do sygnału w API.
organization.signal.sample Przykład z prawdziwej historii firmy, wysłany w Konto › Monitoring. Ta sama struktura co wyżej, plus data.sample: true.
endpoint.test Wiadomość testowa przez /test.
endpoint.verification Challenge podczas weryfikacji.
1{2  "id": "msg_01m65pqg9x0176cteqvtxw68sa",3  "event_id": "evt_01m65pqg9sx7mwmw0edc1mfbbe",4  "type": "organization.signal.sample",5  "timestamp": "2026-10-30T06:07:37.000Z",6  "schema_version": 1,7  "data": {8    "monitor": {9      "id": "mon_01m65pn3vm11sjjp1j076cbvec",10      "type": "organization.signals"11    },12    "sample": true,13    "signal": {14      "event": {15        "id": "36c7c8fddf99bb0299d6815bcaa01013",16        "topic": "TRANSFORMATIONS",17        "topic_name": {18          "de": "Umwandlungen & M&A",19          "en": "Transformations & M&A"20        },21        "occurred_on": "2022-12-22",22        "announced_on": "2023-08-10",23        "date_basis": "SOURCE_EVENT"24      },25      "organization": {26        "type": "ORGANIZATION",27        "entity_id": "94eb910fef13f94585c48c263fa446d4",28        "current_profile": {29          "name": "Hetzner Online GmbH",30          "registration": {31            "register_type": "HRB",32            "register_number": "6089",33            "court": "Ansbach",34            "register_locality": "Ansbach",35            "registration_authority_id": "D3201",36            "register_entity_name": "Ansbach HRB 6089"37          },38          "legal_form": {39            "name": {40              "de": "Gesellschaft mit beschränkter Haftung"41            },42            "short": {43              "de": "GmbH"44            }45          },46          "seat": {47            "city": "Gunzenhausen"48          },49          "status": {50            "code": "ACTIVE"51          }52        }53      },54      "parties": {55        "counterparty": {56          "entity": {57            "type": "ORGANIZATION",58            "entity_id": "dd4d2d6854b2dbd1ffce74e669f3852e",59            "current_profile": {60              "name": "Headtrip GmbH",61              "registration": {62                "register_type": "HRB",63                "register_number": "33432",64                "court": "Nürnberg",65                "register_locality": "Nuremberg",66                "registration_authority_id": "D3310",67                "register_entity_name": "Nürnberg HRB 33432"68              },69              "legal_form": {70                "name": {71                  "de": "Gesellschaft mit beschränkter Haftung"72                },73                "short": {74                  "de": "GmbH"75                }76              },77              "seat": {78                "city": "Nürnberg"79              },80              "status": {81                "code": "INACTIVE"82              }83            }84          },85          "relationship": "TRANSFERRING_COMPANY"86        }87      },88      "register_entry": {89        "entry_number": "3",90        "entry_date": "2023-08-10",91        "description_text": "Verschmelzung zur Aufnahme der Headtrip GmbH",92        "context": "PRIMARY",93        "flags": []94      },95      "source": {96        "kind": "COMMERCIAL_REGISTER"97      },98      "details": {99        "schema": "TRANSFORMATION",100        "kind": "MERGER",101        "specifics": {102          "merger_target": "ABSORPTION"103        },104        "direction": "INCOMING",105        "is_cross_border": false,106        "resolution_date": "2022-12-22",107        "agreement_date": "2022-12-22"108      }109    },110    "links": {111      "signal": "https://handelsregister.ai/api/v1/signals/36c7c8fddf99bb0299d6815bcaa01013"112    }113  }114}
Przykładowa wiadomość dla Hetzner Online GmbH, Ansbach HRB 6089: połączenie z Headtrip GmbH, Nürnberg HRB 33432, wysłane jako przykład z historii

Dostarczenia i ponowienia

Każdą wiadomość dostarczamy co najmniej raz, ale nie w stałej kolejności. Wykrywaj duplikaty po webhook-id. Odpowiadaj szybko i przetwarzaj wiadomość dopiero potem.
Status dostarczenia
Status Znaczenie
withheld Czeka, aż sprawdzenie zostanie naliczone.
pending Czeka na wysłanie.
in_flight Właśnie wysyłane.
retry_wait Czeka na następną próbę.
succeeded Dostarczone.
exhausted Wszystkie próby się nie udały.
blocked_endpoint Endpoint webhooka nie może w tej chwili niczego odebrać.
cancelled Anulowane, np. bo wiadomość wygasła.

Włącz, wyłącz, zarchiwizuj

curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints/wep_01m6b3j1g0cdz98hw8zdefbf52/disable" \
  -H "Authorization: Bearer TWOJ_TOKEN_ADMINA" \
  -H "Idempotency-Key: $(uuidgen)"

Błędy

Błędy
Status Przyczyna Co możesz zrobić
400 api_key jest w URL. Wysyłaj klucz w nagłówku x-api-key.
400 URL nie jest dozwolony jako cel, nagłówek jest niedozwolony, osiągnięto maksymalną liczbę albo endpoint webhooka nie jest aktywny. meta.message podaje powód. Popraw wartość lub najpierw zweryfikuj.
400 Idempotency-Key ma nieprawidłowy format. Popraw format, np. użyj UUID.
401 Brak klucza API lub tokenu albo są nieprawidłowe. Wysyłaj klucz w nagłówku x-api-key.
403 Bearer tokenowi brakuje uprawnienia account:read. Użyj klucza API lub tokenu z account:read.
403 Adres e-mail twojego konta nie jest jeszcze potwierdzony albo konto jest zablokowane. Otwórz link z e-maila potwierdzającego. Jeśli konto jest zablokowane, pomoże support.
403 To wywołanie wymaga tokenu admina. Klucz API nie wystarcza, inny token też nie. Wyślij go z Authorization: Bearer i tokenem admina.
403 Bearer tokenowi brakuje uprawnienia monitoring:manage. Użyj klucza API lub tokenu admina.
404 Brak endpointu webhooka lub dostarczenia o tym ID. Sprawdź ID.
409 Idempotency-Key był już użyty z innymi danymi, jest starszy niż 24 godziny lub jest jeszcze przetwarzany. Użyj nowego klucza lub odczekaj chwilę.
422 Brakuje wartości lub jest nieprawidłowa, np. name lub url. errors wskazuje pole. Popraw wartość i spróbuj ponownie z nowym kluczem.
422 Weryfikacja się nie udała. Sprawdź nagłówek challenge i status 2xx, potem spróbuj ponownie z nowym kluczem.
428 Brakuje nagłówka Idempotency-Key. Wyślij nagłówek.
429 Za dużo zapytań. Spróbuj ponownie po Retry-After.
503 Weryfikacja, testy i ponowne wysyłanie są chwilowo niedostępne. Spróbuj ponownie nieco później.
1{2  "error": "invalid_request",3  "meta": {4    "message": "The endpoint is not active.",5    "request_credit_cost": 0,6    "credits_remaining": 1457  }8}
400 · Endpoint webhooka, który nie jest jeszcze zweryfikowany, nie może odebrać wiadomości testowej