Overview
Every delivery includes a top-level envelope that wraps the event-specific data object:
| Field | Type | Description |
|---|
id | string | Unique event ID — use this for idempotency (evt_ prefix). |
type | string | Event name in resource.action form. |
tenantId | string | UUID of the tenant that owns the data. |
environmentId | string | null | ID of the environment (live or sandbox). null for tenant-scoped events. |
environmentType | "live" | "sandbox" | null | Human-readable environment label. |
data | object | Event-specific payload — schema documented per event below. |
createdAt | string | ISO 8601 UTC timestamp when Zquence emitted the event. |
Your endpoint must return a 2xx HTTP status within 10 seconds. Any non-2xx response or timeout is treated as a failed delivery and retried with exponential backoff. See Retries for the full schedule.
KYC events
KYC events track the internal KYC record lifecycle and provider (Onfido) verification outcomes.
kyc.created
Trigger: A new KYC record is created for a user — happens the first time a user starts the KYC flow.
Use cases:
- Bootstrap a user record in your system.
- Start a compliance workflow downstream.
- Log the KYC initiation timestamp.
Payload schema
| Field | Type | Description |
|---|
kycId | string | Internal KYC record ID. |
userId | string | User the record belongs to. |
tenantId | string | Owning tenant. |
environmentId | string | null | Environment the record lives in. |
currentStep | number | Form step at creation — always 0. |
status | string | KYC status at creation — typically an empty string or "pending". |
{
"id": "evt_0b3e2d90d18048eaa913704cd52937b9",
"type": "kyc.created",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"kycId": "69f9cfbba364e4043805910e",
"userId": "6a25cdac36bc6230704b5b59",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"currentStep": 0,
"status": "pending"
},
"createdAt": "2026-06-07T09:12:41.208Z"
}
kyc.updated
Trigger: The user saves progress on the KYC form — any field update that does not include a final submission signature.
Use cases:
- Track partial form completion for support tooling.
- Measure drop-off at specific form steps via
currentStep.
- Mirror KYC field changes into your own data store.
Payload schema
| Field | Type | Description |
|---|
kycId | string | Internal KYC record ID. |
userId | string | User the record belongs to. |
tenantId | string | Owning tenant. |
environmentId | string | null | Environment. |
currentStep | number | Form step the user is on at time of update. |
status | string | Current KYC status — see KYC status values. |
kycData | object | Spread of clientInformation fields the user has filled in so far. |
{
"id": "evt_1b2595af5e7c4dc4a71bcf54cfe5bc80",
"type": "kyc.updated",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"kycId": "6a26851e64d94ca57870e73b",
"userId": "6a267b273efc540f27171829",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"currentStep": 5,
"status": "pending",
"kycData": {
"fullName": "James Carter",
"idNumber": "GB-1234567890",
"countryOfIssuance": "United Kingdom",
"corporationName": "Acme Corp"
}
},
"createdAt": "2026-06-08T10:01:31.103Z"
}
kyc.submitted
Trigger: The user completes the KYC form and signs it — submittedOn is set for the first time. This marks the end of user-side data entry.
Use cases:
- Notify your compliance team that a KYC is ready for review.
- Transition the user to a “pending verification” state in your UI.
- Trigger downstream document collection workflows.
Payload schema
| Field | Type | Description |
|---|
kycId | string | Internal KYC record ID. |
userId | string | User the record belongs to. |
tenantId | string | Owning tenant. |
environmentId | string | null | Environment. |
submittedOn | string | ISO 8601 timestamp when the form was signed and submitted. |
status | string | KYC status at submission — typically "pending". |
kycData | object | Spread of clientInformation fields at time of submission. |
{
"id": "evt_aa0593639ead48fc9bd3019d24b54ed0",
"type": "kyc.submitted",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"kycId": "6a26851e64d94ca57870e73b",
"userId": "6a267b273efc540f27171829",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"submittedOn": "2026-06-08T10:06:15.635Z",
"status": "pending",
"kycData": {
"fullName": "James Carter",
"idNumber": "GB-1234567890",
"countryOfIssuance": "United Kingdom",
"corporationName": "Acme Corp"
}
},
"createdAt": "2026-06-08T10:06:15.684Z"
}
kyc.provider.completed
Trigger: The identity provider (Onfido) returns an approved outcome for the user’s verification run.
Use cases:
- Unlock features or accounts that require verified identity.
- Update user status to
verified in your system.
- Trigger onboarding completion notifications.
Payload schema
| Field | Type | Description |
|---|
userId | string | User whose verification completed. |
provider | "onfido" | Identity provider name. Always "onfido" currently. |
status | string | Provider status string — see Provider status values. |
workflowRunId | string | undefined | Onfido workflow run ID. Present when the run is trackable. |
{
"id": "evt_2d5a3f92b04e4e67c4g8f901de23456b",
"type": "kyc.provider.completed",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"userId": "6a25cdac36bc6230704b5b59",
"provider": "onfido",
"status": "complete",
"workflowRunId": "5d9b5f73-4b43-4d54-8c2c-86c0f8a53f4f"
},
"createdAt": "2026-06-07T09:20:11.208Z"
}
kyc.provider.failed
Trigger: The identity provider (Onfido) returns a declined or error outcome for the user’s verification run.
Use cases:
- Flag the user account for manual review.
- Notify the user that additional steps are required.
- Track failure rates per reason in your analytics.
Payload schema
| Field | Type | Description |
|---|
userId | string | User whose verification failed. |
provider | "onfido" | Identity provider name. Always "onfido" currently. |
status | string | Provider failure status — see Provider status values. |
workflowRunId | string | undefined | Onfido workflow run ID. Present when the run is trackable. |
{
"id": "evt_3e6b4g03c15f4f78d5h9g012ef34567c",
"type": "kyc.provider.failed",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "sandbox",
"data": {
"userId": "6a25cdac36bc6230704b5b59",
"provider": "onfido",
"status": "declined",
"workflowRunId": "5d9b5f73-4b43-4d54-8c2c-86c0f8a53f4f"
},
"createdAt": "2026-06-07T09:20:11.208Z"
}
KYC status values
The status field in KYC payloads reflects the internal KYC lifecycle state:
| Value | Meaning |
|---|
"" / "pending" | KYC record exists but not yet submitted or reviewed. |
"approved" | KYC passed — provider approved and admin accepted. |
"rejected" | KYC rejected by admin or provider. |
"cancelled" | KYC process cancelled. |
"locked" | Case locked by admin — user cannot edit. |
Provider status values
Onfido returns these status strings, mapped to kyc.provider.completed (approved) or kyc.provider.failed (rejected):
| Value | Outcome event | Meaning |
|---|
"complete" / "approved" / "clear" | kyc.provider.completed | Identity verified successfully. |
"declined" / "rejected" | kyc.provider.failed | Verification declined by provider. |
"abandoned" / "withdrawn" | kyc.provider.failed | Run abandoned before completion. |
"error" | kyc.provider.failed | Provider-side processing error. |
"failed" / "incorrect" / "insufficient" / "expired" | kyc.provider.failed | Document or data quality failure. |
Account events
Account events cover every stage of an escrow account — from creation and invitation through document submission, admin review, source closures, and case management.
The party key in account payloads depends on accountType. For real_estate accounts the keys are buyer and seller. For all other types (e.g. permanent, construction) the key is customer.
account.created
Trigger: A new escrow account is created by an admin or via the API. The buyer (and optionally seller for real_estate) are linked at creation time.
Use cases:
- Register the account in your system before any parties have accepted.
- Send a welcome notification to your CRM.
- Start a compliance timer.
Payload schema
| Field | Type | Description |
|---|
accountId | string | Unique account ID. |
accountType | string | Account type — "real_estate", "permanent", "construction". |
accountTitle | string | Human-readable account title. |
tenantId | string | Owning tenant. |
environmentId | string | null | Environment. |
status | string | Account status — see Account status values. |
customer | PartyObject | undefined | Present for non-real_estate accounts. |
buyer | PartyObject | undefined | Present for real_estate accounts. |
seller | PartyObject | undefined | Present for real_estate accounts. |
createdAt | string | ISO 8601 timestamp. |
updatedAt | string | ISO 8601 timestamp. |
PartyObject schema
| Field | Type | Description |
|---|
id | string | User ID of the party. |
accepted | boolean | Whether this party has accepted the invitation. |
expiresAt | string | null | Invitation token expiry (ISO 8601). |
{
"id": "evt_9998f3a720854483a5c5fdb949638b9d",
"type": "account.created",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a25cdcc36bc6230704b5bce",
"accountType": "permanent",
"accountTitle": "Testing Demo Account",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"status": "invited",
"customer": {
"id": "6a25cdac36bc6230704b5b59",
"accepted": false,
"expiresAt": "2026-06-14T20:00:12.325Z"
},
"createdAt": "2026-06-07T20:00:12.414Z",
"updatedAt": "2026-06-07T20:00:12.414Z"
},
"createdAt": "2026-06-07T20:00:12.449Z"
}
account.invited
Trigger: An invitation email is dispatched to a participant. Fires once per party — separately for buyer/customer and seller.
Use cases:
- Log invitation timestamps for compliance audit trails.
- Track invitation delivery metrics per role.
- Trigger a parallel onboarding workflow in your system.
Payload schema
| Field | Type | Description |
|---|
accountId | string | Account the invitation belongs to. |
userId | string | User who was invited. |
email | string | Email address the invitation was sent to. |
name | string | Display name of the invited user. |
role | "customer" | "buyer" | "seller" | Role of the invited party in this account. |
{
"id": "evt_7a2bc1d304e44091baf1c2de3f4a5678",
"type": "account.invited",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a25cdcc36bc6230704b5bce",
"userId": "6a25cdac36bc6230704b5b59",
"email": "jane@example.com",
"name": "Jane Smith",
"role": "customer"
},
"createdAt": "2026-06-07T20:00:12.460Z"
}
account.opened
Trigger: A participant clicks their invitation link and the invitation page loads. The party has not yet accepted — this is a view event, not an acceptance event.
Use cases:
- Detect when a party has seen the invitation (engagement tracking).
- Start a follow-up timer if acceptance does not follow within N hours.
- Audit trail for compliance.
Payload schema
| Field | Type | Description |
|---|
accountId | string | Account whose invitation was opened. |
role | "customer" | "buyer" | "seller" | Role of the party who opened the link. |
openedAt | string | ISO 8601 timestamp when the link was opened. |
{
"id": "evt_2a3bc4d5e6f74812abc0d1ef2a3b4c5d",
"type": "account.opened",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a1ea31b892791af056f46bd",
"role": "buyer",
"openedAt": "2026-06-02T09:45:11.108Z"
},
"createdAt": "2026-06-02T09:45:11.109Z"
}
account.accepted
Trigger: A participant accepts the invitation. For real_estate accounts, fires once per party (buyer and seller independently). Account status advances to "accepted" only when all required parties have accepted.
Use cases:
- Gate access to document upload flows until all parties accept.
- Notify stakeholders when a party joins.
- Progress a workflow state machine.
Payload: Full account snapshot — same schema as account.created with updated accepted flag and status.
{
"id": "evt_4c5de6f7a8b94c23bcd1e2fg3h4i5j6k",
"type": "account.accepted",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a25cdcc36bc6230704b5bce",
"accountType": "permanent",
"accountTitle": "Testing Demo Account",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"status": "accepted",
"customer": {
"id": "6a25cdac36bc6230704b5b59",
"accepted": true,
"expiresAt": "2026-06-14T20:00:12.325Z"
},
"createdAt": "2026-06-07T20:00:12.414Z",
"updatedAt": "2026-06-07T20:10:45.000Z"
},
"createdAt": "2026-06-07T20:10:45.012Z"
}
account.status.changed
Trigger: The account status transitions to any new value. Fires on admin close, admin reopen, and when both parties accept.
Use cases:
- Drive a workflow state machine (e.g. move to
"completed" after close).
- Send status update emails to participants.
- Update your internal CRM or compliance dashboard.
Payload: Full account snapshot — same schema as account.created with the new status.
Account status values
| Value | Meaning |
|---|
"invited" | Account created; invitations sent. No party has accepted yet. |
"pending" | At least one party has accepted; waiting on remaining parties. |
"accepted" | All required parties have accepted. Documents can now be submitted. |
"completed" | Admin has closed the account after all sources are verified. |
{
"id": "evt_5d6ef7a8b9c04d34cde2f3gh4i5j6k7l",
"type": "account.status.changed",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a25cdcc36bc6230704b5bce",
"accountType": "permanent",
"accountTitle": "Testing Demo Account",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"status": "completed",
"customer": {
"id": "6a25cdac36bc6230704b5b59",
"accepted": true,
"expiresAt": "2026-06-14T20:00:12.325Z"
},
"createdAt": "2026-06-07T20:00:12.414Z",
"updatedAt": "2026-06-07T21:00:00.000Z"
},
"createdAt": "2026-06-07T21:00:00.015Z"
}
account.archived
Trigger: An admin archives the account. Archived accounts are read-only — no modifications are permitted until unarchived.
Use cases:
- Move the account to an archived view in your dashboard.
- Suppress notifications for archived accounts.
- Audit who archived what and when.
Payload schema
| Field | Type | Description |
|---|
accountId | string | ID of the archived account. |
archivedBy | string | User ID of the admin who archived the account. |
{
"id": "evt_6e7fg8h9i0j14e45def3g4hi5j6k7l8m",
"type": "account.archived",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a1ea31b892791af056f46bd",
"archivedBy": "69f9cfbba364e4043805910e"
},
"createdAt": "2026-06-02T10:02:04.300Z"
}
account.unarchived
Trigger: An admin restores a previously archived account. The account becomes editable again.
Use cases:
- Restore the account to the active view in your dashboard.
- Re-enable downstream notifications and workflows.
Payload schema
| Field | Type | Description |
|---|
accountId | string | ID of the unarchived account. |
unarchivedBy | string | User ID of the admin who unarchived the account. |
{
"id": "evt_7f8gh9i0j1k24f56efg4h5ij6k7l8m9n",
"type": "account.unarchived",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a1ea31b892791af056f46bd",
"unarchivedBy": "69f9cfbba364e4043805910e"
},
"createdAt": "2026-06-02T11:05:00.300Z"
}
account.deleted
Trigger: An admin permanently deletes an account. This also cascades to delete all associated document review files. This action is irreversible.
Use cases:
- Hard-delete the account record from your system.
- Clean up downstream references (CRM entries, linked workflows).
- Emit a GDPR deletion audit record.
Payload schema
| Field | Type | Description |
|---|
accountId | string | ID of the deleted account. |
accountType | string | Account type at time of deletion. |
status | string | Account status at time of deletion. |
{
"id": "evt_2efb0dbf1b9042a6bdc050c6ee2f8375",
"type": "account.deleted",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a1ea31b892791af056f46bd",
"accountType": "real_estate",
"status": "invited"
},
"createdAt": "2026-06-02T10:02:04.300Z"
}
account.document.submitted
Trigger: A user submits their documents for admin review (submitForReview: true). Fires on both initial submission and re-submission after corrections.
Use cases:
- Notify the compliance team that documents are ready to review.
- Start a review SLA timer.
- Transition the account to
"under_review" in your system.
Payload schema
| Field | Type | Description |
|---|
accountId | string | Account the documents belong to. |
userId | string | User who submitted the documents. |
status | string | Document record status after submission — typically "under_review". |
submittedAt | string | null | ISO 8601 timestamp of the submission. |
{
"id": "evt_7f8g9h0i1j2k3l4m5n6o7p8q",
"type": "account.document.submitted",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"accountId": "6a1ea31b892791af056f46bd",
"userId": "6a25cdac36bc6230704b5b59",
"status": "under_review",
"submittedAt": "2026-06-08T10:06:15.635Z"
},
"createdAt": "2026-06-08T10:06:15.684Z"
}
account.document.reviewed
Trigger: An admin approves or rejects a specific document. Fires once per document decision.
Use cases:
- Notify the user their document was approved or needs correction.
- Update a document status badge in your portal.
- Track review turnaround times per document type.
Payload schema
| Field | Type | Description |
|---|
reviewId | string | Internal document review record ID. |
accountId | string | Account the document belongs to. |
userId | string | User who owns the document. |
documentCode | string | Dot-notation path identifying the document field (e.g. "bankStatement.statementS3Key"). |
displayName | string | Human-readable document name (e.g. "Bank Statement"). |
status | "approved" | "rejected" | Admin decision. |
feedback | string | null | Rejection reason or admin note. null if approved. |
{
"id": "evt_8g9h0i1j2k3l4m5n6o7p8q9r",
"type": "account.document.reviewed",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"reviewId": "6a26851e64d94ca57870e73c",
"accountId": "6a1ea31b892791af056f46bd",
"userId": "6a25cdac36bc6230704b5b59",
"documentCode": "bankStatement.statementS3Key",
"displayName": "Bank Statement",
"status": "approved",
"feedback": null
},
"createdAt": "2026-06-08T10:10:00.123Z"
}
account.document.requested
Trigger: An admin requests an additional document from the user.
Use cases:
- Notify the user a specific document has been requested.
- Add a pending task to the user’s document checklist in your UI.
- Track admin-initiated document requests separately from standard requirements.
Payload schema
| Field | Type | Description |
|---|
reviewId | string | Internal document review record ID created for this request. |
userId | string | User the document is being requested from. |
documentCode | string | Dot-notation code for the requested document (e.g. "requested.proof_of_address"). |
displayName | string | Human-readable name of the requested document. |
note | string | null | Instructions the admin provided along with the request. |
{
"id": "evt_9h0i1j2k3l4m5n6o7p8q9r0s",
"type": "account.document.requested",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"reviewId": "6a26851e64d94ca57870e73d",
"userId": "6a25cdac36bc6230704b5b59",
"documentCode": "requested.proof_of_address",
"displayName": "Proof of Address",
"note": "Please upload a utility bill or bank statement dated within the last 3 months."
},
"createdAt": "2026-06-08T10:12:00.456Z"
}
account.case.locked
Trigger: An admin locks the user’s case. While locked, the user cannot upload documents or take any document action.
Use cases:
- Prevent further user activity while a compliance review is in progress.
- Display a “case locked” banner in your portal.
- Log the lock event with actor identity for audit trails.
Payload schema
| Field | Type | Description |
|---|
userId | string | User whose case was locked. |
accountId | string | Most recent account associated with this user. |
accountTitle | string | Title of that account. |
lockedBy | string | Email or identifier of the admin who performed the lock. |
lockedAt | string | ISO 8601 timestamp of the lock action. |
{
"id": "evt_1j2k3l4m5n6o7p8q9r0s1t2u",
"type": "account.case.locked",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"userId": "6a267b273efc540f27171829",
"accountId": "6a1ea31b892791af056f46bd",
"accountTitle": "Testing Demo Account",
"lockedBy": "admin@example.com",
"lockedAt": "2026-06-08T10:20:00.000Z"
},
"createdAt": "2026-06-08T10:20:00.012Z"
}
account.case.unlocked
Trigger: An admin unlocks a previously locked case. The user can resume document uploads.
Use cases:
- Remove the “case locked” banner in your portal.
- Re-enable document upload flows for the user.
- Log who unlocked the case and when.
Payload schema
| Field | Type | Description |
|---|
userId | string | User whose case was unlocked. |
accountId | string | Most recent account associated with this user. |
accountTitle | string | Title of that account. |
unlockedBy | string | Email or identifier of the admin who unlocked the case. |
unlockedAt | string | ISO 8601 timestamp of the unlock action. |
{
"id": "evt_2k3l4m5n6o7p8q9r0s1t2u3v",
"type": "account.case.unlocked",
"tenantId": "bc41c6ab-7206-4033-b632-4d1cfa86d840",
"environmentId": "69f9b5fa0600ccbf9c677005",
"environmentType": "live",
"data": {
"userId": "6a267b273efc540f27171829",
"accountId": "6a1ea31b892791af056f46bd",
"accountTitle": "Testing Demo Account",
"unlockedBy": "admin@example.com",
"unlockedAt": "2026-06-08T11:00:00.000Z"
},
"createdAt": "2026-06-08T11:00:00.015Z"
}
Pattern matching
Subscribe to individual events or entire namespaces:
| Pattern | Matches |
|---|
kyc.submitted | Exactly kyc.submitted |
kyc.provider.* | kyc.provider.completed and kyc.provider.failed |
kyc.* | All five KYC events |
account.document.* | account.document.submitted, account.document.reviewed, account.document.requested |
account.source.* | account.source.closed and account.source.reopened |
account.case.* | account.case.locked and account.case.unlocked |
account.* | All 14 account events |
* | Every event across all namespaces |
Delivery response codes
Zquence interprets your endpoint’s HTTP response as follows:
| Your response | Zquence behaviour |
|---|
2xx (200–299) | Delivery marked success. No retry. |
4xx / 5xx | Delivery marked failed. Retried with exponential backoff while attempts remain. |
| Timeout (> 10 s) | Delivery marked failed. Retried with exponential backoff while attempts remain. |
| Connection refused | Delivery marked failed. Retried. |
Even 400 Bad Request and 403 Forbidden are treated as failures and retried. Your handler should return 200 and discard events it does not recognise rather than returning 4xx.
To safely handle duplicate deliveries (from retries or manual replays), store event.id in a deduplication table with a TTL of at least 7 days and skip processing if the ID is already present.