data field contents for each event type.
Quick Reference
Persons
person.created
JSON
person.updated
JSON
Offboarding
Offboarding events track a person’s lifecycle from active employment through exit and potential reinstatement. See Offboard Workers for the full guide.person.offboarding.scheduled
JSON
person.offboarding.cancelled
JSON
person.offboarding.completed
JSON
person.reinstated
JSON
Users
user.created
JSON
user.updated
The payload includes atype field indicating what was updated.
JSON
user.profile.updated
JSON
user.kyc.updated
Fired on every KYC status change. Thetype field indicates which verification component changed.
JSON
user.kyc.expiry
Fired when a user’s identity document is approaching expiry or has expired.JSON
Payroll
Thepayroll.status.updated event fires for the values below. The webhook uses its own status vocabulary — the third column shows the corresponding status on GET /v1/payrolls/{id}. See Payroll Lifecycle for the full lifecycle.
Awaiting Funds is the status a payroll holds between the approved and scheduled events — receiving approved with no scheduled following shortly means the payroll is waiting on funds; it proceeds automatically once the business balance covers it. No webhook fires for Rejected or Deleted; poll GET /v1/payrolls/{id} to detect those.payroll.created
JSON
payroll.status.updated
JSON
Transactions
Everytransaction.* event carries a type field identifying the kind of transaction:
And a
recipientType field identifying what kind of entity recipientId refers to:
transaction.initiated
JSON
transaction.processing
Fires once per transaction, when it passes compliance checks and is being processed. Most transactions pass checks automatically within seconds oftransaction.initiated; transactions held for manual review can stay in the initiated state for longer before this event fires.
JSON
Instantly-settling transactions (for example
PAYROLL_FEE wallet debits) can move straight from transaction.initiated to transaction.succeeded without a transaction.processing event, so treat this event as optional in the lifecycle. It is delivered at most once per transaction.transaction.rfi.updated
Fires when additional information is needed for a transaction under review, and again when that information has been provided. While a request for information is open, the transaction stays in the initiated state; once review completes, the transaction continues its normal lifecycle (transaction.processing on approval, transaction.failed otherwise).
status is RFI_REQUESTED when information is being requested — actionRequired describes what is needed — and RFI_PROVIDED once it has been submitted (the actionRequired field is omitted).
JSON
Use this event to surface “action needed” states in your UI — a transaction with an open request for information will otherwise look like a long-running initiated transaction.
transaction.succeeded
- PAYROLL
- DEPOSIT
- PAYROLL_FEE
JSON
transaction.failed
JSON
transaction.failed with isReturned: true:
JSON
The
type field tells you the kind of transaction. reference is a stable identifier from the source system: payrollId for PAYROLL, the deposit reference for DEPOSIT, the business payout reference for PAYOUT. recipientId is the ID of whoever is receiving funds — use recipientType to interpret it (a userId when recipientType: "USER", a businessId when BUSINESS, a personId when EMPLOYEE or CONTRACTOR).Instant Pay
instant-pay.succeeded
JSON
Contracts
contract.created
JSON
contract.signed
JSON
contract.status.updated
JSON
Invoices
These events cover the contractor self-submitted invoice lifecycle: a contractor raises an invoice billed to your business, you review it, and it is paid.invoice.contractor.submitted is your cue to review — call POST /v1/invoices/{invoiceId}/review to approve or reject it. Only invoices with source of CONTRACTOR_SUBMITTED fire these events. reason is present only on invoice.contractor.rejected.
- invoice.contractor.submitted
- invoice.contractor.approved
- invoice.contractor.rejected
- invoice.contractor.paid
JSON
Reimbursements
These events cover the reimbursement lifecycle: a worker submits a reimbursement — or you create one viaPOST /v1/reimbursements — you review it, and it is paid out. reimbursement.submitted is your cue to review — call POST /v1/reimbursements/{reimbursementId}/review to approve or reject it. Approving disburses the reimbursement from the sourceCurrency wallet, and reimbursement.paid follows once it settles. reason is present only on reimbursement.rejected; amount is the reimbursed (destination) amount.
- reimbursement.submitted
- reimbursement.approved
- reimbursement.rejected
- reimbursement.paid
JSON
Virtual Accounts
A virtual account can belong to either a user or a business. Exactly one ofuserId or businessId will be present.
virtual-account.requested
JSON
virtual-account.submitted
JSON
virtual-account.created
JSON
Business
business.kyb.reviewed
Sent when a KYB submission has been reviewed. May indicate approval or that additional information is needed.JSON
needs-additional-info responses.
business.kyb.rejected
Sent when a KYB submission has been permanently rejected. This is a terminal state — the business cannot resubmit.JSON
business.kyb.completed
JSON
business.basicinfo.updated
JSON
External Accounts
external-account.added
- Instantly verified
- Awaiting micro-deposit
Ready to use for deposits straight away.
status is active for instantly verified accounts, or needs_confirmation for accounts still awaiting micro-deposit verification. This event fires as soon as the account is submitted, so it is the signal to move a customer off your “set up direct debit” prompt.
microdepositInfo is present only while an account is awaiting verification. type is descriptor_code (a code on the statement) or amounts (two small deposits to read back), and arrivalDate is a Unix timestamp for when the deposit is expected — enough to render your interim copy without a follow-up API call. To collect the code or amounts, send the account holder to the link from Generate External Account Link with mode set to verification.
Poll Get External Accounts if you need to reliably detect the needs_confirmation → active transition: the follow-up event carries a different id for the same account, so the two cannot be correlated by id alone.
external-account.removed
JSON
Statutory Compliance
Filing, remittance, and requirement events share a common structure. TheresourceType and resourceId fields identify the affected resource.
filing.created
JSON
filing.blocked
JSON
filing.approved
JSON
filing.accepted
JSON
remittance.completed
JSON
requirement.satisfied
JSON