> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ripio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# On-Ramp integration

> Step-by-step walkthrough to convert fiat into crypto with the Ramps API, using either a single on-ramp order or a reusable on-ramp session.

On-Ramp lets your users buy crypto with fiat. There are **two ways** to run an on-ramp, and you can use either (or both) depending on your product. For request and response details, follow the endpoint link in each step.

<Note>
  Available payment methods depend on the country. See [Countries & payment methods](/ramps-api/overview/countries/overview) first.
</Note>

## Two ways to run an on-ramp

| | On-Ramp order | On-Ramp session |
| - | - | - |
| **What it is** | A single purchase tied to one quote (locked rate). | A reusable deposit account (e.g. a CVU/CLABE) tied to a destination crypto address. |
| **How orders are created** | You create the order explicitly. | Orders are created **automatically** each time the customer sends fiat to the session's deposit account. |
| **Rate** | The quote you pass. | The market rate at the moment of each deposit. |
| **Best for** | One-off purchases with a confirmed amount. | Recurring top-ups where the customer sends fiat whenever they want. |

Both share the same setup (customer and KYC).

## Common setup

<Steps>
  <Step title="Authenticate">
    Get an access token with the OAuth2 Client Credentials flow using your `client_id` and `client_secret`. Send it as a `Bearer` token on every subsequent call.

    → [Acquire Access Token](/ramps-api/authentication/acquire-access-token)
  </Step>

  <Step title="Create the customer">
    Register the end user as a customer. You'll use the returned `customerId` throughout the flow.

    → [Create Customer](/ramps-api/customers/create-customer)
  </Step>

  <Step title="Accept Terms & Conditions">
    Right after creating the customer, register their acceptance of the active Terms & Conditions. This is a required step before the customer can operate.

    It is also a recurring one: acceptance covers the version that was shown, so a new version for the country blocks the customer again until they accept it. Re-check before operating instead of storing the result.

    → [Terms & Conditions](/ramps-api/terms-and-conditions/introduction) · [Accept Terms](/ramps-api/customers/accept-terms)
  </Step>

  <Step title="Verify identity (KYC)">
    The customer must complete KYC before operating — the status must be `COMPLETED`. Choose the model that fits your integration (Ripio-hosted redirect or partner-submitted via API), and reuse an existing Ripio KYC via OTP when possible.

    → [Identity verification (KYC)](/ramps-api/kyc/overview)
  </Step>

  <Step title="Brazilian accounts: collect the investor profile">
    If your account is in Brazil, your customers must answer a short suitability questionnaire after KYC and before their first order or session, and again every year. Check the status, show the questionnaire when it is `REQUIRED` or `EXPIRED`, and submit the answers; without it, creating an order, a session or a destination account fails with `20100`. Accounts in other countries skip this step, whatever the customer's nationality.

    → [Investor Profile (Brazil)](/ramps-api/investor-profile/introduction)
  </Step>

  <Step title="Provision the deposit account">
    The fiat **deposit account** is what the end user transfers to — a CVU in Argentina, a CLABE in Mexico, a BRE-B key in Colombia. Whether you must create it **before** the order depends on the country and the payment method: check [Deposit account by country](#deposit-account-by-country) below. Brazil (PIX) has no deposit account at all — the order itself returns a payable BR Code.

    Where it is required, the deposit key is assigned **asynchronously** by the payment provider: the account starts as `processing` and becomes `enabled` once it can receive transfers. Subscribe to `ACCOUNT.ENABLED` instead of polling — the creation call answers `201` immediately, before the key exists.

    → [Create Deposit Account](/ramps-api/customers/create-deposit-account) · [Account Events](/ramps-api/webhooks/account-events)
  </Step>
</Steps>

### Deposit account by country

| Country | On-Ramp payment method | Deposit account before the order |
| - | - | - |
| Argentina | Bank transfer (CVU) | Not needed — the CVU comes back with the order. |
| Mexico | Bank transfer (CLABE / SPEI) | **Required**, and it must be `enabled`. |
| Colombia | Bank transfer (PSE) · Request-to-Pay (Bancolombia, Nequi) | Not needed — the order provisions it and returns the instructions. |
| Colombia | BRE-B | **Required**, and it must be `enabled`. |
| Brazil | PIX | Not needed — the order returns a payable BR Code, valid until its `expiresAt`. `pix` is not available through an On-Ramp Session. |

<Warning>
  Creating the order before a required deposit account is ready returns **HTTP `400`** — not because of your payload. Two different codes, and they need opposite reactions:

  * **`40019` `FiatAccountNotCreatedException`** — the account was never created. Create it; retrying the order will never succeed on its own.
  * **`40014` `FiatAccountNotReadyException`** — it exists but is still `processing`. Wait for `ACCOUNT.ENABLED` and create the order then.

  Always read the `code` field of the error body before looking for a mistake in your request.
</Warning>

## Option 1 — Single on-ramp order

<Steps>
  <Step title="Create a quote">
    Request an on-ramp quote (fiat → crypto) with the `customerId`, specifying amount and payment method. The quote holds a price for a limited time and returns a `quoteId`. Quotes are scoped to a customer, so this step always comes after creating one.

    → [Create Quote](/ramps-api/quotes/create-quote)
  </Step>

  <Step title="Create the on-ramp order">
    Create the order with the `quoteId`, the `customerId`, the destination `depositAddress` (crypto) and a partner `externalRef`. The response includes the **fiat payment instructions** (for example, the CVU/CLABE to transfer to, or a payment link).

    If the country and payment method require a deposit account, it must already be `enabled` by this point — otherwise the call returns `400`, with code `40019` if the account was never created or `40014` if it is still `processing`. See [Deposit account by country](#deposit-account-by-country).

    → [Create On-Ramp Order](/ramps-api/on-ramp/create-on-ramp-order)
  </Step>

  <Step title="User pays and the order completes">
    The customer pays the fiat amount using the returned instructions. Once the deposit is detected and the trade executes, the order moves to `COMPLETED` and the crypto is sent to the destination address.

    Track it with [On-Ramp Events](/ramps-api/webhooks/on-ramp-events) (recommended) or by polling [List On-Ramp Orders](/ramps-api/on-ramp/list-on-ramp-orders).
  </Step>
</Steps>

## Option 2 — On-ramp session

<Steps>
  <Step title="Create the on-ramp session">
    Create a session for the customer with the destination crypto address, network and currency. The response includes a reusable **fiat deposit account** (e.g. a CVU) and its payment instructions. If the customer already has a session, it is reused/updated. The session does not expire.

    → [Create On-Ramp Session](/ramps-api/on-ramp/create-on-ramp-session)
  </Step>

  <Step title="User deposits fiat — orders are created automatically">
    The customer can send fiat to the session's deposit account as many times as they want. Each deposit automatically creates an on-ramp order, converts the funds at the current rate and sends the crypto to the destination address. No per-deposit API call is needed.

    Track each order with [On-Ramp Events](/ramps-api/webhooks/on-ramp-events) or by inspecting the session via [Retrieve an On-Ramp Session](/ramps-api/on-ramp/retrieve-an-on-ramp-session).
  </Step>
</Steps>

## Order lifecycle

| Status | Meaning |
| - | - |
| `PENDING` | Order created, waiting for the fiat payment. |
| `PROCESSING` | Payment detected, trade in progress. |
| `COMPLETED` | Crypto delivered to the destination address. |
| `CANCELLED` | Something went wrong with the order and it needs review. It can be resolved through customer support (CX). |
| `REFUNDED` | The amount was refunded to the customer. |

A cancelled order's fiat can be returned to the customer — see [Refunds](/ramps-api/refunds/overview).

## Testing in sandbox

In sandbox there's no real fiat movement. If your sandbox account is configured to skip KYC, you can go straight through the ramp flow. If KYC is enabled, complete the KYC step first and use the sandbox KYC simulation endpoints to approve or reject the submission.

→ [KYC in sandbox](/ramps-api/sandbox/kyc-in-sandbox)

Then use the deposit simulation endpoint to move an order forward as if the user had paid.

→ [Simulate Deposit for On-Ramp (Sandbox)](/ramps-api/sandbox/simulate-deposit-for-on-ramp-sandbox)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.