Events & payloads

Every webhook delivery is a JSON POST with the same stable envelope. This page documents the envelope, the event types, and how the block field maps to the profile.

The envelope

Field Type Description
type string The event type — e.g. profile.changed. See Event types.
apiVersion string Payload schema version. Currently v1.
occurredAt string ISO-8601 UTC instant the change occurred, e.g. 2026-06-30T19:40:00Z.
idempotencyKey string Stable key identifying this change — dedupe on it.
block string Which part of the profile changed. Matches a field name in the profile response — see Blocks.
data object Minimal event data: jurisdiction and companyNumber.

The contract is additive — we may add fields without notice, so parse defensively and ignore unknown fields. A breaking change bumps apiVersion.

Event types

type Meaning
profile.changed A tracked profile block changed. The block field says which one.
profile.early_signal.detected A new early-warning signal was detected on the company. block is earlySignals.
profile.early_signal.updated An existing early signal changed state (superseded or expired). block is earlySignals.

The block field

For profile.changed, block tells you which section of the profile changed — and its value is exactly the corresponding field name in the GET /v1/profile/{companyNumber} response, so you can map it straight onto the section to re-read.

block Profile field it maps to Changes when…
overview overview Company size, complexity, maturity, or type changes.
tradingStatus tradingStatus The company's trading status changes (e.g. Active → Ceased).
filingBehaviour filingBehaviour Filing behaviour/consistency changes.
riskOfFailure riskOfFailure The risk-of-failure level changes (e.g. Low → High).
creditCapacity creditCapacity The estimated credit/trade limit changes.
earlySignals earlySignals An early-warning signal appears or changes state.

Example payloads

Trading status changed:

{
  "type": "profile.changed",
  "apiVersion": "v1",
  "occurredAt": "2026-06-30T19:40:00Z",
  "idempotencyKey": "PROFILE_CHANGED:SC855307:ACTIVE_TO_CEASED:20260630",
  "block": "tradingStatus",
  "data": { "jurisdiction": "GB", "companyNumber": "SC855307" }
}

Early signal detected:

{
  "type": "profile.early_signal.detected",
  "apiVersion": "v1",
  "occurredAt": "2026-06-30T19:40:00Z",
  "idempotencyKey": "EARLY_SIGNAL:SC855307:winding_up_petition:ACTIVE",
  "block": "earlySignals",
  "data": { "jurisdiction": "GB", "companyNumber": "SC855307" }
}

Reacting to an event

data carries only jurisdiction and companyNumber — enough to re-fetch. Use block to decide which part of the returned profile you care about:

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://public-api.heygrand.com/v1/profile/SC855307?jurisdiction=GB"

Because the payload never carries the changed values, you never act on stale data and you don't need to handle out-of-order deliveries field-by-field — the profile you fetch is always current.

Verify each delivery before you trust it. Idempotency keys, retries, and ordering.

Grand Public API