Skip to content
This is a new version of the Kivra Developer Docs. Report issues or share feedback at avsandare.support@kivra.se. The previous version can be found here.

Webhooks

Kivra sends a webhook to your endpoint when a company activates or deactivates an integration with you, and when such a company receives content. These events drive the whole flow; the Integration guide describes what to do in response to each one. This page covers the deliveries themselves.

Kivra registers your endpoint and shares the signing secret with you as part of setting you up as a partner. Sandbox and production are registered separately.

Event Sent when Data
integration.created A company activates an integration with you. company_key, vat_number
integration.deleted A company deactivates the integration. company_key, vat_number
content.created A company that has an integration with you receives content. company_key, content_key, vat_number

Every payload has the same envelope:

Field Description
id Event identifier. It is the same across retries, so use it to deduplicate.
event_created_at Unix timestamp in seconds when the event happened.
event_type Which event this is.
data_version Version of the data shape for this event type.
data Event-specific data.

Kivra may add fields to data without changing data_version, so ignore fields you do not know. A breaking change increments data_version. The payloads are also described in the API reference.

Each delivery carries a timestamp and one or more signatures:

X-KIVRA-TIMESTAMP: <unix seconds>
X-KIVRA-SIGNATURE: v1=<hex HMAC-SHA256>

To verify a delivery:

  1. Read the timestamp t from X-KIVRA-TIMESTAMP and reject it if it is outside the window you accept, to prevent replays.
  2. Build the message t + ":" + body, using the raw request body exactly as received.
  3. Compute HMAC-SHA256 of the message with your shared secret, hex-encoded.
  4. Compare the result with the hex digest after v1= in every X-KIVRA-SIGNATURE header, using a constant-time comparison. The delivery is authentic if any of them matches.

During a secret rotation Kivra sends one X-KIVRA-SIGNATURE header per active secret, which is why there can be several.

Respond with 200 OK once you have durably accepted the event. Any other response causes a retry, so acknowledge first and do the actual work asynchronously.

Kivra retries failed deliveries with increasing delays for a long time, so a temporary outage on your side does not lose events. Delivery is therefore at least once, and sometimes late, so:

  • deduplicate on id; and
  • treat event_created_at as when the event happened and X-KIVRA-TIMESTAMP as when this attempt was sent.