API overview

Top-ups and payments

Implemented OneAster APIs and their authentication contracts.

Capability and identity

NOWPayments requires a OneAster account session, not a model API Key. First read enabled, min_amount_usd_cents and max_amount_usd_cents from GET /core/v1/billing/nowpayments. Do not create orders when disabled. NOWPayments is enabled in the current production deployment; Stripe remains disabled and test-mode only. payment_enabled=true does not enable Stripe or every provider.

Creation and units

POST /core/v1/billing/nowpayments/orders requires session Authorization and Idempotency-Key, with an example body of {"amount_usd_cents":"1500","pay_currency":"usdttrc20"}. This is integer USD cents, not credits. 1 USD = 100 OneAster credits; 1 credit = 10000 micro; 1 USD cent = 10000 micro. The $15 example is 1500 credits = 15000000 micro. $5 = 500 credits = 5000000 micro is only a unit conversion and is below the current new-order minimum. Use canonical integer strings and BigInt, without leading zeros or floating-point accounting. The current production range for new orders is 1500–1000000 cents ($15–$10000); read the account capability response for the current range. Clients cannot override credit_micro, callback URLs or exchange rates.

A new order returns201; replaying the same intent, amount and currency/network returns200 with the original order. Changing the amount or currency/network returns409. Keep the original intent on unknown state or timeout; do not recreate an invoice. States are creating, unknown, open, paid, expired and failed.

The capability response also includes max_pending_orders, pending_order_count and pending_order_states. The current limit is 50 unarchived creating, unknown or open orders with an unexpired payment window. A new intent at the limit returns409, while replay of the original intent still returns its existing order. The count is a read-only snapshot; the server checks capacity again when creating an order.

Hosted checkout and credit

Only the owner's unarchived open order with a valid payment window can expose checkout_url. Follow the trusted server-provided NOWPayments hosted link. Choose one of the eight USDT and USDC currency/network options returned by payment_options. The default is usdttrc20; the choice cannot be changed after creation. Do not hardcode payment addresses. New orders have a 900-second local payment window; hide checkout after expiry. Provider timers may differ, and expiry does not cancel the provider invoice. Returning from checkout is not proof of payment.

Poll GET /core/v1/billing/nowpayments/orders/{id} and GET /core/v1/me for paid state and wallet balance. Read-only GETs do not query the provider. Another user's detail returns404; administrator views hide checkout links.

Order archives and administrator summary

Order lists show unarchived records by default; archived=true selects archived records and archived=all includes both. Users can only query their own orders. Administrators can filter by exact order UUID or invoice ID and read GET /core/v1/admin/billing/nowpayments/summary. Administrator POST /core/v1/admin/billing/nowpayments/orders/{id}/archive is disabled in the current production deployment and returns 503 nowpayments_archive_disabled. There is no ordinary-user cancellation endpoint. Existing archives remain available. Archiving retains the order, payment evidence and audit record; it neither cancels the provider invoice nor reverses credited funds. Archived orders do not consume pending-order capacity and no longer return checkout links. Valid late payment evidence is still verified and credited once against the original quote.

Official IPN and recovery

The provider posts to /core/v1/billing/nowpayments/ipn with original JSON and x-nowpayments-sig. Core recursively sorts JSON, verifies HMAC SHA512, and queries the original payment evidence. A valid signature alone, confirmed, sending or partially_paid does not establish credit. The original order, invoice, quote, credentials and instance must match; only finished with actually_paid >= pay_amount can atomically credit the original quote once. Overpayment does not increase the quote, and refund states do not automatically reverse consumed balances.

If evidence has not caught up, retain the original order and retry the original notification. Administrator POST /core/v1/admin/billing/nowpayments/orders/{id}/reconcile queries the original payment_id without creating another invoice. This public documentation does not collect sessions or execute checkout, IPNs or reconciliation. This batch performs no real transfers or provider-delivery acceptance.