---
name: rampnow
description: Use when integrating Rampnow fiat-to-crypto (onramp, buy) or crypto-to-fiat (offramp, sell) into an app, through the Rampnow widget, the @rampnow/sdk package or the Intent API (server-side signed orders with hosted checkout), including request signing, order statuses and webhooks.
metadata:
  version: "2.0"
  docs: https://docs.rampnow.io
---

# Rampnow

Rampnow lets users buy crypto with fiat (onramp, `orderType: "buy"`) and sell crypto for fiat (offramp, `orderType: "sell"`). The docs are at https://docs.rampnow.io. Append `.md` to any page URL for Markdown. The full docs are in https://docs.rampnow.io/llms-full.txt.

## Pick one integration first

There are two separate products. Don't mix their keys, hosts or code.

| | Widget / SDK | Intent API |
|---|---|---|
| Who builds the order | The user, in Rampnow's UI | Your backend, via REST |
| Backend needed | No | Yes |
| Credential | Public key `pk_...` only. No secret, no signing | API key + API secret, HMAC-signed requests |
| Entry point | URL `https://app.rampnow.io/order/quote?apiKey=...`, or `new RampnowSdk({...})` from `@rampnow/sdk` | `POST /api/partner/v1/ext/ramp_order/checkout`, then redirect the user to `redirectUrl` |
| Quickstart | https://docs.rampnow.io/get-started/widget.md, https://docs.rampnow.io/get-started/sdk.md | https://docs.rampnow.io/get-started/intent.md |

If the user hasn't said which one, ask. Widget/SDK is fastest; the Intent API suits teams that collect user details and want to own the flow.

## Environments

| | API base URL | Widget / checkout host |
|---|---|---|
| Production | `https://api.rampnow.io` | `https://app.rampnow.io` |
| Sandbox | `https://api.sandbox.rampnow.io` | `https://app.sandbox.rampnow.io` |

Keys only work in their own environment. Default to sandbox while building. Keys are in the Partner Dashboard (https://partner.rampnow.io) under **API Hub**.

## Widget / SDK

- Widget URL parameters: `apiKey`, `orderType`, `srcCurrency`, `srcChain`, `srcAmount`, `dstCurrency`, `dstChain`, `walletAddress`, `externalOrderId`. Fiat uses chain `fiat`. Full list: https://docs.rampnow.io/api-reference/widget-mode.md
- SDK: `npm install @rampnow/sdk`. Create it with `new RampnowSdk({ apiKey, orderType, ... })`, subscribe with `sdk.on(RampnowEventType.ORDER_COMPLETED, cb)`, then open it with `sdk.init()`. `widgetUrl` defaults to production. Set it to `https://app.sandbox.rampnow.io` for sandbox. Reference: https://docs.rampnow.io/api-reference/sdk.md
- Browser events are for UI only. Use webhooks to decide whether an order succeeded.

## Intent API

All endpoints are under `/api/partner/v1/ext/ramp_order`:

1. Optional: discover what's supported with `GET /config` (full matrix, split into `buy` / `sell`) and `GET /blocked_currencies?country=DE`.
2. Price the order: `POST /quote`.
3. Create the order: `POST /checkout` with `orderType`, `externalOrderUid` (your ID), `srcCurrency`, `srcChain`, `srcAmount`, `dstCurrency`, `dstChain`, `returnUrl`, `user` and `wallet`. The response has `orderUid`, `userUid` and `redirectUrl`.
4. Send the user's browser to `redirectUrl`. Rampnow handles KYC and payment, then returns the user to `returnUrl`.
5. Track the order with webhooks, or poll `GET /{externalOrderUid}`.

Field-level detail: https://docs.rampnow.io/quickstart/ramp-intent/create-order.md. The OpenAPI spec is the source of truth for field names.

### Signing

Every Intent API request sends:

- `X-RAMPNOW-API-KEY`: your API key
- `X-RAMPNOW-TIMESTAMP`: Unix time in seconds
- `X-RAMPNOW-SIGN`: hex HMAC-SHA256, keyed with the API secret, of `timestamp + METHOD + path + body`

`path` starts with `/api/partner/v1` and includes the query string as sent. `body` is the exact string sent; it's empty for `GET`. No separators.

Test vector: secret `test-secret-key`, timestamp `1772080882`, `POST`, path `/api/partner/v1/ext/ramp_order/quote`, body `{"orderType":"buy","srcAmount":"100","srcCurrency":"EUR","srcChain":"fiat","dstCurrency":"ETH","dstChain":"ethereum"}` gives `369afe98d71b99e4121f88643b38956d6bc8c23376426fb2c80b7ba2e6961243`. Check signing code against it before the first real call. Details: https://docs.rampnow.io/api-reference/authentication.md

## Order statuses

| Status | Final | Notes |
|---|---|---|
| `unknown` | No | Created, but the user hasn't confirmed on the hosted page. No webhook |
| `created` | No | Waiting for payment or deposit. Expires after 15 minutes unpaid |
| `payment_processing` | No | No webhook |
| `processing` | No | Payment accepted; delivery or payout in progress |
| `completed` | Yes | Reconcile on `dstFillAmount`, not `dstAmount` |
| `failed` | **No** | Rampnow ops retries or blocks it. Don't refund or close on your side |
| `payment_failed`, `expired` | Yes for the user | A late payment can still move it to `processing` |
| `blocked` | Yes | Compliance block, refunded |

Treat unknown future statuses as "in progress". Reference: https://docs.rampnow.io/api-reference/order-status.md

## Webhooks

- Configure one account-level URL in API Hub and subscribe to `ramp_order.status_change`. The `webhookUrl` field on checkout isn't used for delivery.
- Status is in `payload.orderStatus`. Get Order returns it as `status`.
- Verify `X-RAMPNOW-SIGN` = hex HMAC-SHA256, keyed with the API secret, of `timestamp + "POST" + path + rawBody`. Here `path` is the path of the webhook URL configured in API Hub, used as a constant. Reject timestamps more than 5 minutes off.
- De-duplicate on `eventUid`. Ignore events whose `payload.updateTime` is older than the one you've stored. Return 2xx fast.
- Reference: https://docs.rampnow.io/api-reference/webhook.md

## Common mistakes

- Using a `pk_` key with signed Intent API calls, or signing widget/SDK requests. They are different products.
- Re-serialising JSON after signing. Sign the exact bytes you send.
- Timestamps in milliseconds, or more than 1 minute old.
- "Fixing" `crytpoAccountDetail` in the checkout `wallet` object. That spelling is the real field name. Sells use `bankAccountDetail`.
- Treating the `returnUrl` redirect or an SDK browser event as proof of payment. Confirm with a webhook or Get Order.
- Treating `failed` as final.
- Putting the API secret in frontend code or in an AI prompt.

## Testing

The sandbox delivers on testnets (for example `sepolia`, `base-sepolia`, `solana-devnet`). Payments go through a simulator you control from the Partner Dashboard. Test plan: https://docs.rampnow.io/api-reference/sandbox-testing.md
