/v1/account/webhook-endpoints

account/webhook-endpoints

Webhook: dove Monitoring invia i nuovi Signals e come li verifichi.

Costi e limiti

Costi e limiti
Cosa Crediti
Gestire endpoint webhook e consegne gratis

Limite: 30 richieste al minuto. Creare, modificare ed eliminare: 10 al minuto. Controllo, test e nuovo secret: 6 al minuto.

Admin token o chiave API

Endpoint

Metodo
Metodo Percorso Scopo Accesso
GET /v1/account/webhook-endpoints Tutti gli endpoint webhook, senza quelli archiviati. Chiave API o admin token
POST /v1/account/webhook-endpoints Creare un endpoint webhook. Admin token
POST /v1/account/webhook-endpoints/{id}/verify Verificare. Chiave API o admin token
POST /v1/account/webhook-endpoints/{id}/test Inviare un messaggio di prova. Chiave API o admin token
POST /v1/account/webhook-endpoints/{id}/rotate-secret Nuovo secret di firma. Admin token
POST /v1/account/webhook-endpoints/{id}/enable Attivare. Admin token
POST /v1/account/webhook-endpoints/{id}/disable Disattivare. Admin token
DELETE /v1/account/webhook-endpoints/{id} Archiviare. Admin token
GET /v1/account/webhook-deliveries Le ultime 50 consegne. Chiave API o admin token
POST /v1/account/webhook-deliveries/{id}/retry Reinviare una consegna non riuscita. Chiave API o admin token
GET /v1/account/webhook-events Gli ultimi 50 eventi. Chiave API o admin token

Creare un endpoint webhook

curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints" \
  -H "Authorization: Bearer IL_TUO_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": "IL_TUO_RECEIVER_TOKEN"
    }
}'
Parametri
Nome Tipo Descrizione Esempio
Idempotency-KeyHeader stringaobbligatorio Un valore univoco per operazione, idealmente un UUID. Vedi Idempotency-Key.Limiti: da 1 a 128 caratteri req-20260802-01
nameBody stringaobbligatorio Un nome come tuo riferimento.Limiti: da 1 a 120 caratteri CRM-Sync
urlBody stringa (uri)obbligatorio L’indirizzo del tuo server: raggiungibile pubblicamente, https sulla porta 443, con un nome host invece di un indirizzo IP.Limiti: da 1 a 2.048 caratteri https://hooks.example.com/handelsregister
headersBody oggettofacoltativo Header personalizzati inviati con ogni messaggio, come un token per il tuo server.Limiti: al massimo 10 voci {"X-Receiver-Token":"IL_TUO_RECEIVER_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 · Risposta di esempio: un nuovo endpoint webhook, il secret qui abbreviato

Verificare

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}
Il messaggio che il tuo server riceve durante la verifica
curl -X POST "https://handelsregister.ai/api/v1/account/webhook-endpoints/wep_01m6b3j1g0cdz98hw8zdefbf52/verify" \
  -H "x-api-key: LA_TUA_CHIAVE_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 · Risposta di esempio a una verifica riuscita
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 · Risposta di esempio a un messaggio di prova

Verificare la firma

Header
Header Significato
webhook-id ID del messaggio (msg_…). Resta uguale nei nuovi tentativi. Usalo per riconoscere i duplicati.
webhook-timestamp Momento di questo tentativo di consegna in secondi Unix.
webhook-signature Una o più firme nella forma v1,<Base64>, separate da spazi.
import base64, hashlib, hmac, time

def verify_webhook(secret: str, headers: dict, body: bytes) -> bool:
    msg_id = headers["webhook-id"]
    timestamp = headers["webhook-timestamp"]
    # Rifiuta i messaggi più vecchi di cinque minuti
    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()
    # Durante una rotazione del secret, l’header contiene due firme
    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

Campo
Campo Significato
id ID del messaggio, uguale all’header webhook-id.
event_id ID dell’evento (evt_…).
type Tipo dell’evento, vedi sotto.
timestamp Quando abbiamo rilevato l’evento, in UTC.
schema_version Versione della struttura, attualmente 1.
data I dati dell’evento.
Tipi di evento
Tipo di evento Significato
organization.signal.detected Un monitor ha trovato un nuovo segnale. data.signal ha la stessa struttura di un segnale in signals, più data.monitor e, in data.links.signal, il link al segnale nell’API.
organization.signal.sample Un esempio dallo storico reale dell’azienda, inviato da Account › Monitoring. Stessa struttura di sopra, più data.sample: true.
endpoint.test Messaggio di prova tramite /test.
endpoint.verification Challenge durante la verifica.
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}
Messaggio di esempio per Hetzner Online GmbH, Ansbach HRB 6089: la fusione di Headtrip GmbH, Nürnberg HRB 33432, inviata come esempio dallo storico

Consegne e nuovi tentativi

Consegniamo ogni messaggio almeno una volta, ma non in un ordine fisso. Riconosci i duplicati tramite webhook-id. Rispondi rapidamente ed elabora il messaggio solo dopo.
Stato di una consegna
Stato Significato
withheld Attende che il controllo sia stato addebitato.
pending Attende di essere inviata.
in_flight In fase di invio.
retry_wait Attende il prossimo tentativo.
succeeded Consegnata.
exhausted Tutti i tentativi sono falliti.
blocked_endpoint L’endpoint webhook al momento non può ricevere nulla.
cancelled Annullata, ad esempio perché il messaggio è scaduto.

Attivare, disattivare, archiviare

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

Errori

Errori
Stato Causa Cosa puoi fare
400 api_key è nell’URL. Invia la chiave nell’header x-api-key.
400 L’URL non è consentito come destinazione, un header non è ammesso, è stato raggiunto il numero massimo oppure l’endpoint webhook non è attivo. meta.message indica il motivo. Correggi il valore o verifica prima.
400 L’Idempotency-Key ha un formato non valido. Correggi il formato, ad esempio usa un UUID.
401 Nessuna chiave API o token, o uno non valido. Invia la chiave nell’header x-api-key.
403 Al bearer token manca l’abilitazione account:read. Usa la chiave API o un token con account:read.
403 L’indirizzo email del tuo account non è ancora confermato, oppure l’account è bloccato. Apri il link dall’email di conferma. Se l’account è bloccato, il supporto può aiutarti.
403 Questa chiamata richiede l’admin token. Una chiave API non basta, e nemmeno un altro token. Invialo con Authorization: Bearer e l’admin token.
403 Al bearer token manca l’abilitazione monitoring:manage. Usa la chiave API o l’admin token.
404 Nessun endpoint webhook o consegna con questo ID. Controlla l’ID.
409 L’Idempotency-Key è già stato usato con dati diversi, è più vecchio di 24 ore oppure è ancora in elaborazione. Usa una nuova chiave o aspetta un momento.
422 Un valore manca o non è valido, come name o url. errors indica il campo. Correggi il valore e riprova con una nuova chiave.
422 Verifica non riuscita. Controlla l’header della challenge e lo stato 2xx, poi riprova con una nuova chiave.
428 Manca l’header Idempotency-Key. Invia l’header.
429 Troppe richieste. Riprova dopo Retry-After.
503 Verifica, test e reinvio sono temporaneamente non disponibili. Riprova poco più tardi.
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 · Un endpoint webhook non ancora verificato non può ricevere un messaggio di prova