API Checkout
Overview
API Checkout provides merchants with a streamlined one-step payment flow for building custom checkout UIs. Merchants have full control over the user interface while the platform handles all on-chain payment capabilities.
Core features:
- Custom checkout UI: Merchants fully control the checkout user experience
- One-step flow: Create orders directly without a separate quote step
- On-chain transfer: Supports multiple blockchain networks (TRON, ETH, BSC, and more)
- Stablecoins only: Supports USDC, USDT, and USD1
PERMISSION REQUIRED
API Checkout is a separate product that requires explicit enablement. Contact technical support to activate API Checkout (API_PERMISSION_DISABLED error code 50010 if not enabled).
Authentication
All API requests use the same HMAC-SHA256 signature scheme as the main API. Include the following headers on every request:
| Header | Type | Required | Description | Example |
|---|---|---|---|---|
X-Timestamp | Long | Yes | Request timestamp (milliseconds, 13 digits) | 1640000000000 |
X-Signature | String | Yes | Request signature (Base64-encoded) | calculated-signature |
Signature algorithm:
signaturePayload = timestamp + "\n" + METHOD + "\n" + path + "\n" + SHA256(body)
X-Signature = Base64(HMAC-SHA256(signaturePayload, apiSecret))SHA256(body)is the Base64-encoded hash of the request body- For GET requests without query parameters, omit the fourth component:
timestamp + "\n" + METHOD + "\n" + path - For GET requests with query parameters,
queryStringis hashed as the fourth component;pathdoes not include query parameters - HTTP method must be uppercase
See Signature Algorithm for full details and code examples.
Environments
| Environment | Base URL |
|---|---|
| Production | https://api.paystablecoin.global |
| Sandbox | https://api.sandbox.paystablecoin.global |
1. Get Payment Methods
Retrieve the list of payment methods available to the merchant before creating an order. Use this to display available currency/network options in your checkout UI and to validate combinations before order creation.
Endpoint Information
- Method:
GET - Path:
/api/v1/merchants/{merchantId}/checkout/payment-methods - Authentication: Required
Path Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
merchantId | String | Yes | Merchant ID | MCH_20240101_ABC123 |
Request Example
curl -X GET "https://api.paystablecoin.global/api/v1/merchants/MCH_20240101_ABC123/checkout/payment-methods" \
-H "X-Timestamp: 1640000000000" \
-H "X-Signature: <calculated-signature>"Response Fields
| Field | Type | Description | Example |
|---|---|---|---|
code | String | Response code. 00000 indicates success | 00000 |
message | String | Response message | Success |
data | Object | Response data | - |
data.merchantId | String | Merchant ID | MCH_20240101_ABC123 |
data.paymentMethods | Array | List of available payment methods | - |
data.paymentMethods[].paymentMethodType | String | Payment method type | ON_CHAIN_TRANSFER |
data.paymentMethods[].cryptoCurrency | String | Cryptocurrency (USDC / USDT / USD1) | USDC |
data.paymentMethods[].network | String | Blockchain network code | tron |
data.paymentMethods[].networkDisplayName | String | Network display name | TRON Network |
data.paymentMethods[].minAmount | Number | Minimum payment amount | 0.1 |
data.paymentMethods[].maxAmount | Number | Maximum payment amount | 999999999 |
data.paymentMethods[].estimatedConfirmationTimeSec | Integer | Estimated confirmation time (seconds) | 60 |
data.paymentMethods[].displayOrder | Integer | Display order (lower number = higher priority) | 1 |
Response Example
{
"code": "00000",
"message": "Success",
"data": {
"merchantId": "MCH_20240101_ABC123",
"paymentMethods": [
{
"paymentMethodType": "ON_CHAIN_TRANSFER",
"cryptoCurrency": "USDC",
"network": "tron",
"networkDisplayName": "TRON Network",
"minAmount": 0.10,
"maxAmount": 999999999.00,
"estimatedConfirmationTimeSec": 60,
"displayOrder": 1
},
{
"paymentMethodType": "ON_CHAIN_TRANSFER",
"cryptoCurrency": "USDC",
"network": "eth",
"networkDisplayName": "Ethereum(ERC20)",
"minAmount": 10.00,
"maxAmount": 999999999.00,
"estimatedConfirmationTimeSec": 900,
"displayOrder": 2
},
{
"paymentMethodType": "ON_CHAIN_TRANSFER",
"cryptoCurrency": "USDT",
"network": "tron",
"networkDisplayName": "TRON Network",
"minAmount": 0.10,
"maxAmount": 999999999.00,
"estimatedConfirmationTimeSec": 60,
"displayOrder": 3
}
]
}
}2. Create Checkout Order
After the user selects a payment method in your checkout UI, call this endpoint to create the order. The platform returns order details including the deposit address and amount to display to the user.
Endpoint Information
- Method:
POST - Path:
/api/v1/merchants/{merchantId}/checkout/orders - Content-Type:
application/json - Authentication: Required
Path Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
merchantId | String | Yes | Merchant ID | MCH_20240101_ABC123 |
Request Body — Required Fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
merchantOrderId | String | Yes | Merchant order ID (unique per merchant, 16–64 chars, alphanumeric + _ - only, used for idempotency) | ORDER_2024010112345678 |
orderAmount | Object | Yes | Order amount. Only USDC, USDT, and USD1 are supported | {"value": "100.50", "currency": "USDC"} |
orderAmount.value | String | Yes | Stablecoin amount | 100.50 |
orderAmount.currency | String | Yes | Stablecoin code: USDC / USDT / USD1 | USDC |
paymentMethodType | String | Yes | Payment method type. Fixed value: ON_CHAIN_TRANSFER | ON_CHAIN_TRANSFER |
network | String | Yes | Blockchain network code (e.g. tron, eth, bsc). Must be a valid combination with orderAmount.currency | tron |
expiresAt | String | Yes | Order expiration time (UTC, ISO 8601). Maximum 24 hours from creation | 2024-01-01T13:00:00Z |
Request Body — Optional Fields
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
customer | Object | No | Buyer information (for risk control) | - |
customer.email | String | No | Buyer email address | user@example.com |
customer.name | String | No | Buyer name | John Doe |
customer.customerId | String | No | Buyer ID from merchant system | USR_12345 |
description | String | No | Order description (max 512 chars) | Purchase of 2 items |
items | Array | No | Line item details | - |
items[].name | String | No | Item name | iPhone 15 Pro |
items[].quantity | Integer | No | Item quantity | 1 |
items[].price | String | No | Item unit price | 999.00 |
items[].currency | String | No | Item currency code | USDC |
customerIp | String | No | Client IP address for risk control (max 64 chars) | 192.168.1.100 |
userAgent | String | No | Client User-Agent for device identification (max 512 chars) | Mozilla/5.0... |
callbackUrl | String | No | Webhook callback URL for async payment status notifications (max 2048 chars) | https://api.merchant.com/webhooks/payment |
metadata | String | No | Merchant custom metadata, returned as-is (max 4096 chars, JSON format recommended) | {"orderId":"12345","source":"web"} |
IMPORTANT
merchantOrderIdmust be unique per merchant. It is used for idempotency — submitting the samemerchantOrderIdtwice returns the existing order without creating a duplicate.- The
orderAmount.currencyandnetworkcombination must appear in the results of Get Payment Methods. Use that endpoint first to confirm available combinations. expiresAtis recommended to be set to 30 minutes from creation time.
Request Examples
Example 1: USDC on TRON
curl -X POST https://api.paystablecoin.global/api/v1/merchants/MCH_20240101_ABC123/checkout/orders \
-H "X-Timestamp: 1640000000000" \
-H "X-Signature: <calculated-signature>" \
-H "Content-Type: application/json" \
-d '{
"merchantOrderId": "ORDER_2024010112345678",
"orderAmount": {
"value": "100.50",
"currency": "USDC"
},
"paymentMethodType": "ON_CHAIN_TRANSFER",
"network": "tron",
"expiresAt": "2024-01-01T13:00:00Z",
"description": "Purchase of 2 items",
"callbackUrl": "https://api.merchant.com/webhooks/payment"
}'Example 2: USDC on ETH with buyer info
curl -X POST https://api.paystablecoin.global/api/v1/merchants/MCH_20240101_ABC123/checkout/orders \
-H "X-Timestamp: 1640000000000" \
-H "X-Signature: <calculated-signature>" \
-H "Content-Type: application/json" \
-d '{
"merchantOrderId": "ORDER_2024010112345679",
"orderAmount": {
"value": "200.00",
"currency": "USDC"
},
"paymentMethodType": "ON_CHAIN_TRANSFER",
"network": "eth",
"expiresAt": "2024-01-01T13:00:00Z",
"customer": {
"email": "user@example.com",
"name": "John Doe",
"customerId": "USR_12345"
},
"items": [
{
"name": "iPhone 15 Pro",
"quantity": 1,
"price": "999.00",
"currency": "USDC"
}
],
"customerIp": "192.168.1.100",
"callbackUrl": "https://api.merchant.com/webhooks/payment"
}'Response Fields
| Field | Type | Description | Example |
|---|---|---|---|
code | String | Response code. 00000 indicates success | 00000 |
message | String | Response message | Success |
data.orderId | String | Platform order ID | ORD_20240101_1234567890ABCDEF |
data.merchantId | String | Merchant ID | MCH_20240101_ABC123 |
data.merchantOrderId | String | Merchant order ID | ORDER_2024010112345678 |
data.status | String | Order status: INIT / PROCESSING / SUCCEEDED / FAILED / CLOSED | INIT |
data.orderAmount | Object | Order amount | {"value": "100.50", "currency": "USDC"} |
data.cryptoPaymentAmount | Object | Amount the user must pay (may include fees) | {"value": "101.00", "currency": "USDC"} |
data.depositAddress | String | Address the user must transfer funds to | TYdRLmP9kN4oY3hZ8xT6wQ2vS5uW7aV1b |
data.network | String | Blockchain network code | tron |
data.networkDisplayName | String | Network display name | TRON Network |
data.createdAt | String (ISO 8601) | Order creation time (UTC) | 2024-01-01T12:00:00Z |
data.expiresAt | String (ISO 8601) | Order expiration time (UTC) | 2024-01-01T13:00:00Z |
DISPLAYING PAYMENT INFO
After order creation, immediately display the following to the user in your checkout UI:
depositAddress— the wallet address to send funds tocryptoPaymentAmount— the exact amount the user must send (notorderAmount)networkDisplayName— the network on which the transfer must be made- A countdown timer based on
expiresAt
The user must send at least cryptoPaymentAmount.value. Sending more is accepted; sending less causes the order to fail.
Response Examples
Success:
{
"code": "00000",
"message": "Success",
"data": {
"orderId": "ORD_20240101_1234567890ABCDEF",
"merchantId": "MCH_20240101_ABC123",
"merchantOrderId": "ORDER_2024010112345678",
"status": "INIT",
"orderAmount": {
"value": "100.50",
"currency": "USDC"
},
"cryptoPaymentAmount": {
"value": "101.00",
"currency": "USDC"
},
"depositAddress": "TYdRLmP9kN4oY3hZ8xT6wQ2vS5uW7aV1b",
"network": "tron",
"networkDisplayName": "TRON Network",
"createdAt": "2024-01-01T12:00:00Z",
"expiresAt": "2024-01-01T13:00:00Z"
}
}Error — invalid parameter:
{
"code": "10001",
"message": "Invalid parameter: orderAmount.currency must be one of: USDC, USDT, USD1",
"data": null
}3. Query Checkout Order
Query the latest status and details of a checkout order.
Endpoint Information
- Method:
GET - Path:
/api/v1/merchants/{merchantId}/checkout/orders/{merchantOrderId} - Authentication: Required
- Signature Note: GET requests have no body or query parameters. Algorithm:
Base64(HMAC-SHA256(timestamp\nMETHOD\npath, apiSecret))
Path Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
merchantId | String | Yes | Merchant ID | MCH_20240101_ABC123 |
merchantOrderId | String | Yes | Merchant order ID | ORDER_2024010112345678 |
Request Example
curl -X GET "https://api.paystablecoin.global/api/v1/merchants/MCH_20240101_ABC123/checkout/orders/ORDER_2024010112345678" \
-H "X-Timestamp: 1640000000000" \
-H "X-Signature: <calculated-signature>"Signature string: 1640000000000\nGET\n/api/v1/merchants/MCH_20240101_ABC123/checkout/orders/ORDER_2024010112345678
Response Fields
| Field | Type | Description | Example |
|---|---|---|---|
code | String | Response code. 00000 indicates success | 00000 |
message | String | Response message | Success |
data.orderId | String | Platform order ID | ORD_20240101_1234567890ABCDEF |
data.merchantId | String | Merchant ID | MCH_20240101_ABC123 |
data.merchantOrderId | String | Merchant order ID | ORDER_2024010112345678 |
data.status | String | Order status (see status table below) | SUCCEEDED |
data.orderAmount | Object | Order amount | {"value": "100.50", "currency": "USDC"} |
data.cryptoPaymentAmount | Object | Amount the user was required to pay (including fees) | {"value": "101.00", "currency": "USDC"} |
data.cryptoPaidAmount | Object | Actual amount paid by user (only present after payment succeeds) | {"value": "101.00", "currency": "USDC"} |
data.depositAddress | String | Deposit address | TYdRLmP9kN4oY3hZ8xT6wQ2vS5uW7aV1b |
data.network | String | Blockchain network code | tron |
data.networkDisplayName | String | Network display name | TRON Network |
data.cryptoPaymentDetail | Object | On-chain payment details (only present after payment succeeds) | See below |
data.cryptoPaymentDetail.network | String | Blockchain network | tron |
data.cryptoPaymentDetail.cryptoCurrency | String | Cryptocurrency | USDC |
data.cryptoPaymentDetail.transactionHash | String | Transaction hash | 0x1234567890abcdef... |
data.cryptoPaymentDetail.fromAddress | String | Sender address | TXdQKjYz8f9vN3kYh2xL6mP8sR5wT7uV2a |
data.cryptoPaymentDetail.toAddress | String | Recipient address | TYdRLmP9kN4oY3hZ8xT6wQ2vS5uW7aV1b |
data.cryptoPaymentDetail.amount | String | Transaction amount | 101.00 |
data.cryptoPaymentDetail.confirmations | Integer | Current block confirmations | 21 |
data.cryptoPaymentDetail.requiredConfirmations | Integer | Required confirmations for finality | 21 |
data.createdAt | String (ISO 8601) | Order creation time (UTC) | 2024-01-01T12:00:00Z |
data.expiresAt | String (ISO 8601) | Order expiration time (UTC) | 2024-01-01T13:00:00Z |
data.paidAt | String (ISO 8601) | Payment time (UTC, only present after payment succeeds) | 2024-01-01T12:15:30Z |
Order Status Descriptions
| Status | Description | Is Final? |
|---|---|---|
INIT | Order created, awaiting payment | No |
PROCESSING | Payment detected on-chain, confirming | No |
SUCCEEDED | Payment confirmed and completed | Yes |
FAILED | Payment failed (insufficient amount, timeout, or error) | Yes |
CLOSED | Order closed (expired or cancelled) | Yes |
Response Examples
Succeeded order:
{
"code": "00000",
"message": "Success",
"data": {
"orderId": "ORD_20240101_1234567890ABCDEF",
"merchantId": "MCH_20240101_ABC123",
"merchantOrderId": "ORDER_2024010112345678",
"status": "SUCCEEDED",
"orderAmount": {
"value": "100.50",
"currency": "USDC"
},
"cryptoPaymentAmount": {
"value": "101.00",
"currency": "USDC"
},
"cryptoPaidAmount": {
"value": "101.00",
"currency": "USDC"
},
"depositAddress": "TYdRLmP9kN4oY3hZ8xT6wQ2vS5uW7aV1b",
"network": "tron",
"networkDisplayName": "TRON Network",
"cryptoPaymentDetail": {
"network": "tron",
"cryptoCurrency": "USDC",
"transactionHash": "0x1234567890abcdef1234567890abcdef",
"fromAddress": "TXdQKjYz8f9vN3kYh2xL6mP8sR5wT7uV2a",
"toAddress": "TYdRLmP9kN4oY3hZ8xT6wQ2vS5uW7aV1b",
"amount": "101.00",
"confirmations": 21,
"requiredConfirmations": 21
},
"createdAt": "2024-01-01T12:00:00Z",
"expiresAt": "2024-01-01T13:00:00Z",
"paidAt": "2024-01-01T12:15:30Z"
}
}Webhook Notifications
API Checkout webhook notifications are documented on the Webhook Notifications page.
Error Codes
| Error Code | Code Value | Description | Resolution |
|---|---|---|---|
INVALID_PARAMETER | 10001 | Invalid request parameter | Check all request parameters against the spec |
INVALID_AMOUNT | 10004 | Order amount must be greater than 0 | Provide a positive amount |
INVALID_EXPIRES_AT | 10005 | Expiration time is in the past | Set expiresAt to a future time |
INVALID_MERCHANT | 10007 | Merchant ID is invalid | Verify your merchant ID |
UNCONFIGURED_PAYMENT_METHOD | 10011 | Unsupported currency/network combination, or the merchant does not have this method configured | Call Get Payment Methods to confirm available combinations |
ORDER_ALREADY_EXISTS | 20001 | merchantOrderId already exists | Use a different order ID or check for duplicate submission |
ORDER_NOT_FOUND | 40001 | Order not found | Verify the order ID |
API_PERMISSION_DISABLED | 50010 | API Checkout is not enabled for this merchant | Contact technical support to activate API Checkout |
SYSTEM_ERROR | 99999 | Internal system error | Retry after a short delay or contact support |
Appendix: Supported Networks and Currencies
The following combinations are supported by the platform. The merchant's actual available methods depend on platform configuration — always call Get Payment Methods to confirm.
Currency / Network Combinations
| Currency | Network Code | Network Display Name |
|---|---|---|
USD1 | eth | Ethereum(ERC20) |
USD1 | bsc | BNB Smart Chain(BEP20) |
USDC | eth | Ethereum(ERC20) |
USDC | polygon | Polygon |
USDC | optimism | Optimism |
USDC | arbitrum | Arbitrum One |
USDC | bsc | BNB Smart Chain(BEP20) |
USDC | base | Base |
USDC | solana | Solana |
USDT | bsc | BNB Smart Chain(BEP20) |
USDT | eth | Ethereum(ERC20) |
USDT | polygon | Polygon |
USDT | arbitrum | Arbitrum One |
USDT | optimism | Optimism |
USDT | solana | Solana |
USDT | tron | Tron(TRC20) |
Network Reference
| Network Code | Full Name | Notes |
|---|---|---|
tron | Tron | TRC20 standard. Fast and low-cost — recommended for USDT |
eth | Ethereum | ERC20 standard. Higher fees, ~15 min confirmation |
bsc | BNB Smart Chain | BEP20 standard. Low fees |
polygon | Polygon | Ethereum sidechain (formerly Matic) |
arbitrum | Arbitrum One | Ethereum Layer 2 |
optimism | Optimism | Ethereum Layer 2 |
base | Base | Coinbase Layer 2 |
solana | Solana | High-performance chain |
Best Practices
- Call Get Payment Methods first: Before creating an order, always fetch available payment methods to avoid
UNCONFIGURED_PAYMENT_METHODerrors and to populate your UI accurately. - Idempotency: Use a stable, unique
merchantOrderIdper checkout attempt. If the user retries, reuse the same ID to avoid duplicate orders. - Set a 30-minute expiry: Set
expiresAtto 30 minutes from creation. Avoid very short or very long windows. - Display
cryptoPaymentAmount, notorderAmount: Users must send thecryptoPaymentAmountvalue. It may differ fromorderAmountdue to fees. - Configure
callbackUrl: Strongly recommended. Without it, you must poll to detect payment completion. - Poll as a fallback: If no webhook is received, poll every 5–10 seconds using Query Checkout Order.
- Idempotent webhook handling: Use
acquiringOrderIdormerchantOrderIdto deduplicate webhook notifications, as the same event may be delivered more than once.
Related Documentation
- Authentication Headers - Learn about request header setup
- Signature Algorithm - Learn signature calculation
- Webhook Notifications - API Checkout webhook reference
- Error Codes and Solutions - Understand error codes and troubleshooting