Receiving webhooks
The webhook is the authoritative result channel. Polling exists for progress indicators and recovery, not for driving business logic.
This page covers configuration and delivery semantics. For the payload itself — every field, every object — see The webhook payload.
Configure a receiver
Section titled “Configure a receiver”-
Portal → Connect → Add Webhook.
-
Enter your HTTPS endpoint.
-
For Authorization choose Bearer, and set a secret. UpPass sends it on every delivery as
Authorization: Bearer {secret}. -
Subscribe to
submit_format minimum. Other events are listed underevent.type.
One flow can have several receivers.
Contract
Section titled “Contract”What UpPass sends, and what your endpoint must do.
| Method | POST |
| Content type | application/json |
| Transport | HTTPS with a valid certificate |
| Auth header | Authorization: Bearer {your configured secret} |
| Expected response | Any 2xx, within 30 seconds |
| Body | Submission payload on submit_form; lifecycle envelope otherwise |
Your endpoint must:
- Reject a mismatched
Authorizationheader. It is the only thing authenticating the caller. - Return
2xxwithin 30 seconds. Acknowledge first and process afterwards if your handling is slow. See the delivery rules below. - Deduplicate on
application.slug+application.submitted_at. See below. - Fetch signed image URLs within 15 minutes. See below.
Delivery, timeout and retry
Section titled “Delivery, timeout and retry”| Your receiver… | UpPass… |
|---|---|
Returns 2xx within 30 seconds |
Marks the delivery successful |
Returns 5xx |
Retries, up to three times |
Returns 4xx |
Does not retry |
| Does not answer within 30 seconds | Does not retry |
A delivery that is not retried is not lost — recover it with
Resend webhook. Answer 5xx only for a genuine
transient failure on your side; answering 5xx for a payload you cannot process
just replays it three times.
Three delivery semantics that affect your design
Section titled “Three delivery semantics that affect your design”nounce cannot deduplicate a re-delivery
Section titled “nounce cannot deduplicate a re-delivery”event.nounce is unique per delivery, not per application. A resend, or an
automatic retry after your receiver answered 5xx, arrives with a different nonce
and passes any nonce-only check.
Use application.slug + application.submitted_at as the idempotency key. Both
are stable for the life of the application. Keep nounce for collapsing an immediate
transport-level retry, if you want it at all.
event.created_at is the delivery time
Section titled “event.created_at is the delivery time”Not the submission time. On a first delivery the two are seconds apart; on a re-delivery they can be far apart.
Read application.submitted_at for when the applicant finished.
Signed image URLs live 15 minutes
Section titled “Signed image URLs live 15 minutes”If you miss the window it is recoverable — a resend mints fresh URLs.
extra.identity_aml is unbounded and dominates the payload. One sanctions match
carried a dozen source lists with several hundred aliases; adverse-media matches
carry dozens of article snippets.
Size-test your receiver against a sanctions-match payload before go-live. Body limits on reverse proxies and serverless gateways are a realistic failure mode.
curl -O https://docs.uppass.io/examples/webhook-submit_form-aml-hit.jsonThat file is trimmed at __TRIMMED__ markers, so it is smaller than a production
payload. Treat it as a floor, not a ceiling.
Recovering a missed delivery
Section titled “Recovering a missed delivery”curl --request POST \ 'https://app.uppass.io/{lang}/api/forms/{form_slug}/applied-forms/{slug}/hook-submit/' \ --header 'Authorization: Bearer '"$UPPASS_API_TOKEN"Returns 204.
The resent payload has the same shape, with a new nounce and a new
event.created_at — which is why idempotency must not key on either.
Testing without a real applicant
Section titled “Testing without a real applicant”Complete payloads are published as JSON:
curl -O https://docs.uppass.io/examples/webhook-submit_form-clean.jsoncurl -O https://docs.uppass.io/examples/webhook-submit_form-aml-hit.jsoncurl -O https://docs.uppass.io/examples/webhook-drop_off.jsonPOST them at your own endpoint with the Authorization header you configured.