Skip to main content
A webhook is an HTTPS POST that Aniva sends to your server when something changes. You do not need to poll. Events are thin. They carry the object id, the new status, a revision and the url to read. They never carry lab values or personal data. Read the url with your API key to get the data.

Quick setup

  1. Build an HTTPS endpoint that accepts POST and answers 2xx within 15 seconds.
  2. Register it with Create Webhook. Store the secret from the response. Aniva shows it only once.
  3. Verify the signature of every request.
  4. Send a test event. Check the result in List Deliveries.
Your API key needs the webhooks_manage scope. Ask Aniva to add it. A webhook belongs to the API key that created it, and a key can own at most 5 webhooks.

Events

You receive an event only for objects your API key can read with the matching GET endpoint. Choose the types with enabled_events. Send ["*"] to receive every type, also types added later.
  • A status event fires on every move into that status, also a move back. For example, a kit that goes from dispatched back to pending sends home_kit_order.pending.
  • One change can send two events with the same status_revision, for example appointment.confirmed and appointment.rescheduled.
  • results.updated fires on every change of the results: a new value, a correction, a fault, a new or replaced document, or a sample that leaves the object. It arrives within a few minutes of the last change.
  • results.completed and results.fault always come with a results.updated of the same results_revision. Results can reopen and complete again, so you can get a second results.completed.
Subscribe to results.updated to show partial results, or to results.completed to act only on final results. results.completed follows the result values, not the PDF. The report PDF can arrive before or after the values. Some labs first send a preliminary PDF and later replace it with the final one under the same document id. The replacement sends results.updated. Read documents[].original_file_name to tell the two apart: Labor Quade ends a preliminary report (Vorbefund) in _V and the final report (Endbefund) in _E, for example 7642100312_B0012_FA_E.pdf. Location, profile and shipment events arrive within a few minutes. Aniva waits until the object has not changed for 2 minutes, so a burst of edits sends one event. These rules also apply:
  • Anonymous profiles send no events.
  • A shipment sends no event when you lose access to it.
  • A shipment status change sends shipment.updated and the shipment.<status> event with the same revision.

Payload

Status event data

appointment.confirmed

Results event data

home_kit_order.results.completed

Location, profile and shipment event data

shipment.in_transit
A ping carries data.object webhook and data.id, the webhook id.

Verify the signature

Events carry no data, but you should still verify each one. A valid signature proves that the event came from Aniva. Each request carries the headers webhook-id, webhook-timestamp (Unix seconds) and webhook-signature.
  1. Take the raw request body. Verify it before you parse the JSON.
  2. Build the signed content {webhook-id}.{webhook-timestamp}.{raw body}.
  3. Base64-decode the part of your secret after whsec_. Use it as the key.
  4. Compute HMAC-SHA256 of the signed content and encode it as base64.
  5. Compare it in constant time with each v1,<signature> entry in webhook-signature. The entries are separated by spaces. One match is enough.
  6. Reject the request when webhook-timestamp is more than 5 minutes from your clock.
Node.js
The scheme is Standard Webhooks. Standard Webhooks libraries exist for most languages and do this in one call.

Rotate the secret

Call Rotate Secret to get a new secret. For 24 hours, Aniva signs with the old and the new secret, so deploy the new one within that time. After a leak, send revoke_current_secret_now: true to stop the old secret at once.

Delivery

  • Answer 2xx within 15 seconds. Store or queue the event and do the work later.
  • Use an https URL on port 443 with a public host. Aniva does not follow redirects: a 3xx counts as a failure.
  • Delivery is at least once and unordered. Drop duplicates by webhook-id. Use the revisions to ignore an older event.
  • Answer 410 Gone to stop the events. Aniva disables the webhook at once.
  • Aniva keeps deliveries for 30 days. After that, you cannot list or resend them.

Retries

A non-2xx answer, a timeout or a network error starts a retry. Each event gets up to 10 attempts over about three days: After attempt 10, the delivery is failed. Send it again with Resend Delivery. It keeps the same webhook-id.

Failure notices

Aniva emails the webhook’s alert_emails when no delivery succeeded for 24 hours, when an event is failed, and when the webhook is disabled. After 5 days without a successful delivery, Aniva disables the webhook. A disabled webhook gets no new events, and its waiting deliveries are cancelled. To start again, fix your endpoint and send status: "enabled" with Update Webhook. Missed events are not sent again by themselves. Resend them, or read the current state with the GET endpoints.

Best practices

  • Drop duplicates. Skip an event whose webhook-id you already processed.
  • Use the revisions. Store the highest status_revision, results_revision and revision per object. Ignore an event with a lower one.
  • Fetch the url. The event says that something changed. The GET endpoint says what.
  • Answer fast. Queue the event and answer 2xx before you process it.
  • Reconcile. Run a regular job that reads open objects with the GET endpoints. Polling stays a valid fallback.
  • Test after each deploy. Use Send Test Event.