Onramping API
This document covers the Onramping endpoint used to create pay-links that redirect your customers to our on-ramp checkout where they can purchase crypto with fiat and have it sent directly to a deposit address. It includes:- Create a pay-link (
POST /api/ramping/links)
This endpoint is protected, you must be authenticated.
Base URL
All examples use:https://www.niftipay.com
Authentication
This endpoint supports two authentication methods (depending on your integration setup):1) API Key (recommended for server-to-server integrations)
Send your API key in thex-api-key header.
2) Session cookie (browser / dashboard usage)
If you are authenticated via the dashboard.For browser calls, you usually don’t need to add headers manually — the cookie is sent automatically.
How it works
- You call
POST /api/ramping/linkswith your customer’s details and the fiat amount. - The API creates an underlying crypto invoice order and generates a signed pay-link token.
- You redirect your customer to the returned
url. - The customer lands on the Niftipay on-ramp page, selects a payment method (card or bank transfer), completes KYC if needed, and pays.
- The purchased crypto is sent directly to the invoice deposit address.
- Once the on-chain deposit is detected, the invoice is marked as
paidand your webhook fires.
Create a pay-link
POST /api/ramping/links
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
firstName | string | Yes | Customer’s first name. |
lastName | string | Yes | Customer’s last name. |
email | string | Yes | Customer’s email. Used for verification and KYC. |
fiatAmount | string or number | Yes | The fiat amount the merchant wants to receive (net). Must be a valid decimal. |
network | string | No | Blockchain network: BTC, LTC, ETH, SOL, or XRP. Falls back to your saved defaults if omitted. |
asset | string | No | Crypto asset: BTC, LTC, ETH, SOL, XRP, USDT, or USDC. USDT/USDC require network to be ETH. Falls back to your saved defaults if omitted. |
fiatCurrency | string | No | Fiat currency code. Defaults to EUR if not provided and no saved default. See supported currencies below. |
reference | string | No | Your own unique reference for this order. If provided, must be unique across your orders. |
merchantId | string | No | Optional merchant identifier for multi-merchant setups. |
provider | string | No | Optional provider preference. If omitted, the provider is chosen automatically based on customer geolocation. |
Ifnetworkandassetare not provided, the API will use your saved defaults from/api/ramping/settings-token. If no defaults are saved either, the request will fail with a 400 error.
Query parameters
| Param | Type | Notes |
|---|---|---|
replaceCancelled | "1" | If set, allows re-creating a link for a previously cancelled order with the same reference. |
Success response (200)
Response fields
url
The full public URL to redirect your customer to. This is the on-ramp checkout page.
order
| Field | Type | Notes |
|---|---|---|
id | string | Internal order ID. |
reference | string | Your reference (or auto-generated). |
network | string | Blockchain network. |
asset | string | Crypto asset. |
amountCrypto | string | The crypto amount the customer needs to send. |
fiatCurrency | string | Fiat currency code. |
fiatAmount | string | Net fiat amount. |
depositAddress | string | The on-chain address the customer will send to. |
destinationTag | string or null | XRP destination tag (only for XRP). |
paymentUri | string | Payment URI for wallet apps. |
qrUrl | string | QR code image URL. |
status | string | Order status (starts as pending). |
createdAt | string | ISO 8601 creation timestamp. |
expiresAt | string | ISO 8601 expiration timestamp. |
merchantId | string or null | Your merchant ID if provided. |
link
| Field | Type | Notes |
|---|---|---|
orderId | string | Same as order.id. |
reference | string | Same as order.reference. |
fiat | string | Fiat currency. |
fiatAmount | string | Net fiat amount. |
crypto | string | Crypto asset. |
blockchain | string | Blockchain network. |
expiresAt | string | When the pay-link token expires. |
invoiceExpiresAt | string | When the underlying invoice expires. |
invoiceStatus | string | Current invoice status. |
providerHint | string or null | Provider hint if specified. |
fiatAmountNet | string or null | Net fiat amount (provider prefill). |
fiatAmountGross | string or null | Gross fiat amount including fees (provider prefill). |
feePercent | number or null | Fee percentage applied (provider prefill). |
Supported fiat currencies
The following fiat currencies are supported for on-ramping:| Code | Currency |
|---|---|
USD | US Dollar |
EUR | Euro |
GBP | British Pound |
AUD | Australian Dollar |
AED | UAE Dirham |
BRL | Brazilian Real |
CAD | Canadian Dollar |
CHF | Swiss Franc |
CZK | Czech Koruna |
DKK | Danish Krone |
HKD | Hong Kong Dollar |
IDR | Indonesian Rupiah |
INR | Indian Rupee |
JPY | Japanese Yen |
MXN | Mexican Peso |
NOK | Norwegian Krone |
NZD | New Zealand Dollar |
PHP | Philippine Peso |
PLN | Polish Zloty |
QAR | Qatari Riyal |
RON | Romanian Leu |
SAR | Saudi Riyal |
SEK | Swedish Krona |
SGD | Singapore Dollar |
THB | Thai Baht |
TRY | Turkish Lira |
TWD | New Taiwan Dollar |
VND | Vietnamese Dong |
ZAR | South African Rand |
Availability of specific currencies may vary depending on the customer’s country and the on-ramp provider selected.
Bank approval rates
On-ramping is limited by the customer’s card-issuing bank. Each bank has a historic approval rate that determines how likely a card transaction is to succeed. See the full Bank Approval Rates reference for all supported banks and their approval percentages by region.Error responses
| Status | Condition | Example |
|---|---|---|
| 400 | Missing required fields | { "error": "firstName, lastName, email are required" } |
| 400 | Invalid fiat amount | { "error": "fiatAmount is required and must be a number (string or number)" } |
| 400 | Missing network/asset with no defaults | { "error": "network and asset are required. Either provide them in the request or set defaults via /api/ramping/settings-token." } |
| 400 | Unsupported network | { "error": "Unsupported network: ABC" } |
| 400 | Asset/network mismatch | { "error": "USDC/USDT require ETH" } |
| 403 | Crypto not enabled for ramping | { "error": "Crypto not enabled for ramping" } |
| 409 | Duplicate reference | { "error": "Reference already exists" } |
| 409 | No available deposit addresses | { "error": "No available addresses" } |
Examples
Example 1 — Basic pay-link (EUR, ETH network)
Example 2 — With reference and merchant ID
Example 3 — Using saved defaults (no network/asset/fiat)
If you have already configured defaults via the dashboard or/api/ramping/settings-token:
Example 4 — Replace a cancelled order
If a previous order with the same reference was cancelled and you want to create a new one:Customer flow after redirect
Once your customer opens theurl returned by this endpoint:
- They see the on-ramp checkout page with the invoice details pre-filled.
- They enter their email (used for verification code and KYC).
- They select a payment method: Debit/Credit Card or Bank Transfer.
- They are redirected to complete KYC and payment.
- The crypto is purchased and sent to the invoice deposit address.
- Once the on-chain deposit is confirmed, the invoice status changes to
paid.
The on-ramp provider is automatically selected based on the customer’s geolocation. You can override this with the provider field in the API request.
Node.js Example
A complete Node.js example showing how to create an onramping pay-link, including all optional fields and response parsing.See the full working script with setup and helper function: API Examples (Node.js)
Webhooks
Ramping orders fire events on two channels, both delivered to your merchant webhook URL with the same HMAC signing scheme:- Core order events (
pending,paid,cancelled,expired,refunded) track the underlying crypto invoice — the same events you receive for direct crypto orders. - Ramping events (
ramping.status_changed,ramping.kyc_pending) track the onramp provider’s own lifecycle (KYC, fiat capture, status transitions).
Expiry behavior for Banxa orders
Crypto invoices created through the ramping flow get an initialexpiresAt = createdAt + 12 hours, the same as direct invoices. Onramp orders behave differently when KYC is in progress:
- If the linked Banxa order is still in a non-terminal status (e.g.
extraVerification,pendingPayment,waitingPayment,paymentReceived) as the 12h mark approaches, Niftipay automatically extends the invoice’sexpiresAtup to a 72-hour hard cap from the ramping order’s creation time and emits aramping.kyc_pendingevent. - If KYC clears within 72h, funds are delivered on-chain and you receive the normal
paidevent. - If KYC does not clear within 72h, the invoice is force-cancelled and you receive an
expiredevent withreason: "ramping_kyc_timeout"plus a finalramping.status_changedwithreason: "kyc_timeout_72h".