Skip to main content

Event types

You choose which events to subscribe to per endpoint, so you can listen only for the ones you care about (most integrations just need transaction.completed and transaction.failed).

Transaction events

Each event maps 1:1 to a transaction status.

Fee events

A fee your account bears for an account you manage moves through three stages, and each is announced separately. Subscribe to all three, or only to the one you act on.
If you subscribe to fee.charged alone, your balance will move without an event to explain it — sometimes for a long time, since a fee is held for as long as the transaction that incurred it stays unsettled. Take fee.pending and fee.released too if you reconcile on available balance.
All three carry the same shape; event and effect say which stage it is. amount is in minor units25000 means 250.00. Note the transaction listing endpoints report amounts in major units instead, so convert before comparing the two. fee_type is what the fee was charged for — withdrawal, payin or card_funding. related_transaction_id is the movement that incurred it and incurred_by_account the account that made it, so the charge can be attributed without matching on amount or timing. Each stage carries its own event_id, so a redelivery of the same stage is recognisable while the three stages never suppress one another.
A fee borne by the account that incurred it does not produce these events — there is no separate charge to announce, and the fee is reported as fee_amount on that account’s own transaction. To list fees rather than be pushed them, filter List Transactions Across Accounts on transactionType=fee.

Account events

These cover the onboarding lifecycle of the accounts you manage via the API (the additional business/individual accounts you create under your profile), plus the deposit accounts provisioned for them.

Account lifecycle

An account onboarded through the API typically moves through:
1

account.onboarded

The account has been created and onboarding has begun. Complete its application data and upload the required documents.
2

account.submitted

The application has been submitted for review.
3

account.approved / account.rejected / account.changes_requested (review outcome)

Review resolves one of three ways: approved (the account can now transact, and deposit accounts can be issued for it), rejected (the application was declined), or changes_requested (the account must update its details and resubmit — after which it emits account.submitted again).
4

account.virtual_account.created

A deposit account (NGN/USD bank transfer details, or a crypto address) is now available for funding. The data.virtual_account object carries the details — the same shape you’d get from the funding instructions endpoint.

Deposit account requests

A USD deposit account request is reviewed before the account is provisioned, so it resolves one of three ways:
1

account.virtual_account.created

The request was approved and the deposit account exists.
2

account.virtual_account.changes_requested

Something on the request needs correcting. data.bank_account_request.reason explains what. Re-issue the account with the corrections and the same request reopens — no duplicate is created.
3

account.virtual_account.declined

The request was declined, with the reason in data.bank_account_request.reason. Further requests for the same currency are blocked until the decision is lifted.
These three events are scoped to the deposit account request, not the account’s KYB. account.rejected and account.changes_requested refer to the account’s application and are unrelated.

Transaction lifecycle

A typical transaction emits transaction.pending and then one or more later events as it progresses to a terminal state:
1

transaction.pending

The transaction has been created and is awaiting processing.
2

transaction.processing / transaction.sent (in flight)

The transaction is being processed and dispatched to the bank or network.
3

transaction.completed (success path)

The transaction finalized. For a deposit, funds are now available in your wallet; for a payout, the beneficiary has been paid.
4

transaction.failed / rejected (failure paths)

The transaction did not complete. Funds for a failed/rejected payout are returned to your wallet. A transaction.refunded event may follow a completed transaction that is later reversed.
Not every transaction emits every event, and intermediate events (processing, sent) may be skipped depending on the rail and how fast the transaction settles. A deposit that is auto-confirmed may jump from pending to completed; a payout that fails will emit transaction.pending then transaction.failed. Always treat the event’s status as the source of truth and don’t assume ordering.

The event_id field

Each logical event has a stable event_id. The same logical event (for example, “transaction X completed”) always carries the same event_id, even if it is delivered more than once. Use it to make your handler idempotent.

Distinguishing deposits from payouts

The payload’s data.type field is either deposit or payout. The data.rail field tells you whether it’s fiat or stablecoin. See Payloads for the full schema and samples.