Stablecoin Pay-ins Quickstart
This guides walks you through the steps to set up a basic payments workflow using the Paxos Platform, including configuring a stablecoin pay-in workflow and setting up a refund workflow. Once completed, similar, more robust, workflows can be implemented in production. If you already have sandbox access, this guide should take less than one hour to complete.
Before You Begin
- Paxos may need to enable some API functionality described in the payments guides. Contact Support with any access issues.
- If you need a developer sandbox account, contact us before continuing.
- The API endpoints require authentication with a Client ID and Secret.
Each Client ID has a specific set of allowed scopes to access API endpoints.
Example: Sandbox Credentials
Log in to your sandbox account and go to Settings > API Management. Either select an existing Client ID or create a new one.
Best PracticeAlways store the Client ID and Client Secret in a safe place. The secret must be reset if forgotten.
To complete the steps in this guide, ensure the following scopes are enabled for the client (scopes may be updated at any time):
funding:read_profile \
funding:write_profile \
transfer:read_transfer \
transfer:write_crypto_withdrawal \
transfer:write_deposit_addressInclude the client (
client_id
) and secret (client_secret
) in the authentication request to https://oauth.sandbox.paxos.com/oauth2/token:curl --location "https://oauth.sandbox.paxos.com/oauth2/token" \
--form grant_type=client_credentials \
--form client_id={client_id} \
--form client_secret={client_secret} \
--form scope="funding:read_profile funding:write_profile transfer:read_transfer transfer:write_crypto_withdrawal transfer:write_deposit_address"Confirm the response includes the requisite scopes and save the
{access_token}
to use in the request authorization header (-H "Authorization: Bearer {access_token}"
).{
"access_token": "{access_token}",
"expires_in": 3599, // Seconds (59 Minutes and 59 Seconds)
"scope": "funding:read_profile funding:write_profile transfer:read_transfer transfer:write_crypto_withdrawal transfer:write_deposit_address",
"token_type": "bearer"
} - To follow along with this guide, create a new Profile to represent the Seller.
However, any existing Profile can be used when setting up simple pay-in and refund workflows.
Learn more about user onboarding requirements.
Example: Seller Profile
Use Create Profile to represent the seller.
curl --location 'https://api.sandbox.paxos.com/v2/profiles' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}' \
--data '{
"nickname": "Seller A",
"description": "Stablecoin Pay-in and Refunds."
}'Save the
id
(profile_id
) from the response, it will be used throughout this guide.{
"id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"nickname": "Seller A",
"type": "NORMAL"
}Use List Profiles to retrieve the Profile ID when needed.
- To represent the Buyer in this guide, send enough testnet tokens to pay network fees, along with one of the supported testnet stablecoins, to an off-platform wallet.
Example: Buyer's Wallet
We airdropped Solana Devnet to a self-custody wallet. We also used the Paxos Testnet Faucet to transfer some PYUSD on Solana Devnet to the Buyer's wallet. The same Buyer wallet is used to simulate a purchase as well as a refund.
Set Up Stablecoin Pay-in Workflow
To accept a pay-in on the Paxos Platform, first use Create Deposit Address to add a new wallet address on the public blockchain. Then add the deposit address as a stablecoin payment option for Buyers, typically at checkout.
Using a wallet connector or displaying a QR code in the Buyer interface helps to ensure that Buyers send the correct amount and avoid errors.
Once a Buyer completes a purchase, the transaction shows up in the List Transfers monitoring and reconciliation polling request.
1. Add Seller Stablecoin Deposit Address
Use Create Deposit Address to add a wallet address to the Profile designated for the Seller.
The request must include one of supported stablecoins networks.
Set conversion_target_asset
to USD
to automatically convert stablecoin pay-ins to USD on the Paxos Platform.
Whenever possible, include your own unique identifier in the request using ref_id
.
Doing so helps to protect against submitting the same request twice, as the second request with the same ref_id
will be rejected with 409 already exists
.
The ref_id
can also be used in many query parameters.
The example uses SOLANA
as the crypto_network
.
If needed, use either ETHEREUM
or POLYGON_POS
for crypto_network
.
curl --location 'https://api.sandbox.paxos.com/v2/transfer/deposit-addresses' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}' \
--data '{
"profile_id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"crypto_network": "SOLANA",
"ref_id": "da_73bcbb08-db06-4308-b0c2-2a6398012f8b",
"conversion_target_asset": "USD"
}'
Capture the address
and compatible_crypto_networks
values for distribution to potential Buyers.
Also store the id
to use when looking up pay-ins.
{
"id": "2d3b2366-c432-4098-ba16-83ca418c6f00",
"profile_id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"customer_id": "8cbc1177-d982-4750-a435-3c7f36245452",
"crypto_network": "SOLANA",
"identity_id": "00000000-0000-0000-0000-000000000000",
"ref_id": "da_73bcbb08-db06-4308-b0c2-2a6398012f8b",
"address": "7iR1TfsaZ3f1PmbsoRuPYDbV7iujxZmuHaZDDU1Uv4YX",
"account_id": "00000000-0000-0000-0000-000000000000",
"conversion_target_asset": "USD",
"compatible_crypto_networks": [
"SOLANA"
]
}
Since the designated Profile has not gone through the Identity onboarding process, the default identity_id
and account_id
values appear in the response.
Onboarding Questions? See the onboarding FAQ for details about user Identity and Account requirements. Contact Support to help determine the best onboarding approach.
2. Receive Stablecoin Payment
Off the Paxos Platform, share the deposit address with Buyers, typically on the checkout page, and start accepting stablecoin pay-ins. Once a Buyer completes a pay-in transaction, Paxos credits the designated Profile with either stablecoin or USD, based on the deposit address configuration.
Example: Buyer's Wallet
We airdropped Solana Devnet to a self-custody wallet. We also used the Paxos Testnet Faucet to transfer some PYUSD on Solana Devnet to the Buyer's wallet. The same Buyer wallet is used to simulate a purchase as well as a refund.
For this guide, all received pay-ins are automatically converted to USD on the Paxos Platform because we used "conversion_target_asset": "USD"
when creating the deposit address.
3. Add Pay-in Monitoring and Reconciliation Request
Using List Transfers, create a recurring request that looks for completed transactions in the Seller's Profile.
Retrieve the status for payments received in the deposit address using the profile_id
, filtered by on the CRYPTO_DEPOSIT
type and updated_at.gte
parameters.
We recommend to poll List Transfers globally at a set cadence (for example, at 1 second intervals), using slightly behind the last processed updated_at.gte
as a synchronization checkpoint.
curl --location 'https://api.sandbox.paxos.com/v2/transfer/transfers?profile_ids=eb1dbb95-8e22-471b-9ded-40bbfe309037&updated_at.gte=2024-06-24T15%3A44%3A54.383141Z&type=CRYPTO_DEPOSIT' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}'
The response confirms that a total
of 7.06
PYUSD (asset
) was converted to USD (balance_asset
) when the pay-in reached the Paxos Platform.
{
"items": [
{
"id": "9d93693f-5157-49f4-ae44-4a7a8eae3d73",
"customer_id": "8cbc1177-d982-4750-a435-3c7f36245452",
"profile_id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"amount": "7.06",
"total": "7.06",
"fee": "0",
"asset": "PYUSD",
"balance_asset": "USD",
"direction": "CREDIT",
"type": "CRYPTO_DEPOSIT",
"status": "COMPLETED",
"created_at": "2024-06-24T15:44:48.724648Z",
"updated_at": "2024-06-24T15:44:55.383141Z",
"destination_address": "7iR1TfsaZ3f1PmbsoRuPYDbV7iujxZmuHaZDDU1Uv4YX",
"crypto_network": "SOLANA",
"crypto_tx_hash": "4ex3dQ1bkoxQyyWKsk5UfVwNzzi2HXBcDb2Xv1BzxKLhRKZaVmfAJyM2hWochXTqTRDMsrpcfvoaFTMZrBsaaJPx",
"crypto_tx_index": "4",
"auto_conversion": {}
}
],
"next_page_cursor": "CAISDAj3qOazBhCIidm2ARijg5MN"
}
4. Move USD to Bank Account
To manage on-platform cash balances, use the Fiat Transfers APIs to batch withdraw USD to any designated bank account as needed. Learn more in the fiat transfers guide.
If you need to create a fiat account Paxos may need to enable some API functionality. C> ontact Support for assistance.
Set Up a Refund Workflow
To process stablecoin refunds on the Paxos Platform, first fund your account with USD then use Create Crypto Withdrawal to initiate a stablecoin refund to the Buyer. Once a refund is complete, the transaction shows up in the List Transfers monitoring and reconciliation polling request.
1. Add USD to a Refund Account
Production implementations can use the Fiat Transfers APIs to send USD to a destination on the Paxos Platform, which is out of scope for this guide. The fiat transfers guide provides step-by-step instructions on setting up fiat movements.
If you need to create a fiat account Paxos may need to enable some API functionality. Contact Support for assistance.
For simplicity, this guide uses Create Sandbox Deposit to simulate funding the designated Seller Profile with USD.
Include the Seller's Profile ID (profile_id
) as a path parameter, as well as the deposit asset
and amount
as query parameters.
curl --location 'https://api.sandbox.paxos.com/v2/sandbox/profiles/eb1dbb95-8e22-471b-9ded-40bbfe309037/deposit' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token} \
--data '{
"asset": "USD",
"amount": "100"
}'
A successful response only includes the system-generated activity_id
.
{
"activity_id": "a457f3b2-8897-4118-bc9b-216541cfc5a7"
}
1.1 Sandbox Only: Check USD Deposit
To confirm the USD deposit, use List Profile Balances.
curl --location 'https://api.sandbox.paxos.com/v2/profiles/eb1dbb95-8e22-471b-9ded-40bbfe309037/balances?assets=USD' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}'
The Profile USD balance is now 107.06
, reflecting both the previously received pay-in and the current USD deposit.
{
"items": [
{
"asset": "USD",
"available": "107.06",
"trading": "0"
}
]
}
2. Initiate a Stablecoin Refund
Use Create Crypto Withdrawal to send stablecoin to the Buyer's designated wallet address. The request must include one of supported stablecoins networks.
Set balance_asset
to USD
to automatically convert fiat to stablecoin and issue a refund in a single request.
For this guide, the refund is issued to the Buyer's original wallet address (destination_address
) using the same stablecoin/network pair:
- The
asset
isPYUSD
, thebalance_asset
isUSD
, and thecrypto_network
isSOLANA
.
The funding source is the Seller's Profile (profile_id
) used earlier.
Whenever possible, include your own unique identifier in the request using ref_id
.
Doing so helps to protect against submitting the same request twice, as the second request with the same ref_id
will be rejected with 409 already exists
.
The ref_id
can also be used in many query parameters.
curl --location 'https://api.sandbox.paxos.com/v2/transfer/crypto-withdrawals' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}' \
--data '{
"profile_id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"asset": "PYUSD",
"destination_address": "BtXdwoYSWPprQT88ZCLuQcXuTz4dFHB1AJFYqr5uXoAd",
"crypto_network": "SOLANA",
"ref_id": "cw_293a8f7c-bcb6-483f-919b-8661ae65f0e6",
"balance_asset": "USD",
"amount": "7.06"
}'
The initial response has a status
of PENDING
, since the on-chain transaction has not yet been confirmed.
Create a refund monitoring request to check that the refund was successful.
{
"id": "c327d8b7-0c1a-4125-b73f-318924373d37",
"customer_id": "8cbc1177-d982-4750-a435-3c7f36245452",
"profile_id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"ref_id": "cw_293a8f7c-bcb6-483f-919b-8661ae65f0e6",
"amount": "7.06",
"total": "7.06",
"fee": "0",
"asset": "PYUSD",
"balance_asset": "USD",
"direction": "DEBIT",
"type": "CRYPTO_WITHDRAWAL",
"status": "PENDING",
"created_at": "2024-06-24T18:33:51.087868Z",
"updated_at": "2024-06-24T18:33:51.087868Z",
"destination_address": "BtXdwoYSWPprQT88ZCLuQcXuTz4dFHB1AJFYqr5uXoAd",
"crypto_network": "SOLANA",
"auto_conversion": {}
}
3. Add Refund Monitoring and Reconciliation Request
Using List Transfers, create a recurring request that looks for completed transactions in the Seller's Profile.
Retrieve the status for refunds sent by using the profile_id
, filtering by on the CRYPTO_WITHDRAWAL
type and updated_at.gte
parameters.
We recommend to poll List Transfers globally at a set cadence (for example, at 1 second intervals), using slightly behind the last processed updated_at.gte
as a synchronization checkpoint.
curl --location 'https://api.sandbox.paxos.com/v2/transfer/transfers?profile_ids=eb1dbb95-8e22-471b-9ded-40bbfe309037&updated_at.gte=2024-06-24T15%3A44%3A54.383141Z&type=CRYPTO_WITHDRAWAL' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}'
The response confirms that a total
of 7.06
PYUSD (asset
) was sent to the Buyer's wallet address.
{
"items": [
{
"id": "c327d8b7-0c1a-4125-b73f-318924373d37",
"customer_id": "8cbc1177-d982-4750-a435-3c7f36245452",
"profile_id": "eb1dbb95-8e22-471b-9ded-40bbfe309037",
"ref_id": "cw_293a8f7c-bcb6-483f-919b-8661ae65f0e6",
"amount": "7.06",
"total": "7.06",
"fee": "0",
"asset": "PYUSD",
"balance_asset": "USD",
"direction": "DEBIT",
"type": "CRYPTO_WITHDRAWAL",
"status": "COMPLETED",
"created_at": "2024-06-24T18:33:51.105228Z",
"updated_at": "2024-06-24T18:34:24.976618Z",
"destination_address": "BtXdwoYSWPprQT88ZCLuQcXuTz4dFHB1AJFYqr5uXoAd",
"crypto_network": "SOLANA",
"crypto_tx_hash": "4xo8doZQ58W6WCrzmyjd3vyrv2SPMRjHiz4v6w8mEuCCWbAyiXjzbFADia7St6XF3jTNyQmrDmpSNH84TXdDujFU",
"crypto_tx_index": "0",
"auto_conversion": {}
}
],
"next_page_cursor": "CAISDAiw-OazBhCQhNjRAxi0jpMN"
}
3.1 Sandbox Only: Check USD Withdrawal
To confirm USD was used to fund the crypto withdrawal, use List Profile Balances.
curl --location 'https://api.sandbox.paxos.com/v2/profiles/eb1dbb95-8e22-471b-9ded-40bbfe309037/balances?assets=USD' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {access_token}'
The Profile USD balance is now 100.00
, where previously it was 7.06
.
{
"items": [
{
"asset": "USD",
"available": "100.00",
"trading": "0"
}
]
}