Step 1 of 8

Start with the full payment flow

Complete the common setup, create a payment, configure IPN, test the full flow, then choose how incoming payments should work for your business.

Set up account
→
Create payment
→
Set up IPN
→
Test flow
→
Choose logic
→
Payouts

For developers

Use API snippets and IPN validation examples to connect your backend.

For product teams

Choose the right payment logic: fixed-price payments, balance top-ups, or payouts.

For launch

Use dashboard settings and the go-live checklist before production.

1. Set up your account

Configure the account settings required before creating and processing payments.

1

Generate API key

Your API key is generated automatically and is required for API integration.

2

Set base currency

Base currency is the currency in which the price is displayed.

Dashboard > Settings > Payments > Payment details > Base currencyOpen Payment details
3

Generate IPN secret key

Generate and save the IPN Secret key in Payment Settings tab at the Dashboard.

Dashboard > Settings > Payments > Instant payment notificationsOpen IPN settings
4

Whitelist NOWPayments IP addresses

Make sure firewall software on your server allows NOWPayments requests. It may be required to whitelist NOWPayments IP addresses on your side. For assistance contact support@nowpayments.io.

5

Whitelist settings

Whitelist your IP and all wallet addresses, or request to disable these safety measures from your Dashboard. If you have both IPv-4 and IPv-6 addresses, whitelist both.

2. Create your first payment

Use the Create Payment request and include your IPN callback URL.

You can also accept payments using invoices instead of API payments.

Create Payment API request

Insert your URL address where you want to get callbacks in the create_payment request. The parameter name is ipn_callback_url.

API documentation snippet
import requests
import json

url = "https://api.nowpayments.io/v1/payment"

payload = json.dumps({
  "price_amount": 3999.5,
  "price_currency": "usd",
  "pay_currency": "btc",
  "ipn_callback_url": "https://example.com",
  "order_id": "RGDBP-21314",
  "order_description": "Apple Macbook Pro 2019 x 1"
})
headers = {
  'x-api-key': '{{api-key}}',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

Payment address

In response, you get pay_address. This is the deposit address where the user should send the money.

3. Set up IPN

IPN sends payment updates to the callback URL specified in your Create Payment request.

Always verify the signature before delivering goods or crediting a balance. Anyone can send a request to your callback URL. Accept payment updates only after verifying x-nowpayments-sig with your IPN secret.

IPN flow

Status changes
→
POST to callback URL
→
x-nowpayments-sig
→
Validate signature
RequirementDetails
EndpointSet up an endpoint which can receive POST requests from NOWPayments server.
HeaderThe POST request contains the x-nowpayments-sig parameter in the header.
BodyThe body is similar to a get payment status response body.
Before productionMake a test request to this endpoint to ensure it works properly.
We can't send POST requests to localhost. Do not use localhost (127.0.0.1) for IPN callbacks.

Server configuration

CheckRequirement
FirewallA firewall should not prevent NOWPayments POST requests from passing through to the address specified as the IPN callback URL. There can be more than one firewall in the system.
Notification server IPsWhitelist 51.89.194.21, 51.75.77.69, 138.201.172.58, 65.21.158.36. IP whitelisting is an additional safeguard; it never replaces signature validation.
Endpoint accessEndpoint must not be closed by authorisation, or other such requirements.
Response timeThe endpoint shall respond within 3000 ms.
Hosting / CloudflareNOWPayments does not recommend shared-based hosting services. Be extremely careful when setting up Cloudflare if it is an external firewall.

Rate limits

EndpointLimitIf exceeded
GET estimate7 requests per second from one outgoing IP address429 error code
POST payment3 requests per second from one outgoing IP address429 error code
GET /payment/:id10 requests per second429 error code

Signature validation steps

0

Reject missing or empty signatures

If x-nowpayments-sig is missing or empty, reject the request and stop processing. Never run validation only when the header is present: omitting it would bypass that check.

1

Sort the POST request by keys

Convert it to string using JSON.stringify(params, Object.keys(params).sort()) or the same function.

2

Sign the string

Sign a string with an IPN-secret key with HMAC and sha-512 key.

3

Compare signatures

Compare the expected signature with the x-nowpayments-sig request header using constant-time comparison: crypto.timingSafeEqual (Node.js), hash_equals (PHP), or hmac.compare_digest (Python). Do not use ==. Reject a mismatch and stop processing.

IPN validation examples

Run these checks on your backend. If validation returns false, reject the callback (for example, with HTTP 401) and return immediately. Do not update an order or balance. Only process a verified callback after checking its payment status, amount and currency.

Webhook example: Payments

Payments webhook example
{
"payment_id":123456789,
"parent_payment_id":987654321,
"invoice_id":null,
"payment_status":"finished",
"pay_address":"address",
"payin_extra_id":null,
"price_amount":1,
"price_currency":"usd",
"pay_amount":15,
"actually_paid":15,
"actually_paid_at_fiat":0,
"pay_currency":"trx",
"order_id":null,
"order_description":null,
"purchase_id":"123456789",
"outcome_amount":14.8106,
"outcome_currency":"trx",
"payment_extra_ids":null,
"fee": {
"currency":"btc",
"depositFee":0.09853637216235617,
"withdrawalFee":0,
"serviceFee":0
}
}
ParameterUse
payment_statusUse payment status when processing payment updates.
outcome_amountCheck the actual amount received.
outcome_currencyCheck the currency actually received.
x-nowpayments-sigValidate the callback signature.
feeReview fee details when present in the webhook body.
Node.js signature validation example
const crypto = require('node:crypto');

function sortObject(obj) {
  return Object.keys(obj).sort().reduce(
    (result, key) => {
      result[key] = (obj[key] && typeof obj[key] === 'object') ? sortObject(obj[key]) : obj[key]
      return result
    },
    {}
  )
}
function verifyIpnSignature(params, receivedSignature, notificationsKey) {
  // A missing, empty or malformed header must fail validation.
  if (typeof receivedSignature !== 'string' ||
      !/^[a-f0-9]{128}$/i.test(receivedSignature)) return false;

  const expected = crypto.createHmac('sha512', notificationsKey)
    .update(JSON.stringify(sortObject(params))).digest();
  const received = Buffer.from(receivedSignature, 'hex');
  return received.length === expected.length &&
    crypto.timingSafeEqual(expected, received);
}
// Pass the parsed JSON body, x-nowpayments-sig header and IPN secret.
// If verifyIpnSignature(...) is false, reject and stop processing.
PHP signature validation example
function tksort(&$array)
{
    ksort($array);
    foreach (array_keys($array) as $k) {
        if (is_array($array[$k])) {
            tksort($array[$k]);
        }
    }
}
function check_ipn_request_is_valid($ipn_secret)
{
    $received_hmac = $_SERVER['HTTP_X_NOWPAYMENTS_SIG'] ?? '';
    if (!is_string($received_hmac) ||
        !preg_match('/\A[a-f0-9]{128}\z/i', $received_hmac)) {
        return false;
    }
    $request_json = file_get_contents('php://input');
    if ($request_json === false || $request_json === '') return false;
    $request_data = json_decode($request_json, true);
    if (json_last_error() !== JSON_ERROR_NONE || !is_array($request_data)) {
        return false;
    }
    tksort($request_data);
    $sorted_request_json = json_encode($request_data, JSON_UNESCAPED_SLASHES);
    if ($sorted_request_json === false) return false;
    $hmac = hash_hmac('sha512', $sorted_request_json, trim($ipn_secret));
    return hash_equals($hmac, strtolower($received_hmac));
}
// If check_ipn_request_is_valid($ipn_secret) is false,
// reject the callback and return before updating an order or balance.
Python signature validation example
import json
import hmac
import hashlib
import re

def np_signature_check(np_secret_key, np_x_signature, message):
    # A missing, empty or malformed header must fail validation.
    if not isinstance(np_x_signature, str) or not re.fullmatch(
        r'[a-fA-F0-9]{128}', np_x_signature
    ):
        return False
    sorted_msg = json.dumps(message, separators=(',', ':'), sort_keys=True)
    signature = hmac.new(
        str(np_secret_key).encode(),
        sorted_msg.encode(),
        hashlib.sha512
    ).hexdigest()
    return hmac.compare_digest(signature, np_x_signature.lower())

# If np_signature_check(...) is False, reject and stop processing.

4. Test the full payment flow

Create a payment, receive payment status updates through IPN, and verify the final payment data before granting goods or crediting a balance.

Test checklist

Payment statuses

StatusMeaning
waitingWaiting for the customer to send the payment.
confirmingThe transaction is being processed on the blockchain.
confirmedThe process is confirmed by the blockchain.
sendingThe funds are being sent to your personal address or custody balance.
finishedThe funds have reached your personal address or custody balance and the payment is finished.
partially_paidA completed payment. This status means you've already received your funds, but the amount sent by your customer was less than the settled price.
failedThe payment was not completed due to an error.
expiredThe user did not send funds within the payment window.
Do not grant goods or services when the payment is in confirming or confirmed statuses.

5. Choose incoming payment logic

Select how incoming payments should be handled. Only the selected logic is shown.

Fixed-price payments

User pays for a product or service with a fixed price.

E-commerceServicesFixed-price items

Balance top-ups

User deposits funds to credit an internal balance.

CasinoBalance top-ups

6. Configure dashboard features

Use dashboard features to solve payment processing cases before going live.

Repeated Payments

Set the default payment status for repeated payments made by your user to the same deposit address.

Partially Paid / FinishedOpen Payment details

Wrong-asset deposits auto processing

Process or do not process wrong-asset deposits automatically. Payment status can be set to Partially Paid or Finished.

Payment Covering

Set the percentage of the payment that needs to be paid for it to be considered completed.

Network Fee Optimization

Among your wallets, a payment picks the most suitable one and undergoes a conversion resulting in the lowest network fee in total.

Payment Markup

Allows setting a markup percentage over the initial price, from 0% to 10%.

My Team

Add team members and customize their access to the main account. Team members need to have a NOWPayments account.

Dashboard > Settings > Account > My Team

7. Send payouts

Choose how you want to send funds: to users by email with ChangeNOW Pro, or to crypto wallets through payouts.

ChangeNOW Pro Payouts

Payout to email with $0 fees and instant delivery.

Email-based payoutsCSV uploadAPI$0 fees

Crypto Payouts

Send payouts from Custody to crypto wallet addresses.

Mass PayoutsAPICustody

Subscriptions

Create plans and customer subscriptions through the NOWPayments API. Customers choose how to pay on the invoice; your backend tracks payments and renewals through NOWPayments.

Create plan
→
Subscribe email
→
Open invoice_url
→
Customer pays
→
Confirm & renew
No separate ChangeNOW Pro API integration is required. Use the existing NOWPayments Recurring Payments API (Email Subscriptions feature).
1

Complete account setup

Register or sign in, generate your API key, and follow the existing Setup and IPN steps in this guide. Use the authentication headers specified for each recurring API method; keep credentials on your backend.

To offer ChangeNOW Pro: enable Custody; set Company name in your merchant account or pass merchant_name; use an interval_day of 1, 7, 30, 31 or 365 days.
2

Create a subscription plan

POST /v1/subscriptions/plans — Create plan. Set the title, billing interval, amount and currency; configure notification and redirect URLs as described in the plan documentation. Save the returned plan ID.

Additional request fieldUse in Create plan / Update plan
grace_period0–5 days, no greater than interval_day. The subscription stays active during this period if the first payment attempt fails.
merchant_nameYour company name; can also be set as Company name in the merchant account.
Example plan body — illustrative values

Send to https://api.nowpayments.io/v1/subscriptions/plans with the headers required by the documentation.

POST Create plan — JSON body
{
  "title": "Monthly plan",
  "interval_day": 30,
  "amount": 49,
  "currency": "usd",
  "ipn_callback_url": "https://your-domain.example/subscription-ipn",
  "grace_period": 3,
  "merchant_name": "Your company"
}

Plan responses also include grace_period and Merchant_name (the merchant company name).

3

Create the customer's subscription

POST /v1/subscriptions — Create an email subscription. Required fields: subscription_plan_id and email.

POST Create an email subscription — JSON body
{
  "subscription_plan_id": 76215585,
  "email": "customer@example.com"
}

Save the returned subscription ID and status, subscriber data, invoice_url and payment_type. Send the customer to invoice_url. No ChangeNOW Pro selection parameter is needed: the customer chooses on the invoice.

Creating a subscription is not payment confirmation. Grant access only after confirming payment and subscription status through the API and your configured notifications.
4

Customer pays on the invoice

The invoice offers standard crypto payment and, when available, ChangeNOW Pro. With ChangeNOW Pro, funds come from the customer's CHN Pro balance.

Invoice illustration · not a product screenshot

Your company

Monthly plan · illustrative amount

49 USD

Standard crypto payment
Pay with ChangeNOW Pro
From your CHN Pro balance · when available

Payment is completed on the actual invoice_url page.

How the payment type changes renewals

one-time
The customer makes a single payment. It does not authorize future automatic charges; renewal requires another payment.
auto-renew
The customer authorizes recurring charges. Renewals charge the CHN Pro balance according to the plan, subject to permission and sufficient funds.

Read payment_type through the API to determine the subscription's payment mode. Invoice creation alone does not authorize auto-renewal.

5

Monitor payments and subscription status

Use Get many recurring payments and Get one recurring payment. Both return invoice_url and payment_type (one-time or auto-renew) alongside subscription data.

Continue using the NOWPayments API and the notifications configured in your integration. Update customer access after confirmed payment or renewal; handle failed attempts and the configured grace period.

6

Cancel a subscription

Call DELETE /v1/subscriptions/{sub_id} with the saved subscription ID. Use the existing cancellation method and check its result.

API methods at a glance

Base URL: https://api.nowpayments.io. Replace {plan_id} and {sub_id} with the saved IDs. See Recurring Payments API for each method's authentication, complete parameters and response schema.

Method nameRequest
Create planPOST /v1/subscriptions/plans
Update planPATCH /v1/subscriptions/plans/{plan_id}
Get one planGET /v1/subscriptions/plans/{plan_id}
Get all plansGET /v1/subscriptions/plans
Create an email subscriptionPOST /v1/subscriptions
Get many recurring paymentsGET /v1/subscriptions
Get one recurring paymentGET /v1/subscriptions/{sub_id}
Cancel subscriptionDELETE /v1/subscriptions/{sub_id}

All four plan methods return the added plan fields. grace_period and merchant_name can be set through Create plan and Update plan.

8. Go live checklist

Complete the checklist before going live.

Do not recommend granting goods and services with any status other than finished, unless your selected scenario uses partially_paid for balance top-ups.

FAQ & troubleshooting

Short answers for setup, payments, callbacks, payouts and subscriptions. Use the search above to find words inside every answer, including closed questions.

Do I need a separate ChangeNOW Pro API integration?
Setup

No. Create subscriptions and email payouts through NOWPayments. For subscriptions, the customer selects ChangeNOW Pro on the invoice when it is available.

NOWPayments APIcustomer invoiceChangeNOW Pro balance
Open subscriptions guide →
Where do I get my API key?
Setup

Sign in to the NOWPayments dashboard and open API keys in merchant settings. Keep the key on your backend, never in public frontend code. Follow the Setup section for the remaining account settings.

Open setup guide →
When do I need Custody?
Setup

Enable Custody for payouts from your merchant balance and for the ChangeNOW Pro subscription flow. Complete the related whitelist and account settings before testing.

Open payouts guide →
Can I use a hosted invoice instead of building checkout?
Payments

Yes. The guide supports invoices as an alternative to API payments. For subscriptions, creation returns invoice_url: send the customer to that page to pay.

Open create payment guide →
The payment is confirmed. Can I deliver the order?
Payments

Do not deliver at confirming or confirmed. For fixed-price orders, wait for finished and check outcome_amount and outcome_currency against the expected price. Creating an invoice is not payment confirmation.

Createdwaitingconfirming / confirmedfinishedverify amountdeliver
Open test flow guide →
What should I do with an underpayment?
Payments

For fixed-price orders, do not deliver automatically unless your approved payment logic allows it. For balance top-ups, credit the actual outcome_amount in outcome_currency after finished or partially_paid. Payment Covering can be configured for your accepted threshold.

Open payment logic guide →
How do I choose fixed-price payments or balance top-ups?
Payments

Choose fixed-price logic for a specific order or service price. Choose balance top-ups when a deposit credits the user’s internal balance. The delivery trigger and treatment of partially_paid differ; select your scenario in Payment logic.

Open payment logic guide →
What happens if a customer sends another payment to the same address?
Payments

Repeated Payments sets the default status for subsequent payments to that deposit address. The guide recommends Partially Paid for fixed-price flows and Finished for balance top-ups. This setting is not an authorization for automatic subscription charges.

Open dashboard features guide →
What does Payment Covering do?
Payments

It sets the payment percentage you accept as completed. Choose the threshold for your business model and continue checking final payment data before delivering an order or crediting a balance.

Open dashboard features guide →
What is IPN and where do I configure it?
IPN & testing

IPN sends payment updates to your backend. Include ipn_callback_url in the payment request, generate your IPN secret in the dashboard, and implement the receiving endpoint described in the IPN section.

NOWPaymentsyour callback endpointvalidate signatureupdate order
Open ipn guide →
How do I check that a callback is authentic?
IPN & testing

Anyone can send a request to your callback URL. Reject missing, empty or invalid x-nowpayments-sig headers. Verify the signature with your IPN secret using constant-time comparison; IP whitelisting does not replace this check. Then check the payment status, outcome_amount and outcome_currency before updating the order or user balance.

Open ipn guide →
Why am I not receiving payment notifications?
IPN & testing

Check that ipn_callback_url points to the correct reachable endpoint and your server accepts POST requests. Review firewall settings and whitelist NOWPayments IP addresses where required. Contact support@nowpayments.io for help with the IP list.

Open ipn guide →
What do I test before going live?
IPN & testing

Create a payment, receive and validate its callback, verify the final status and settlement amount/currency, and check delivery or balance crediting. Complete the Go live checklist; test your selected payout and subscription scenarios if you use them.

Open go live guide →
Can I pay a customer by email without collecting a wallet address?
Payouts

Yes. Use ChangeNOW Pro payouts. Set address to the recipient’s email in the payout request. A ChangeNOW Pro account is created for a new recipient; they receive an email to access their funds.

Merchant balancepayout to emailChangeNOW Pro accountrecipient accesses funds
Open payouts guide →
Do email payouts and external crypto payouts use different endpoints?
Payouts

No. Both use POST /v1/payout. For ChangeNOW Pro payouts, the address field contains an email. For an external crypto payout, it contains the recipient’s wallet address. Follow the correct configuration and verification steps for your route.

Open payouts guide →
Where do the $0 payout fees apply?
Payouts

The $0 fee and instant-delivery claim in this guide applies to payouts to ChangeNOW Pro by email. Do not apply that claim to external wallet transfers, conversions or fiat operations.

Open payouts guide →
What should I check if a payout cannot be created or verified?
Payouts

Check Custody balance, IP whitelist, recipient details and the authentication required by the method. For external crypto payouts, review wallet whitelist settings. Complete the documented 2FA verification step and inspect the payout status.

Open payouts guide →
What must be enabled for ChangeNOW Pro subscriptions?
Subscriptions

Enable Custody and specify your Company name in the merchant account or pass merchant_name. Supported interval_day values for this flow are 1, 7, 30, 31 and 365 days.

Open subscriptions guide →
How do I create a customer subscription?
Subscriptions

Create a plan with POST /v1/subscriptions/plans and save its ID. Then call POST /v1/subscriptions with subscription_plan_id and email. Save the subscription ID and send the customer to the returned invoice_url.

Create plansave plan IDsubscribe emailopen invoice_urlcustomer pays
Open subscriptions guide →
Should I send a parameter to select ChangeNOW Pro?
Subscriptions

No. The customer selects an available payment method on the invoice page. You do not need a separate ChangeNOW Pro selection parameter when creating the subscription.

Open subscriptions guide →
What is the difference between one-time and auto-renew?
Subscriptions

one-time pays once and does not authorize future automatic charges. auto-renew allows recurring charges after the customer gives permission, according to the plan and subject to sufficient CHN Pro balance. Read payment_type through the NOWPayments API.

Open subscriptions guide →
What happens if a renewal payment attempt fails?
Subscriptions

Use the subscription status and configured notifications to handle the failed attempt. grace_period can keep the subscription active for 0–5 days after the first failed payment attempt; it must not exceed interval_day. Do not treat auto-renew as a guarantee of successful payment.

Open subscriptions guide →
How do I monitor or cancel a subscription?
Subscriptions

Use GET /v1/subscriptions for the list and GET /v1/subscriptions/{sub_id} for one subscription. Read status, invoice_url and payment_type. To cancel, call DELETE /v1/subscriptions/{sub_id} with the saved subscription ID and check the result.

Open subscriptions guide →
Is my subscription active as soon as I receive invoice_url?
Subscriptions

No. invoice_url means that a payment page has been created. Confirm payment and subscription status through NOWPayments before granting access, and update access after confirmed renewals.

Open subscriptions guide →