Guides
/
Webhooks

Webhooks

Receive real-time notifications for payments, disbursements, KYC, and tax compliance events

Vivamo sends webhooks at each stage of a payment or disbursement, when a customer's KYC status changes, and when tax compliance actions (W-9) are required or completed. Webhooks are the most reliable way to track transaction outcomes, especially for asynchronous payment methods like bank transfers.

Registering a webhook

Register your webhook endpoint using the API:

When a webhook is created, Vivamo generates a unique secret key for HMAC signature verification. This key is returned in the creation response — store it securely, as it cannot be retrieved again.

You can also list, update, and delete your registered webhooks.

Updating a webhook

Use PATCH /v1/operators/webhooks/{webhookId} to update a webhook's URL, status, event types, or custom headers without rotating the HMAC secret key. If you need to rotate the secret, delete the webhook and create a new one.

Duplicate webhooks are not allowed. If another webhook already exists with the same URL and overlapping event types, the request will be rejected with a 409 status.

Webhook authentication

Every webhook includes an HMAC-SHA512 signature in the signature HTTP header. This lets you verify that the payload came from Vivamo and was not tampered with.

Verifying the signature

The signature is generated by signing the JSON request body with your webhook's secret key using HMAC-SHA512:

Custom headers

In addition to the HMAC signature, any custom headers you provided during webhook registration are included with every delivery. You can use these as an extra layer of verification (e.g. a pre-shared key).

Retries and responding

Return a 200 status code from your webhook endpoint to acknowledge receipt. If your server returns any other status (or doesn't respond), Vivamo retries delivery up to 5 times with increasing delays:

AttemptDelay
1st retry
1 minute
2nd retry
2 minutes
3rd retry
3 minutes
4th retry
4 minutes
5th retry
5 minutes

After 5 failed attempts, the webhook is marked as failed. Undelivered webhooks are retained for 24 hours.

Event types

Every webhook payload includes an eventType field that identifies the category of event. Use this field to route incoming webhooks to the appropriate handler.

eventTypeDescription
transaction
A payment or disbursement status change. Use the transactionType field to distinguish between "payment" and "disbursement".
kyc_verification
A customer's KYC verification status has changed.
customer_w9_required
A customer needs to complete a W-9 form before disbursements can proceed. Includes a w9CaptureUrl for the form if you wish to present this (not required).
customer_w9_completed
A customer has successfully submitted their W-9 form.

Webhook flows

The diagrams below show the payment, disbursement, and KYC verification lifecycles end to end. Each has three lanes: your backend, the customer in the SDK, and Vivamo. Processor and bank activity happens behind Vivamo, so it appears as notes on the Vivamo lane. Webhook deliveries are the amber-highlighted arrows into the Your backend lane, so you can read off exactly when your endpoint gets called, and how that varies by payment method and operator configuration.

In the payment and disbursement diagrams, every webhook: arrow except the W-9 ones is a transaction event. Route these by transactionType ("payment" or "disbursement") and status. The W-9 arrows are the separate customer_w9_required and customer_w9_completed events, and the KYC diagram's arrows are kyc_verification events. Click any diagram to view it full size.

Payment flow

Notes on the payment branches:

  • Card payments are authorized synchronously, so the customer sees the outcome in the SDK right away. A decline or error sends the failed webhook immediately. The success webhook is sent once the processor confirms the charge, which normally happens shortly after the customer sees the result.
  • Bank (ACH) payments stay pending until the bank network reports back, which can take longer. Webhooks are the reliable way to track these.
  • declined, voided, and refunded only occur on Pay By Bank payments. voided and refunded can arrive after you have already received a success webhook for the same payment.
  • If your configuration requires KYC, a customer who completes verification during checkout also triggers a separate kyc_verification webhook. See KYC Verification.

Disbursement flow

Notes on the disbursement branches:

  • The pending-validation webhook is always sent, even when auto-approve is enabled for your account. With auto-approve on, you receive pending-validation and approved in quick succession with no action needed on your side.
  • rejected records your own decision and the disbursement never reaches a processor. failed and declined happen on the processor side after approval.
  • Bank and card payouts settle asynchronously, so there is a gap between the approved webhook and the terminal one. Pay By Bank payouts are typically instant.
  • The W-9 branch only applies when personal tax reporting is enabled for your account, and only for a customer who does not yet have a W-9 on file. See Personal Tax.

KYC verification flow

Notes on the KYC branches:

  • KYC only runs when your operator configuration requires it, and it is scoped to payments, disbursements, or both. A customer verified once stays verified, even across operators.
  • The webhook status values are verified, under-review, and rejected (with a reason field). Note the hyphen in under-review: the webhook wire format hyphenates, while the persisted status you read back from Get Customer KYC Info uses under_review.
  • kyc_verification webhooks are sent to every operator the customer is connected to. You may receive one for a verification the customer completed while transacting with a different operator.
  • Most results come back while the customer is still in the SDK. Some provider checks finish asynchronously, in which case the webhook arrives when the provider reports back.
  • See the KYC Verification guide for the full integration options, including the kyc-completed SDK event.

Sample Webhook Payloads

Payment results

Payment webhooks use the same structure regardless of payment method. The status field can take the following values:

StatusDescription
success
The payment completed successfully.
failed
The payment did not complete. A subStatus will be included with the reason from the gateway or processor (e.g. "Insufficient balance", "Invalid CVV", "AVS failure").
declined
The payment was declined by the bank or processor. Specific to pay-by-bank methods that distinguish a decline from a generic failure.
voided
A previously authorized payment was voided before settlement.
refunded
A previously settled payment was refunded.

Success

Failed

Disbursements

Disbursements emit a webhook at every lifecycle transition. The status field tells you which transition occurred:

StatusDescription
pending-validation
A new disbursement was created and is awaiting your decision via Proceed With Disbursement.
approved
You approved the disbursement (allow=true); processor work is in progress.
rejected
You rejected the disbursement (allow=false). Terminal — the disbursement is never sent to a processor.
success
The processor confirmed the disbursement was sent. Terminal.
failed
The processor returned an error during processing. A subStatus field is included with the reason. Terminal.
declined
The processor reached the bank or network and got an explicit decline (specific to pay-by-bank). Terminal.

rejected, failed, and declined are distinct terminal states: rejected reflects your own decision and never reaches a processor, failed indicates a processor-side error during processing, and declined indicates the processor reached the bank/network and was told no. Each fires its own webhook.

The webhook status of approved corresponds to a persisted disbursement status of pending on the disbursement record itself (as returned by Get Disbursement Intent Status and described in the OpenAPI Disbursement schema). The webhook uses approved to mirror rejected and make the operator-decision event unambiguous; the persisted status remains pending because the disbursement is now awaiting processor work.

Creation

Approved

Sent when you approve the disbursement via Proceed With Disbursement with allow=true. The disbursement is now being processed; expect a terminal success, failed, or declined webhook to follow.

Rejected

Sent when you reject the disbursement via Proceed With Disbursement with allow=false. The disbursement is not sent to a processor. Terminal.

Result: Success

Result: Failed

Result: Declined

Customer KYC verification status change

KYC verification results are sent as webhooks when a customer's status changes. See the KYC Verification guide for more detail.

Possible status values are:

StatusDescription
verified
The verification was successful.
under-review
Manual review is required.
rejected
The verification failed. The reason field will provide more details on the failure.

Verified payload:

Rejected payload:

Customer W-9 tax compliance

W-9 webhooks are sent when a customer needs to complete tax documentation for disbursements, and when they have successfully submitted their form. These events only fire for operators with personal tax reporting enabled.

Each W-9 webhook carries a status field that tells you where the customer is in the W-9 process:

StatusEventDescription
pending
customer_w9_required
The customer needs to submit a W-9 before the disbursement can proceed.
completed
customer_w9_completed
The customer has submitted their W-9.

W-9 required:

Sent when a customer attempts a disbursement but has not yet completed their W-9. The w9CaptureUrl is a one-time link for the customer to fill out the form. Handling this is not required on your end, but you can choose to present the link to the customer to streamline the process.

Warning: The w9CaptureUrl will expire, so it is not advised that this is stored.

W-9 completed:

Sent when a customer has successfully submitted their W-9 form.

Built with