Status: Production partner preview for admitted personal tenants. Projection starts with events created after activation and does not backfill earlier task events.Webhooks let your server receive durable run progress without holding an SSE connection open. Praxa signs every request, retries failed deliveries, and may deliver the same event more than once or out of order. Your handler must verify the raw request, persist each event idempotently, and order changes within each run.
1. Register an endpoint
The signed-in developer portal usesPOST /api/platform/webhooks. The bearer
SDK contract uses this active partner-preview operation:
This operation is available only to keys issued to admitted personal tenants.
It is not generally available.
runs:write. The backend reauthorizes both runs:read
and runs:write, so the key must carry both scopes. The response status is
201.
The response includes signing_secret once. Store it immediately in your
secret manager; Praxa will not show it again.
2. Verify the signature before parsing
Every delivery carries:JSON.parse:
persistOnceAndQueue should atomically insert event_id under a unique
constraint and enqueue any slower work. Return 2xx only after that transaction
commits. If the id already exists, acknowledge the duplicate without repeating
its effects.
3. Deduplicate and order per run
Praxa provides at-least-once delivery. Retries and manual replay preserve the same immutableevent_id, so use that as the deduplication key.
Delivery order is not guaranteed. A retry of sequence 11 can arrive after
sequence 12. Use (run_id, sequence) to process or reconstruct one run’s
ordered history:
sequence as global, and do not use HTTP arrival order as run
state. You may receive a later event before an earlier one.
4. Parse the strict v1 body
The body contains exactly seven top-level fields:data object is strict and depends on type. Reconciliation notifications
are run.progress with exactly { "status": "running" }. A permanently
unknown committing outcome is:
5. Fetch the approval before rendering it
Anapproval.required webhook is a notification, not the approval
presentation. Its data contains only:
GET /v1/runs/:id, require pendingApproval, and verify its digest
equals the webhook digest. Only then render the exact
pendingApproval.summary and allow a human to approve or deny. If the run no
longer exposes that exact pending approval, fail closed and acknowledge the
webhook without showing active decision controls.
Submit the public decision with the unchanged digest:
approve or deny. The later
approval.resolved.data.decision webhook deliberately preserves the internal
event values approved or denied. Do not send those past-tense values in the
public approval request.
6. Understand retries and dead letters
- Return 2xx after durable acceptance, then process slow work asynchronously.
- Timeouts,
408,409,425,429, and 5xx responses are retryable. - Praxa makes at most five attempts, delayed by 30 seconds, 5 minutes, 30 minutes, and 2 hours.
- Other 4xx responses and refused or unsafe redirects fail permanently.
- A delivery that exhausts retries enters
dead_letter. Inspect it and use the idempotent replay action after correcting your endpoint.
runs:read:
endpoint_id, run_id, or status, page with cursor, and
set limit from 1 to 100. The default is 50. The response status is 200, and
the strict list contains apiVersion, data, and optional nextCursor.
Replay a corrected dead-letter delivery by sending an exact empty object:
runs:write, while the backend requires both runs:read
and runs:write. A successful replay returns 202 and the created or
idempotently reused delivery record.
Production evidence
A production canary created an endpoint, received a delivery, and verified its HMAC over the exact raw body. Retry, dead-letter, eligible replay, and redirect safety remain separate operational canaries. Build idempotent handling as documented even when a particular retry path has not been forced in a live canary.Next steps
- Build the human decision flow with Build an approval UI.
- Review the full payload, signing, activation, and endpoint constraints in Webhooks.