/v1/account/webhook-endpoints

account/webhook-endpoints

Webhooks: hvor Monitoring sender nye Signals hen, og hvordan du verificerer dem.

Omkostninger og grænser

Omkostninger og grænser
Hvad Kreditter
Administrer webhook-endpoints og leveringer gratis

Grænse: 30 forespørgsler pr. minut. Opret, opdater og slet: 10 pr. minut. Tjek, test og ny secret: 6 pr. minut.

Admin-token eller API-nøgle

Endpoints

Metode
Metode Sti Formål Adgang
GET /v1/account/webhook-endpoints Alle webhook-endpoints, uden arkiverede. API-nøgle eller admin-token
POST /v1/account/webhook-endpoints Opret et webhook-endpoint. Admin-token
POST /v1/account/webhook-endpoints/{id}/verify Verificér. API-nøgle eller admin-token
POST /v1/account/webhook-endpoints/{id}/test Send en testbesked. API-nøgle eller admin-token
POST /v1/account/webhook-endpoints/{id}/rotate-secret Ny signeringssecret. Admin-token
POST /v1/account/webhook-endpoints/{id}/enable Aktivér. Admin-token
POST /v1/account/webhook-endpoints/{id}/disable Deaktivér. Admin-token
DELETE /v1/account/webhook-endpoints/{id} Arkivér. Admin-token
GET /v1/account/webhook-deliveries De seneste 50 leveringer. API-nøgle eller admin-token
POST /v1/account/webhook-deliveries/{id}/retry Send en mislykket levering igen. API-nøgle eller admin-token
GET /v1/account/webhook-events De seneste 50 hændelser. API-nøgle eller admin-token

Opret et webhook-endpoint

curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints" \
  -H "Authorization: Bearer DIN_ADMIN_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CRM-Sync",
    "url": "https://hooks.example.com/handelsregister",
    "headers": {
        "X-Receiver-Token": "DIN_MODTAGER_TOKEN"
    }
}'
Parametre
Navn Type Beskrivelse Eksempel
Idempotency-KeyHeader strengpåkrævet En entydig værdi pr. handling, helst et UUID. Se Idempotency-Key.Grænser: 1 til 128 tegn req-20260802-01
nameBody strengpåkrævet Et navn til din egen reference.Grænser: 1 til 120 tegn CRM-Sync
urlBody streng (uri)påkrævet Din servers adresse: offentligt tilgængelig, https på port 443, med et værtsnavn i stedet for en IP-adresse.Grænser: 1 til 2.048 tegn https://hooks.example.com/handelsregister
headersBody objektvalgfri Egne headers, der sendes med hver besked, f.eks. et token til din server.Grænser: højst 10 poster {"X-Receiver-Token":"DIN_MODTAGER_TOKEN"}
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 · Eksempelsvar: et nyt webhook-endpoint, secret forkortet her

Verificér

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}
Den besked, din server modtager under verificeringen
curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints/wep_01m6b3j1g0cdz98hw8zdefbf52/verify" \
  -H "x-api-key: DIN_API_NOEGLE" \
  -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 · Eksempelsvar på en vellykket verificering
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 · Eksempelsvar på en testbesked

Verificér signaturen

Header
Header Betydning
webhook-id Beskedens ID (msg_…). Det forbliver det samme ved genforsøg. Brug det til at finde dubletter.
webhook-timestamp Tidspunkt for dette leveringsforsøg i Unix-sekunder.
webhook-signature En eller flere signaturer på formen v1,<Base64>, adskilt af mellemrum.
import base64, hashlib, hmac, time

def verify_webhook(secret: str, headers: dict, body: bytes) -> bool:
    msg_id = headers["webhook-id"]
    timestamp = headers["webhook-timestamp"]
    # Afvis beskeder, der er ældre end fem minutter
    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()
    # Under en rotation af secret bærer headeren to signaturer
    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

Felt
Felt Betydning
id Beskedens ID, lig med headeren webhook-id.
event_id Hændelsens ID (evt_…).
type Hændelsens type, se nedenfor.
timestamp Hvornår vi opdagede hændelsen, i UTC.
schema_version Opbygningens version, i øjeblikket 1.
data Hændelsens data.
Hændelsestyper
Hændelsestype Betydning
organization.signal.detected En monitor har fundet et nyt signal. data.signal har samme opbygning som et signal i signals, plus data.monitor og, under data.links.signal, linket til signalet i API’et.
organization.signal.sample Et eksempel fra virksomhedens rigtige historik, sendt under Konto › Monitoring. Samme opbygning som ovenfor, plus data.sample: true.
endpoint.test Testbesked via /test.
endpoint.verification Challenge under verificeringen.
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}
Eksempelbesked for Hetzner Online GmbH, Ansbach HRB 6089: fusionen med Headtrip GmbH, Nürnberg HRB 33432, sendt som eksempel fra historikken

Leveringer og genforsøg

Vi leverer hver besked mindst én gang, men ikke i en fast rækkefølge. Find dubletter via webhook-id. Svar hurtigt, og behandl først beskeden derefter.
Status for en levering
Status Betydning
withheld Venter, til tjekket er afregnet.
pending Venter på at blive sendt.
in_flight Sendes lige nu.
retry_wait Venter på næste forsøg.
succeeded Leveret.
exhausted Alle forsøg mislykkedes.
blocked_endpoint Webhook-endpointet kan ikke modtage noget lige nu.
cancelled Annulleret, f.eks. fordi beskeden er udløbet.

Aktivér, deaktivér, arkivér

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

Fejl

Fejl
Status Årsag Hvad du kan gøre
400 api_key står i URL’en. Send nøglen i headeren x-api-key.
400 URL’en er ikke tilladt som destination, en header er ikke tilladt, det maksimale antal er nået, eller webhook-endpointet er ikke aktivt. meta.message angiver årsagen. Ret værdien, eller verificér først.
400 Idempotency-Key har et ugyldigt format. Ret formatet, brug f.eks. et UUID.
401 Ingen eller en ugyldig API-nøgle eller token. Send nøglen i headeren x-api-key.
403 Bearer-tokenet mangler rettigheden account:read. Brug API-nøglen eller et token med account:read.
403 Din kontos e-mailadresse er endnu ikke bekræftet, eller kontoen er spærret. Åbn linket fra bekræftelsesmailen. Er kontoen spærret, kan support hjælpe.
403 Dette kald kræver admin-tokenet. En API-nøgle er ikke nok, og det er et andet token heller ikke. Send det med Authorization: Bearer og admin-tokenet.
403 Bearer-tokenet mangler rettigheden monitoring:manage. Brug API-nøglen eller admin-tokenet.
404 Intet webhook-endpoint eller nogen levering med dette ID. Tjek ID’et.
409 Idempotency-Key blev allerede brugt med andre data, er ældre end 24 timer eller behandles stadig. Brug en ny nøgle, eller vent kort.
422 En værdi mangler eller er ugyldig, f.eks. name eller url. errors angiver feltet. Ret værdien, og prøv igen med en ny nøgle.
422 Verificeringen mislykkedes. Tjek challenge-headeren og 2xx-status, og prøv så igen med en ny nøgle.
428 Headeren Idempotency-Key mangler. Send headeren.
429 For mange forespørgsler. Prøv igen efter Retry-After.
503 Verificering, test og gensending er midlertidigt utilgængelige. Prøv igen lidt senere.
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 · Et webhook-endpoint, der endnu ikke er verificeret, kan ikke modtage en testbesked