Register your endpoint
Create or replace your webhook
string
required
The HTTPS endpoint that receives events.
- One endpoint per account. Calling
POST /business/webhookagain replaces your URL and issues a new secret. - Save the
secret. You need it to verify signatures. - Every event goes to your URL. There’s no per-event subscription, so ignore event types you don’t handle.
- Right after you save a webhook, Yativo sends a
webhook_updatedtest event to the new URL.
Other webhook endpoints
Verify the signature
Every request carries aSignature header:
Timestamp header (Unix seconds). It isn’t part of the signature.
Payload envelope
Every event uses this envelope:event.type names the event. payload holds the event data. The envelope has no delivery ID or timestamp, so use fields inside payload, such as id, event_id, status and created_at, to deduplicate and order events.
The customer object
Every payload includescustomer_id and a customer object, so you know whose event it is without another API call:
customer_type is individual or business. customer is null when the event isn’t about one of your customers, for example user.updated. Only these five fields are sent.
Event catalog
New event types are added over time. Ignore ones you don’t recognize.
Payments
deposit.created and deposit.updated
status is pending, processing, success, failed, cancelled or expired.
Deposits with a currency conversion also include currency_from, currency_to, amount_from, amount_to and deposit_currency. Only these fields and the ones above are sent.
payout.updated
Sent whenever a payout changes status. There’s no payout.created event. The first event you see is usually pending or processing.
status is pending, processing, completed, failed, cancelled or refunded. beneficiary fields vary by payout rail and currency. reference is the payment reference you sent, or null.
virtual_account.deposit
amount is the net amount credited. amount_recevied is the gross amount received, before fees.
virtual_account.created and virtual_account.updated
customer is null when the account belongs to your business.
virtual_account.deleted
Sent when you delete a virtual account. The account no longer accepts funds. The payload has the same fields as virtual_account.created.
metadata.created, metadata.updated and tracking.created
Customers
customer.created and customer.updated
customer.updated is sent when one of these fields or the customer’s KYC status changes.
endorsement.updated
endorsements is the customer’s full current list, not only the one that changed. Compare it with your stored copy. This is the only event that reports KYC and KYB results. A service is available when its endorsement is approved. See Track verification with endorsements.
Stablecoin deposits
crypto.wallet.created and wallet.deleted
is_customer is false, the address belongs to your business and customer is null. wallet.deleted has the same payload with wallet_status: "deleted". Funds sent to a deleted address can’t be recovered.
crypto.deposit.completed
transaction_hash. transaction_id is Yativo’s reference and isn’t always the hash. transaction_hash is null if the hash isn’t available.
The older crypto_deposit event has the same payload plus user_id. Handle both names.
Virtual cards
Everyvirtualcard.* payload includes:
event_id: unique per event, and the same on every redelivery. Use it to deduplicatecard_id: the card ID you pass to the card endpointscustomer_idandcustomer: the cardholder
4.5 means $4.50).
KYC
kyc_status is under_review, approved or rejected. Show rejection_details[].message to your customer and branch on code.
Card lifecycle
When you terminate a card through the API, the remaining balance reaches your wallet when
virtualcard.terminated.refund arrives, not in the terminate response.
Funding
reference matches the reference returned by your top-up or withdrawal request.
Card transactions
Branch on
event.type first, then on transaction_type.
A cross-border purchase sends virtualcard.transaction.crossborder twice with the same reference. The first, cross_border_pending, includes fee_amount, which is debited from your USD wallet. The second, cross_border_settled, moves the purchase amount off the card.
Declines
After 2 failed charges, the card is frozen and you receive
virtualcard.deactivated.
Corporate cards
business_spend_card.* events cover corporate cards. card_id is your card ID. Events not tied to one of your customers have "customer": null.
transaction_id is the ID of the record in GET /business/spend-card/transactions, which you use to attach notes and invoices.
Account and platform events
Use
webhook_updated to confirm your endpoint receives events and your signature check works.
In user.updated, business has only business_legal_name, business_operating_name, business_type and country, each when it’s set. Documents, directors, shareholders and verification results are never included. Signing in or changing security settings doesn’t send user.updated.
Respond to a webhook
- Return a
2xxstatus as soon as you’ve stored or queued the event. Do slow work afterwards. - Respond within 3 seconds. Some events are sent while the API call that caused them is still running, so a slow endpoint can slow that call down.
- Yativo doesn’t read your response body. An empty
200is enough. - A non-
2xxstatus, a connection error or a timeout is a failed delivery. Failed deliveries are retried up to 3 times in total, with exponential backoff, then dropped. Resend any event you missed.
Node.js
Delivery log
Every delivery attempt is logged:number
Results per page.
GET /business/events/show/{eventId} returns 404 Webhook event not found when the ID isn’t in your log.
Resend an event
eventId is the id from the delivery log, not an ID from inside the event’s payload.
- The original payload is resent, signed with your current secret, to the URL you have registered now. Fields that events no longer carry are left out.
- The resend appears as a new entry in the delivery log.
404 Webhook event not foundmeans the ID isn’t in your log.400 No webhook endpoint is configured for your accountmeans you have no webhook.
Test in sandbox
Send sample events to your registered URL without creating real records:type is one of payin, payout, virtual_account, virtual_account_created, virtual_account_updated, customer, customer_updated, endorsement, metadata_created, metadata_updated, webhook_updated, user, tracking, payin_method_enabled, payin_method_disabled, payout_method_enabled, payout_method_disabled, crypto_wallet, crypto_deposit or wallet_deleted.
payin sends deposit.created and then deposit.updated. Their customer may be null.
To settle a real sandbox record — a payin, payout, virtual-account deposit, or card event — use the helpers in Sandbox simulation endpoints.
Best practices
- Verify every signature before trusting the contents.
- Respond fast, process later. Return
2xximmediately and do the work in a background job. - Deduplicate. The same event can arrive more than once. Use
event_idwhere present, otherwise the record’sid,transaction_idordeposit_idwith itsstatus. - Don’t rely on order.
deposit.createdcan arrive afterdeposit.updated. Usestatusand timestamps. - Ignore unknown events. New types are added over time.
- Keep your secret safe, and rotate it with
regenerate-secretif it may have leaked. - Use HTTPS.

