This is additive, not a replacement. Server-side events enrich an existing journey — they never create one. A journey always starts with a browser-attributed entry (via the tracking snippet); the server confirms what happened on it.
Authentication
Every request needs a Bearer API key. Create one under Settings → Workspace → Settings & Integrations (API Keys card) — copy the plaintext value immediately, it is shown once. Use aTest key while integrating and switch to Live for production traffic.
Joining the visitor’s journey
Passdava_session_id — the same session ID the browser snippet is already using — so the event lands on the visitor’s existing journey instead of standing alone.
dava_session_id in the event body.
Identity
At least one ofanonymous_id, contact_id, or hashed_email is required — the request is rejected with 400 otherwise. dava_session_id handles journey attribution; these fields drive identity-cluster matching (linking the same person across visits/devices), a separate concern.
Sending a single event
subdomain — Dáva resolves the domain from the request’s Host header instead.
Request fields
source is not a request field. Dáva derives it internally from the ingestion path ("api" for all /v1/events deliveries). Any source value sent in the request body is silently ignored.Deduplication
Duplicates at the delivery layer are expected — a network retry, a queue redelivery, or your own backend firing the same webhook handler twice. Dáva stores every delivery it receives for the same underlying action, but reports it as one canonical event. Two events are treated as the same action when they share a dedup key, checked in this order:event_id(top-level) — your stable per-event dedup key. E.g."policy_POL123". Any opaque string up to 128 characters — no UUID constraint.transaction_id(top-level) — the business transaction this event belongs to. E.g."POL123". Takes priority over the same value embedded inproperties.properties.transaction_id— or one of its aliasesquote_id,policy_id,order_id. Use whichever name matches your domain (an insurer sendspolicy_id, an e-commerce store sendsorder_id).external_id— your safe-retry idempotency key, if none of the above is present.
external_id still deduplicates at priority 4. A caller sending only properties.transaction_id still deduplicates at priority 3. Both orderings are preserved exactly.
When a second delivery matches an existing key:
- The response is
200(not201) withdeduped: trueand the sameevent_idas the first delivery. - Any field you send with a non-null value (
value,currency,properties) updates the stored event — anull/absent field never erases a value that was already there. This lets a browser-side event with novalueget enriched by a later server confirmation carrying the real amount, without one delivery overwriting the other’s data. created_atin the response reflects the original delivery’s timestamp, not the retry.
Response
201 on first receipt, 200 if the event deduplicated against a prior delivery (deduped: true) — see Deduplication above.
Sending multiple events
GET /v1/events/batch/{job_id}: