Skip to main content

Webhooks

Coming soon: The Webhooks API is currently under design review. This documentation describes the target interface and may change before release. The exact event identifiers are still being finalised.
Webhooks let Cobee notify your system the moment something changes, instead of you polling the API. You register an HTTPS endpoint and subscribe it to one or more event types; whenever a matching event occurs, Cobee sends an HTTP POST request to your endpoint with a signed notification. Every webhook is a notification, not a full data dump: data identifies the relevant resources for what changed (for example, a company, employee, payroll period or committed expense) so you can call the corresponding GET endpoint for the authoritative state, and it may additionally include the immutable fact that triggered the event (e.g. the individual consumption that was just charged) — but never a computed, mutable balance, since that could go stale if a notification is delayed or delivered more than once. This keeps every event idempotent: receiving one more than once, or out of order, is always harmless.

How It Works

  1. Register a subscription: you provide the URL of your endpoint and the list of event types you want to receive (POST /webhooks/subscriptions). Cobee returns a signing secret that you must store securely.
  2. Receive notifications: when an event occurs, Cobee calls your endpoint with a small signed JSON body identifying what changed.
  3. Acknowledge: your endpoint must respond with a 2xx status code within 10 seconds. Any other response (or a timeout) is considered a failed delivery and will be retried.
  4. Fetch the data: call the corresponding GET endpoint (consumptions, committed expenses…) with the filters and format options that suit your integration to obtain the latest state.
  5. Monitor: you can inspect the delivery history of your subscription at any time (GET /webhooks/subscriptions/{subscriptionId}/deliveries).

Notification Envelope

Every webhook call uses the same envelope, regardless of the event type:
Webhook notifications are always application/json. To download the actual data you call the GET endpoints, which support JSON and CSV as usual.

Delivery Semantics

  • Notification, not a query API: some events include the immutable record that triggered them, but you always obtain the accumulated totals, all benefit categories, groupBy and format by calling the GET endpoint when you need the authoritative current state — so the contract you consume there is the one you already know.
  • Idempotent by design: computed, mutable balances are never embedded in the payload, so it does not matter if a notification is delivered more than once, out of order, or coalesced — replaying the notification is safe, while a subsequent GET returns the latest authoritative state.
  • At-least-once delivery: the same event may be delivered more than once. Deduplicate by event id if you want to avoid redundant fetches.
  • No cascading calls: when a company closes its payroll cycle you receive a single company.payroll-cycle.closed notification — not one call per employee. You then download the company’s consumptions in one GET call.
  • Retries: failed deliveries are retried with exponential backoff for up to 72 hours. After that, the delivery is marked as failed and can be inspected in the delivery history.

Verifying Signatures

Every webhook request includes an X-Cobee-Signature header so you can verify that the call genuinely comes from Cobee and that the notification was not tampered with:
To verify:
  1. Extract the timestamp (t) and the signature (v1) from the header.
  2. Concatenate the timestamp, a dot (.), and the raw request body: {t}.{body}.
  3. Compute the HMAC-SHA256 of that string using your subscription’s signing secret as the key.
  4. Compare your computed signature with v1 using a constant-time comparison.
  5. Reject the request if the signatures do not match, or if the timestamp is older than 5 minutes (to prevent replay attacks).
Store the signing secret securely and never expose it in client-side code or logs. If you suspect it has been compromised, rotate it with POST /webhooks/subscriptions/{subscriptionId}/secret.

Endpoints

Authentication works exactly like the rest of the Partners API: obtain a JWT via POST /oauth/token and send it as a Bearer token.