# Crypto Payments
Use the Crypto API to collect cryptocurrency into a merchant wallet or send cryptocurrency to a blockchain wallet. Authenticate every request as described in Authentication.
Before initiating a payment, call Active Channels with the target MerchantCode. Confirm that all_channels.crypto contains the required channel, such as USDT TRC20.
# Collect crypto
POST https://api.sandbox.pesaway.com/api/v1/crypto/receive-payment/This endpoint creates a collection and returns a provider-generated deposit address. The transaction remains processing until the on-chain payment is confirmed and reconciled.
# Request fields
| Field | Required | Description |
|---|---|---|
Amount | Yes | Amount in the merchant account currency, or the pricing amount when using an FX quote. |
MerchantCode | Yes | Active Internal account number to credit. |
Channel | Yes | Active configured crypto method, for example USDT TRC20. |
Currency | Yes | Merchant account currency. Must match the account when no FX quote is used. |
ExternalReference | Yes | Your unique payment reference. Reuse it only to retry the same request. |
ResultsUrl | Yes | HTTPS endpoint for the terminal transaction callback. |
Reason | No | Purpose of the collection. Defaults to Collection. |
description | No | Optional merchant description. |
FxQuoteID | Conditional | Required when a fiat merchant account is being paid in crypto. Use the ID from FX Quotes. |
PricingCurrency | Conditional | Required with FxQuoteID; must match the quote. |
# Crypto wallet to crypto wallet
For a USDT merchant wallet, no FX quote is needed:
{
"Amount": "10.50",
"Channel": "USDT TRC20",
"Currency": "USDT",
"MerchantCode": "PHY000000001ZC6",
"ExternalReference": "CRYPTO-USDT-001",
"ResultsUrl": "https://merchant.example/payments/callback",
"Reason": "Wallet top-up"
}
# Crypto payment into a fiat merchant wallet
First create a crypto collection FX quote with PricingCurrency equal to the merchant wallet currency and PaymentCurrency equal to the crypto asset. The API derives PayableCurrency from the merchant account. Then use the returned quote in the collection request:
{
"Amount": "1300.00",
"Channel": "USDT TRC20",
"Currency": "KES",
"MerchantCode": "PHY000000001ZC6",
"ExternalReference": "CRYPTO-KES-001",
"ResultsUrl": "https://merchant.example/payments/callback",
"Reason": "Invoice payment",
"FxQuoteID": "<quote-id>",
"PricingCurrency": "KES"
}
Send the quote response's PaymentAmount in USDT to the returned DepositAddress. Do not send the fiat Amount on-chain.
# Immediate response
Crypto collection response keys use PascalCase except code and status.
{
"code": "200.001",
"OriginatorReference": "CRYPTO-USDT-001",
"TransactionID": "PHYE1B82D30F6",
"ResponseDescription": "Success. Request accepted for processing",
"DepositAddress": "TDY5seykLPdmrTPehZyfue9Azn64Mkhq8o",
"Asset": "USDT",
"Network": "TRC20",
"status": "processing"
}
| Field | Description |
|---|---|
DepositAddress | Address to which the customer sends the crypto payment. |
Asset | Crypto asset being collected, for example USDT. |
Network | Blockchain network required for the transfer, for example TRC20. |
TransactionID | PesaWay transaction reference; retain this for support and status queries. |
status | Immediate transaction state. processing is not a successful on-chain settlement. |
# Send crypto
POST https://api.sandbox.pesaway.com/api/v1/crypto/send-payment/Use this endpoint to send crypto from the merchant's Internal account to a customer blockchain wallet. The request is accepted for processing, not immediately settled. Wait for the terminal callback or query its status before treating it as complete.
# Request fields
| Field | Required | Description |
|---|---|---|
Amount | Yes | Amount to send from a crypto-denominated wallet, or the pricing amount when using an FX quote. |
WalletAddress | Yes | Customer wallet address. It must belong to the selected blockchain network. |
MerchantCode | Yes | Active Internal account number to debit. |
Channel | Yes | Active configured crypto method, for example USDT TRC20. |
Currency | Yes | Merchant account currency. Must match the account when no FX quote is used. |
ExternalReference | Yes | Your unique payout reference. Reuse it only to retry the same payout request. |
ResultsUrl | Yes | HTTPS endpoint to receive the terminal success or failure callback. |
Reason | No | Payout purpose. Defaults to Payment. |
description | No | Optional payout description. |
FxQuoteID | Conditional | Required when a fiat merchant account is funding a crypto payout. |
PricingCurrency | Conditional | Required with FxQuoteID; must match the FX quote. |
# USDT TRC20 payout example
{
"Amount": "10.50",
"WalletAddress": "TDY5seykLPdmrTPehZyfue9Azn64Mkhq8o",
"MerchantCode": "PHY000000001ZC6",
"Channel": "USDT TRC20",
"Currency": "USDT",
"ExternalReference": "CRYPTO-PAYOUT-001",
"ResultsUrl": "https://merchant.example/payments/callback",
"Reason": "Customer withdrawal",
"description": "USDT withdrawal"
}
Only send to an address on the network returned by the configured channel. For example, a USDT TRC20 payout must use a TRON/TRC20 address. An address can be syntactically valid but still belong to the wrong network; the merchant is responsible for verifying the customer's destination before submitting the request.
# Immediate response
Send X-API-Version: 2 to receive the canonical lowercase status shown below.
Without that version header, existing integrations retain the legacy Status field
for this inline-approved payout response.
{
"code": "200.001",
"TransactionID": "PHYE1B82D30F6",
"OriginatorReference": "CRYPTO-PAYOUT-001",
"ResponseDescription": "Success. Request accepted for processing",
"status": "processing"
}
Keep TransactionID; it identifies the payout in both the status query and callback. An accepted request can still fail at the provider or blockchain stage.
# Payout callback
The API sends a signed JSON request to ResultsUrl only when the payout reaches a terminal state. Validate the Signature HTTP header with your API application's hash secret before acting on the payload.
{
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"OriginatorReference": "CRYPTO-PAYOUT-001",
"TransactionID": "PHYE1B82D30F6",
"TransactionAmount": "10.50",
"TransactionReceipt": "<provider-receipt>",
"WalletAddress": "TDY5seykLPdmrTPehZyfue9Azn64Mkhq8o",
"TransactionCompletedDateTime": "2026-08-17T12:45:00+00:00"
}
ResultCode: 0 is successful; ResultCode: 2001 is failed. Store and process callbacks idempotently using TransactionID.
# Query transaction status
POST https://api.sandbox.pesaway.com/api/v1/crypto/transaction-query/{
"TransactionReference": "PHYE1B82D30F6"
}
Use the TransactionID returned at initiation. A completed transaction returns ResultCode: 0; a failed transaction returns ResultCode: 2001; any other result is still processing.
# Integration checks
# Collection checks
- Use a unique
ExternalReferencefor every payment intent. - Always transfer the exact
payment_amountand use the returnedNetwork; sending the correct asset on the wrong network cannot be reconciled. - Treat the immediate
200.001response as acceptance, not settlement. - Configure and verify
ResultsUrl; terminal success or failure is delivered there after provider reconciliation.
# Payout checks
- Use a unique
ExternalReferencefor every payout intent. Channeldefines the required blockchain network. VerifyWalletAddressbelongs to that network before sending the request.- Treat the immediate
200.001response as acceptance, not settlement; use the callback or transaction-status query to determine the final outcome. - Configure and verify
ResultsUrl; terminal success or failure is delivered there after provider reconciliation.