Skip to main content
Webhooks deliver an AI-generated summary of each completed call — including the full conversation transcript, tags, interest classification, and any custom keys extracted by the AI — to an endpoint you control. Use them to push call outcomes into your CRM, analytics pipeline, or internal tooling.

Webhooks setup

To set up webhooks, go to Settings > Webhooks in the Dashboard and add the URLs you would like to receive events on. A company can configure multiple active webhook URLs; leaving the list empty disables delivery. When a webhook is created, a signing secret is automatically generated. Every dispatch is signed with HMAC-SHA256 using that secret — you can verify the signature on your server to confirm the request originated from Olimi and that the payload wasn’t tampered with.

When a webhook fires

A webhook is sent once per call, after the AI summary pipeline finishes for that call. Specifically:
  • The call must have a transcript with at least one user message (calls with no user messages are summarized as “No message was left during this call.”).
  • The company must have at least one active webhook configured.
  • Delivery is asynchronous and queued — the webhook is dispatched after the call record is committed to the database.
If a receiver returns a non-2xx response, the job is retried according to the standard queue retry policy. Failures are logged but do not roll back the underlying call record.

Request format

The body is a plain JSON object — not a JSON:API envelope. Treat unknown fields as additive; new fields may be introduced without a breaking change.

Signing secret

Each webhook has a whsec_ signing secret (48 hex characters). The full secret is shown only on create or rotate — copy it immediately. All other API responses return a masked hint (whsec_…XXXX). From Settings > Webhooks use the rotate (↻) and revoke (🗑) icons to manage the secret, or via the API:
  • POST /api/v2/organization-webhooks/:id/rotate-token — generates a new secret; old one is immediately invalidated
  • DELETE /api/v2/organization-webhooks/:id/token — clears the secret; dispatches will send no signature headers until rotated

Signature verification

When a webhook has a signing secret configured, every outbound request includes two headers:
  • X-Olimi-Timestamp — the Unix timestamp (seconds) at the time of dispatch
  • X-Olimi-Signature — sha256= followed by the lowercase hex HMAC-SHA256 digest

How the signature is constructed

The signed message is formed by concatenating the timestamp, a dot, and the raw JSON body:
Including the timestamp in the signed message ties the signature to a specific point in time, so a captured request cannot be replayed later with a valid signature.

Why HMAC over a Bearer token

With a raw Bearer token, your server compares the incoming header value to a stored secret — the secret itself travels in every request. With HMAC, the secret never leaves your server. You recompute the expected signature from the payload and timestamp, then compare — so even if a request is intercepted in transit, the secret cannot be extracted from it.

Verifying in Node.js

req.rawBody must be the raw request body bytes — not a parsed object. Computing HMAC over JSON.stringify(parsedBody) will fail if the serialization differs from what Olimi sent (e.g. key ordering, whitespace). In Express, capture raw bytes with express.raw({ type: 'application/json' }) before any JSON middleware.

Verifying in Python

Example headers

Payload

Field reference

Call outcome fields

call_status is one of: is_final tells you whether to expect more. More than one webhook can arrive for the same contact — each attempt is delivered as its own call with its own id.
  • answered — final, unless a callback was scheduled during the conversation, in which case callback_date carries the UTC time of the follow-up and is_final is false.
  • not_answered / failed — final only when no campaign retry remains. If the campaign will dial again, is_final is false.
  • pending / in_progress — never final.
Treat is_final: true as the signal to close the record on your side; earlier deliveries are interim updates for the same contact.

Transcript items

Each transcript item includes detailed metadata and execution flags:
Observed roles: system, assistant, user.

Custom keys

Each custom key is an object with key and value:
The callback_date key, when present, is also consumed server-side to schedule a callback on the contact — you don’t need to act on it unless you want to mirror the behavior in your own system.

Campaign

Included only when the call belongs to a campaign.

Example payload

is_final is false in this example because the conversation scheduled a callback — callback_date carries its UTC time, and a further webhook will follow that call.

Receiver expectations

  • Respond with any 2xx status to acknowledge receipt. Non-2xx responses trigger retries on our end.
  • Your endpoint must accept application/json request bodies.
  • Don’t rely on JSON key ordering — it is not guaranteed.
  • duration is in seconds. call_time and callback_date are ISO-8601 in UTC.
  • Expect more than one webhook per contact. Key your records off id (unique per call attempt) and use is_final to decide when the outcome is settled.
  • Treat unknown fields as additive and ignore them if you don’t need them.