CompanyBelgium

Integration guide

Receive real-time changes for the enterprises and establishments you watch.

Full flow

  1. Create a webhook with your HTTPS URL and the entities to watch.
  2. Carefully store the HMAC secret — it is returned exactly once.
  3. On the next BCE sync, each change triggers a signed POST.
  4. Verify the signature on the receiver side before processing the payload.

Create a webhook

bash
curl -X POST https://companybelgium.be/api/v2/webhook \
  -H "X-API-Key: $API_KEY" \
  -H "X-API-Secret: $API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production listener",
    "url": "https://hooks.example.com/companybelgium",
    "entityNumbers": ["1033022383", "0202239951"]
  }'

⚠️ The `hmacSecret` field is returned exactly once on creation. Store it now — you will not be able to retrieve it again (only rotate it via PATCH /hmac-secret).

Payload format

http
POST https://hooks.example.com/companybelgium HTTP/1.1
Content-Type: application/json
X-CompanyBelgium-Signature: sha256=8e6c…
X-CompanyBelgium-Timestamp: 1747843200000
X-CompanyBelgium-Event: update
X-CompanyBelgium-Delivery: 9c1b…

{
  "event": "update",
  "entityNumber": "1033022383",
  "entityType": "enterprise",
  "data": {},
  "timestamp": "2026-04-15T10:00:00.000Z"
}

Signature verification

Reconstruct the HMAC on the receiver side with your secret + the timestamp and compare in constant time.

javascript
import crypto from "node:crypto"

function verify(req, secret) {
  const signature = req.headers["x-companybelgium-signature"]
  const timestamp = req.headers["x-companybelgium-timestamp"]
  const body = req.rawBody // Express: use express.raw() or capture before json()

  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${body}`)
    .digest("hex")

  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    throw new Error("Invalid signature")
  }

  // Reject signatures older than 5 minutes (replay protection)
  if (Math.abs(Date.now() - Number(timestamp)) > 5 * 60_000) {
    throw new Error("Timestamp too old")
  }
}

Retry policy

The dispatcher retries up to 3 times on network errors or 5xx, with exponential backoff (0.5s → 2s → 8s). 4xx are not retried. All attempts show up in GET /webhook/{id}/events.

Trigger a test

To verify your integration without waiting for a real BCE change, use the `trigger` endpoint.

bash
curl -X POST https://companybelgium.be/api/v2/webhook/$WEBHOOK_ID/trigger \
  -H "X-API-Key: $API_KEY" \
  -H "X-API-Secret: $API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"entityNumber":"1033022383","data":{"note":"manual test"}}'

Need help?

Our support team is available to help you with API integration.