Configure webhook URLs from the business dashboard. These URLs are used for Rivo Business event delivery once outbound webhook dispatch is enabled for your integration.

Current rollout note

Webhook URL management is available today. Before relying on live partner webhook events, confirm with Rivo that outbound delivery has been enabled for the event types you need.

Manage webhook URLs

Webhook management uses the business dashboard JWT flow, not API-key signing.

Create webhook

targetUrl must be a valid http or https URL. Duplicate URLs for the same business are rejected. Example response:

List webhooks

Example response:

Delete webhook

Example response:

Delivery format

Every webhook is an HTTP POST to your targetUrl with a JSON body in this envelope:
Headers:
Rivo waits up to 5 seconds for a response. Return a 2xx status once you have stored the event. Process it asynchronously if handling takes longer. Events can arrive more than once and out of order. Deduplicate using the event name plus the resource reference (or id), and always treat the latest status you read from the API as the source of truth.

Verify the signature

Compute an HMAC-SHA512 of the raw request body using your webhook secret and compare it with the x-webhook-signature header before trusting the payload.
Use the raw body exactly as received. Re-serializing parsed JSON can change the bytes and break verification.

Events

payment.created

Sent after POST /payments/initiate succeeds.

payment.completed

Sent when the checkout is paid in full. amountSettled is what reaches your balance after fee.

payment.failed

Sent when a checkout fails or expires before full payment. reason explains why.
Sent after POST /payment-links succeeds. data is the payment link.
Sent when a payment is received on a payment link. data is the payment link, with the received payment under payment.
For crypto links, payment.sender is replaced by payment.cryptoSender with the sending address, and the payment includes network and transactionHash. Sent when a payment link expires, including when you call POST /payment-links/{id}/expire.

transfer.created

Sent after POST /transfers/ngn accepts and queues a transfer. data has the same shape as GET /transfers/ngn/{reference}.

transfer.completed

Sent when the recipient bank account has been paid.

transfer.failed

Sent when the transfer cannot be completed. reason explains why. Debited funds are returned to your balance.

virtual-account.created

Sent when a customer virtual account is ready to receive funds. data has the same shape as the matching GET /virtual-accounts/... response, plus currency. NGN account:
Temporary NGN accounts also include expiresAt. USD account:

virtual-account.rejected

Sent when a virtual account request is rejected, for example when customer verification fails. reason explains why. You can retry with the same reference after correcting the customer details.
NGN rejections have the NGN account shape with accountNumber, accountName and bankName set to null.

Testing webhooks on staging

On staging (https://sandbox-api.userivo.co), virtual accounts are simulated so you can test your webhook handling end to end:
  • NGN accounts (/virtual-accounts/ngn/temporary and /virtual-accounts/ngn/permanent) are created instantly with dummy account details, and virtual-account.created is sent straight away.
  • USD accounts (/virtual-accounts/usd) return pending and under review as in production. About 3 seconds later the account is approved with dummy bank details and virtual-account.created is sent.
  • Use a reference containing reject (for example ref_reject_001) to simulate a rejection. NGN requests then return 400 immediately; USD requests still return pending and under review. In both cases virtual-account.rejected is sent.
Sandbox account numbers cannot receive real money.

Security

Keep webhook secrets on your backend only. Verify the x-webhook-signature header before trusting a payload, and return a 2xx response only after your server accepts the event. To rotate a webhook secret today, delete the webhook URL and create it again. Store the new secret on your backend before enabling event handling for that URL.

Supported IP allowlist

Supported IPs are configured from the business dashboard and apply to signed Rivo Business API-key requests. If no supported IPs are configured, signed API-key requests are accepted from any IP address after normal authentication and signature checks pass. Once at least one supported IP is configured, Rivo only accepts signed API-key requests from the configured IP addresses.

Add supported IP

ipAddress must be a valid IPv4 or IPv6 address. Each business can configure up to 5 supported IP addresses. Example response:

List supported IPs

Example response:

Delete supported IP

Example response:
If a signed API-key request comes from an IP address outside the configured allowlist, Rivo returns: