NOWPayments
Crypto payment processing via NOWPayments — deposits using the crypto_address channel.
NOWPayments handles cryptocurrency deposits and payouts through Phoenix Pay. Deposits use the crypto_address channel, and payouts use the crypto_payout channel.
Supported Operations
| Operation | Channel | Supported |
|---|---|---|
| Deposits | crypto_address | Yes |
| Withdrawals | crypto_payout | Yes |
Supported Currencies
| Currency | Network | Min Amount (cents) |
|---|---|---|
| USDT | TRC-20 | 100 (= 1.00 USDT) |
| USDT | ERC-20 | 1000 (= 10.00 USDT) |
| BTC | Bitcoin | 1 (= 0.01 BTC) |
| ETH | Ethereum | 1 (= 0.01 ETH) |
| LTC | Litecoin | 1 (= 0.01 LTC) |
The exact list of supported currencies depends on your NOWPayments account configuration. Contact your platform administrator to enable additional currencies.
How It Works
Create Deposit
Your backend calls POST /api/deposits with channel: "crypto_address" and a crypto currency.
Address Generated
NOWPayments generates a unique wallet address. The response has action: "await" with metadata fields:
{
"intent_id": "01912e4a-...",
"action": "await",
"message": "Send payment to TXrk4d5x...",
"pay_address": "TXrk4d5x7Bj3e6g7Y8Zw9AbCdEf1234567",
"pay_currency": "usdttrc20",
"pay_amount": 50.0,
"expires_at": "2026-03-11T14:30:00Z"
}Display pay_address and pay_amount to your user.
User Sends Crypto
The user sends the specified amount from their wallet to the generated address before expires_at.
Blockchain Confirmation
NOWPayments monitors the blockchain. Phoenix Pay delivers signed webhooks as the payment progresses:
created→pending— transaction detected on blockchainpending→completed— sufficient confirmations received
Withdrawals
NOWPayments payouts are treated as a server-to-server flow in Phoenix Pay.
Create responses should return action: "await" while NOWPayments processes the payout. Phoenix Pay does not expose NOWPayments merchant verification as a user-facing step.
If the NOWPayments account still requires manual merchant verification for payouts, Phoenix Pay returns a normal API error and does not ask your application to submit an OTP.
Before Phoenix Pay creates the payout, it asks NOWPayments to validate the wallet address. If NOWPayments says the address is invalid, Phoenix Pay returns a normal API error instead of creating a payout that would fail later.
Create Request
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"order-12345","amount":5000,"currency":"USDT","channel":"crypto_address"}'
curl -X POST https://pay.phoenixverse.io/api/deposits \
-H "Content-Type: application/json" \
-H "X-Key-Id: your-key-id" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: <signature-of-$TIMESTAMP.$BODY>" \
-d "$BODY"| Field | Value | Description |
|---|---|---|
channel | "crypto_address" | Required. Selects the NOWPayments address flow. |
amount | integer (cents) | 5000 = 50.00 USDT |
currency | string | Must be a currency supported by your NOWPayments config |
Create Withdrawal Request
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"payout-12345","amount":2500,"currency":"USDT","channel":"crypto_payout","fields":{"address":"TXrk4d5x7Bj3e6g7Y8Zw9AbCdEf1234567"}}'
curl -X POST https://pay.phoenixverse.io/api/payouts \
-H "Content-Type: application/json" \
-H "X-Key-Id: your-key-id" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Signature: <signature-of-$TIMESTAMP.$BODY>" \
-d "$BODY"| Field | Value | Description |
|---|---|---|
channel | "crypto_payout" | Required. Selects the NOWPayments payout flow. |
amount | integer (cents) | 2500 = 25.00 USDT |
currency | string | Your Phoenix Pay payout currency |
fields.address | string | Recipient wallet address |
fields.extra_id | string | Optional memo / destination tag |
Response Metadata
When the create response has action: "await", these metadata fields are included:
| Field | Description |
|---|---|
pay_address | Crypto wallet address the user should send funds to |
pay_amount | Exact amount to send (in the PSP's native format) |
pay_currency | NOWPayments currency code (e.g., usdttrc20, btc) |
expires_at | When the payment window closes — address is invalid after this time |
These same fields appear on the GET response as well.
NOWPayments payout create responses can also include:
| Field | Description |
|---|---|
batch_withdrawal_id | NOWPayments payout batch id used for later verification and webhook correlation |
payout_status | Raw NOWPayments payout status such as CREATING, WAITING, or PROCESSING |
payout_currency | Network-specific NOWPayments payout currency code |
fee_amount | Estimated payout fee in cents when NOWPayments returns it |
fee_currency | Currency code for the estimated fee |
address_validation | true when NOWPayments accepted the destination address during preflight validation |
Configuration
These credentials are entered in the Phoenix Pay admin panel under Payment Providers > NOWPayments:
| Field | Required | Description |
|---|---|---|
credentials.api_key | Yes | API key from the NOWPayments dashboard under Store Settings > API Keys |
webhook_secret | Yes | IPN callback secret from Store Settings > IPN — Phoenix Pay stores this separately and uses it to verify NOWPayments webhooks |
credentials.email | Yes for payouts | NOWPayments account email used for POST /v1/auth before creating payouts |
credentials.password | Yes for payouts | NOWPayments account password used for payout auth |
credentials.pay_currency | No | Default NOWPayments payment currency code for deposit creation, for example usdttrc20 |
credentials.payout_currency | No | Default NOWPayments payout currency code for withdrawals, for example usdttrc20 |
credentials.api_base_url | No | Override API base URL. Use this if you want a NOWPayments sandbox endpoint instead of the live default |
All credentials are encrypted at rest using AES-256. They are never exposed through the API — only configurable via the admin panel.
Phoenix Pay generates the NOWPayments callback URL for your tenant automatically. You do not need to paste a webhook URL into the credentials JSON.
Setup Steps
Create a NOWPayments Account
Sign up at nowpayments.io and complete verification.
Generate API Credentials
In the NOWPayments dashboard:
- Go to Store Settings > API Keys and generate an API key
- Go to Store Settings > IPN and set a callback secret
- Make sure payout wallets are configured for the currencies you plan to withdraw
- Disable NOWPayments payout 2FA for automated withdrawals
- If payout security restrictions are enabled, whitelist your server IPs and recipient addresses as required by NOWPayments
Configure in Admin Panel
Enter the API key, payout auth email/password, and any default pay/payout currency overrides in the credentials JSON. Enter the IPN secret in the Webhook Secret / IPN Secret field. Select which currencies to enable for your tenant.
Test with Sandbox
Enable sandbox mode first. Create test deposits to verify the flow end-to-end before going live.
Sandbox Testing
When using sandbox mode:
- Create a PSP config with
mode: "sandbox" - Set
credentials.api_base_urlto your NOWPayments sandbox API URL - No real crypto transactions are processed
- Sandbox and live configs are stored separately per tenant
Webhook Reliability
NOWPayments may send the same webhook more than once if delivery is slow or uncertain.
Phoenix Pay safely ignores duplicate NOWPayments webhook deliveries and still returns success, so retries do not re-process a payment.
Payout Notes
- Phoenix Pay assumes NOWPayments payout 2FA is disabled for automated withdrawals.
- If the NOWPayments account still requires manual merchant verification, payout creation is rejected with a clear adapter error.
- If a payout address or server IP is not whitelisted in NOWPayments, payout creation can be rejected before processing starts.