POSTs a signed event to your configured
URL. Set the URL in your dashboard before creating sessions.
Events
| Event | When | Key payload |
|---|---|---|
step.completed | A step verified successfully | stage, primitive, and claims / satisfied / signature |
session.completed | All steps done | session_id, status |
session.stopped | You ended it at a gate | session_id, reason |
session.failed | A step failed, funds ran out, or an internal error | session_id, reason |
client_reference_id and any metadata. See
the event reference for full payloads.
Delivery guarantees
Ordered per step
step.completed fires in step order (stage 0, 1, 2…), followed by the terminal
session.* event.At-least-once
Delivery is retried with backoff until it succeeds. Each event has a stable
X-UIP-Delivery-Id — dedupe on it so a retry is harmless.Off the request path
Webhooks are queued and sent out-of-band, so a slow endpoint never blocks
verification — but it does delay your delivery.
Fired after the result is durable
An event is only sent once the verified result + audit record are committed, so a
webhook you receive always reflects persisted state.
Verifying signatures
Every delivery is signed with your business’s webhook secret (uip_whsec_...
from the dashboard). Always verify before trusting a payload.
Each request carries:
| Header | Value |
|---|---|
X-UIP-Event | The event name |
X-UIP-Timestamp | Unix seconds when signed |
X-UIP-Signature | HMAC-SHA256(secret, "{timestamp}.{raw_body}"), hex |
X-UIP-Delivery-Id | Stable per-event id (dedupe key) |
timestamp + "." + raw_request_body and compare in constant
time. Use the raw bytes — re-serializing the JSON can change them and break the
match.