Log in Create workspace
Skip to content

API reference

Platform - Billing

Receive and durably queue signed NOWPayments status notifications for hosted checkout and credit top-ups.

Jump to 1 endpoints
On this page

Overview

This endpoint is an inbound provider callback, not a customer or operator payment-write API. NOWPayments sends a JSON payload plus x-nowpayments-sig; the application verifies its HMAC-SHA512 signature over canonical sorted JSON, deduplicates the event in a durable inbox, and queues processing before returning 202.

Provider authentication is payload signing
There is no workspace bearer credential on this route. The provider signature is lowercase-insensitive hexadecimal HMAC-SHA512 over recursively key-sorted canonical JSON; invalid or missing signatures receive an empty 401 response.
Acceptance precedes settlement processing
HTTP 202 means the verified event is durable and processing is queued or already completed. An identical callback can reuse a processed inbox record without creating another job. The empty response is not proof of a new credit or subscription change. Persistence or queue insertion failure returns 503 so the provider can retry.
Duplicate callbacks are safe
The inbox derives a provider/handler event key from the canonical payload and inserts on conflict. Repeated identical notifications resolve to the existing inbox record and processing is idempotent; payment status changes produce distinct payloads that can advance state.

Before you begin

  • The command-line examples require curl and jq; any exception is identified in its introduction.
  • A NOWPayments account configured to deliver IPN callbacks to the public /webhooks/nowpayments URL.
  • The same IPN secret configured securely in the provider and application environments.
  • A hosted-checkout or credit order created through the supported billing flow; do not create balances by posting fabricated callbacks.

How it works

  1. Configure the provider callback

    Give NOWPayments the HTTPS webhook URL and configure the IPN secret on both sides. Keep the endpoint outside browser and workspace authentication flows.

  2. Return the provider-facing status

    Allow the application to verify, persist, and enqueue each callback. NOWPayments should regard 202 as accepted, 401 as a configuration/signature fault, and 503 as retryable delivery failure.

  3. Reconcile through billing records

    Observe the hosted-checkout, payment, inbox, and credit state through operator billing tools and logs. Do not infer settlement solely from delivery of waiting, confirming, or other nonterminal statuses.

Examples

These examples are illustrative. Replace the sample values with your own. Keep credentials in environment variables or a secret manager, never in client-side code.

Inspect a representative provider payload

This is an offline inspection example only. Do not POST hand-crafted payment notifications; only NOWPayments should call the webhook with a valid provider signature.

bash
cat > /tmp/nowpayments-ipn-example.json <<'JSON'
{
  "actually_paid": 25.0,
  "order_id": "robotscenter_workspace-example_credits_1789556400",
  "pay_currency": "usdc",
  "payment_id": 8123456789,
  "payment_status": "confirmed",
  "price_amount": 25.0,
  "price_currency": "usd"
}
JSON

jq '{order_id, payment_id, payment_status, price_amount, price_currency, actually_paid, pay_currency}' \
  /tmp/nowpayments-ipn-example.json
What to expect

No HTTP request is made. The command only displays an illustrative callback shape so operators can recognize provider fields without forging a signed billing event.

Troubleshooting

NOWPayments receives 401
The x-nowpayments-sig value is missing or does not match the canonical JSON under the configured IPN secret. Check secret parity and ensure an intermediary is not changing JSON values before verification.
NOWPayments receives 503
Signature verification passed, but durable persistence or worker queueing failed. Restore PostgreSQL/Oban readiness and allow the provider to retry; do not bypass the inbox with a manual balance write.
A 202 has not changed the balance yet
Acceptance means the event is durable and processing is queued or already completed. Inspect worker and inbox status, and confirm the provider payment reached a supported settlement state rather than assuming every callback grants credits.
The same callback appears repeatedly
Providers retry at least-once deliveries. Identical canonical payloads deduplicate in the inbox; investigate only when processing remains failed or changing provider statuses are not converging.

Endpoint reference

Ready to integrate? Open an endpoint for its required permissions, request fields, response format, and status codes. The examples above explain the workflow; these details define each individual request.

POST
/webhooks/nowpayments

NOWPayments payment webhook

Description

NOWPayments sends webhook notifications (IPN) to this endpoint when a payment status changes. This is the confirmation path for /app/billing hosted checkout and balance top-up. create_email_subscription/2 exists in Billing but has no operator-UI event, form, or route. ## Webhook verification 1. NOWPayments signs the payload with HMAC-SHA512 using the IPN secret 2. The signature is sent in the `x-nowpayments-sig` header 3. The signature is computed over the sorted JSON payload parameters 4. The server verifies the signature before processing the event ## Supported payment statuses | Status | Description | |--------|-------------| | `waiting` | Waiting for blockchain confirmation | | `confirming` | Payment has blockchain confirmations | | `confirmed` | Payment is fully confirmed on-chain | | `sending` | Funds are being sent to the merchant wallet | | `partially_paid` | Payment received is less than the expected amount | | `finished` | Payment is complete and funds delivered | | `failed` | Payment failed | | `refunded` | Payment was refunded | | `expired` | Payment expired before completion | ## Response A verified callback is deduplicated in a durable database inbox and queued for background processing before the endpoint returns HTTP 202. Invalid signatures return HTTP 401. Persistence or queueing failures return HTTP 503 so the provider can retry. Inbox processing is idempotent and retries up to 20 attempts.

Auth

None
Responses
202

Webhook accepted for processing

401

Invalid webhook signature

503

Webhook could not be persisted or queued

Where to go next

see also