Event Notifications and Webhooks
The Pay.io Payment Gateway provides real-time event notifications, so merchants can stay up to date with deposits, withdrawals, and onramp purchases as they happen.
You can consume these events through Webhooks, the gateway pushes event notifications to your HTTP endpoint.
Event Types for Webhooks
The gateway sends notifications for the following transaction events:
Deposit Events
Processing Event - The deposit has been detected on the blockchain and is being processed.
Confirmation Event - The blockchain has confirmed the transaction, funds are now available in the wallet.
Withdrawal Events
Successful Event - The withdrawal was completed successfully, confirms that funds have been transferred.
Onramp Events
When a user buys crypto with fiat through an onramp session (created via POST /v1/user/payments), the purchase moves through several stages — the provider accepting the session, the card payment, and the on-chain delivery of funds. The gateway sends a User Onramp event at every stage, so you can show the user live purchase status and credit funds the moment they settle, without polling.
Pending Event - The provider has picked up the session, awaiting the user's payment.
Processing Event - The payment was accepted and the crypto transfer is in progress.
Succeeded Event - The crypto has been delivered to the destination wallet.
Failed Event - The transaction failed and no funds moved.
One session, multiple callbacks. Deposit and withdrawal events are self-contained, but an onramp session emits a callback for each status change: pending → processing → succeeded (or failed). Group them by transaction_uuid, and use correlation_key to match callbacks to the session you created via POST /v1/user/payments.
Webhook Integration
Setup Requirements
Webhook URL - Update the URL, which Payment Gateway will call in the Merchant Portal.
IP Whitelisting - Contact support for the list of IPs to allow.
Public Key - Obtain your Pay.io public key from the Merchant Console.
Secure Storage - Store the key securely in your application configuration.
Signature Verification - Implement verification on all incoming requests.
Webhook Security Verification
Each webhook request includes headers you must validate. Verification is identical for all event types — deposit, withdrawal, and onramp callbacks are all signed the same way.
[Table: Header / Description] X-Signature — Base64-encoded request signature X-Timestamp — UNIX timestamp when the event was sent X-Algorithm — Signing algorithm, always RSA-SHA256
Verification steps:
Extract the raw JSON request payload.
Read X-Signature, X-Timestamp, and X-Algorithm headers.
Build a string to verify:
Decode the Base64 signature.
Verify with RSA-SHA256 using the stored Pay.io public key.
Example: Verification in Elixir
Event Structure
Each event payload includes:
event- Type of event (User Deposit, User Payout, User Onramp).transaction- Full transaction details.transaction_uuid- Unique transaction ID for reconciliation.user_reference- Your internal user ID.merchant_reference- Reference configured during transaction creation (deposit and withdrawal events).correlation_key/session_reference- Session identifiers for matching onramp callbacks to the session you created (onramp events).
Because an onramp purchase starts on the fiat side and settles on the crypto side, its transaction object differs from deposit and withdrawal payloads:
currency block
Nested object with id, symbol, token_address, icons
Not present
to_currency block
Not present
{code, name, network}
from_amount / from_currency
Not present
Present (fiat side of the purchase)
to_address / tx_hash
Present
Not present (destination is stored server-side)
merchant_reference
Present
Not present
correlation_key / session_reference
Not present
Present
Multiple callbacks per session
No (single event)
Yes, one per status change
Example: Deposit Processing
Example: Deposit Confirmation
Example: Withdrawal Successful
Example: Onramp Pending
The provider has picked up the session. provider_transaction_id and payment_method are still null at this stage — they populate once the user completes their payment.
Example: Onramp Processing
The user has paid, and the crypto transfer is in progress. The fiat side (from_amount, from_currency) is now populated; to_amount stays null until the funds settle.
Example: Onramp Succeeded
The crypto has been delivered to the destination wallet. to_amount now shows the final settled amount, as this is the event to act on when crediting the user.
Example: Onramp Failed
The transaction failed and no funds moved. No action is needed on your side beyond updating the user's purchase status.
Onramp Field Reference
event
string
Always "User Onramp"
transaction_uuid
string (UUID)
Internal session ID
correlation_key
string
{merchant_id}:{session_reference} — matches the value returned from POST /v1/user/payments
session_reference
string | null
Your own ID for the session, if you supplied it at creation
user_reference
string | null
Player ID, if you supplied it at creation
payment_method
string | null
e.g. "CREDIT_DEBIT_CARD". Null on the first pending event
transaction.status
string
pending | processing | succeeded | failed
transaction.transaction_type
string
Always "onramp"
transaction.to_amount
number | null
Crypto amount received; null until settled
transaction.to_currency
object
{code, name, network}
transaction.from_amount
number | null
Fiat amount paid; populated from processing onwards
transaction.from_currency
string | null
Fiat currency code, e.g. "EUR"
transaction.provider_transaction_id
string | null
Provider's ID; null on the first pending event
transaction.date
string (ISO 8601)
Timestamp of this status change
Last updated