---
title: "Create a v2 payment order (offramp or onramp)"
method: POST
path: "/sender/orders"
tags: ["Sender"]
---

# Create a v2 payment order (offramp or onramp)

`POST /sender/orders`

Creates a new payment order.

- **Offramp** (stablecoin → fiat): set `source.type = "crypto"` and `destination.type = "fiat"`.
  The response `providerAccount` contains a `receiveAddress` to send tokens to.
- **Onramp** (fiat → stablecoin): set `source.type = "fiat"` and `destination.type = "crypto"`.
  The response `providerAccount` contains a virtual bank account for the user to deposit fiat into.

## Request body

- V2PaymentOrderPayload
  - `amount` string, required — Payment amount. Denomination is determined by `amountIn` (defaults to crypto units).
  - `amountIn` 'crypto' | 'fiat' — Specifies whether `amount` is denominated in crypto or fiat. Defaults to `crypto`.
  - `rate` string — Quoted exchange rate (fiat per crypto unit). Optional — protocol uses best available rate if omitted.
  - `senderFee` string — Fixed sender fee in crypto units.
  - `senderFeePercent` string — Sender fee as a percentage of the order amount (alternative to senderFee).
  - `reference` string — Your internal reference ID for this order.
  - `source` union, required — Polymorphic source — set `type: "crypto"` for offramp or `type: "fiat"` for onramp.
    - V2CryptoSource
      - `type` 'crypto', required
      - `currency` string, required — Stablecoin symbol (e.g. USDT, USDC, cNGN)
      - `network` 'ethereum' | 'base' | 'bnb-smart-chain' | 'lisk' | 'scroll' | 'celo' | 'arbitrum-one' | 'polygon', required
      - `refundAddress` string, required — Wallet address for refunds if the order can't be fulfilled
    - V2FiatSource
      - `type` 'fiat', required
      - `currency` string, required — Fiat currency code (e.g. NGN, KES, BRL)
      - `country` string — ISO 3166-1 alpha-2 country code (optional)
      - `refundAccount` V2FiatRefundAccount, required
        - `institution` string, required — Bank or mobile provider code (SWIFT prefix or Paycrest institution code)
        - `institutionName` string — Human-readable institution name (e.g. OPay). Present on GET responses when the code resolves in Paycrest.
        - `accountIdentifier` string, required — Account number or mobile number
        - `accountName` string, required — Account holder name
  - `destination` union, required — Polymorphic destination — set `type: "fiat"` for offramp or `type: "crypto"` for onramp.
    - V2FiatDestination
      - `type` 'fiat', required
      - `currency` string, required — Fiat currency code (e.g. NGN, KES)
      - `country` string — ISO 3166-1 alpha-2 country code (optional)
      - `providerId` string — Pin order to a specific provider (optional)
      - `kyc` object — Optional destination (recipient) KYC for offramp. Do not send sender or provider KYB on offramp create.
      - `recipient` V2FiatRecipient, required
        - `institution` string, required — Institution code (e.g. SAFAKEPC for Safaricom M-Pesa). Till and Paybill use the same mobile institution with channel metadata.
        - `institutionName` string — Human-readable institution name (e.g. OPay). Present on GET responses when the code resolves in Paycrest.
        - `accountIdentifier` string, required — Bank account, mobile phone (E.164 or local), till number, or paybill account reference depending on channel.
        - `accountName` string, required
        - `memo` string, required — Payment narration / reference
        - `metadata` object — Corridor-specific hints. For KES mobile offramp, use channel and optional businessNumber (see Sender API Integration guide).
          - `channel` 'Mobile' | 'Till' | 'Paybill' — KES payout channel. Mobile = phone M-Pesa; Till = buy goods; Paybill = paybill. Omit for default phone M-Pesa when accountIdentifier is a mobile number.
          - `businessNumber` string — Paybill business number (required for Paybill when not inferrable from accountIdentifier alone).
    - V2CryptoDestination
      - `type` 'crypto', required
      - `currency` string, required — Stablecoin symbol (e.g. USDT, USDC)
      - `providerId` string
      - `recipient` V2CryptoRecipient, required
        - `address` string, required — Wallet address to receive stablecoins
        - `network` 'ethereum' | 'base' | 'bnb-smart-chain' | 'lisk' | 'scroll' | 'celo' | 'arbitrum-one' | 'polygon', required

## Response `201`

Order created

- object
  - `status` string
  - `message` string
  - `data` V2PaymentOrderResponse — Response returned when creating an order
    - `id` string, uuid
    - `status` string
    - `orderType` 'regular' | 'otc'
    - `timestamp` string, date-time
    - `amount` string — Crypto amount in token units
    - `rate` string
    - `senderFee` string
    - `senderFeePercent` string
    - `transactionFee` string
    - `reference` string
    - `providerAccount` union — Crypto provider account for offramp; fiat provider account (virtual account) for onramp
      - V2CryptoProviderAccount — Returned for offramp orders — the address to send stablecoins to
        - `network` string
        - `receiveAddress` string — EVM address to send stablecoins to
        - `validUntil` string, date-time — Deadline for the stablecoin deposit
      - V2FiatProviderAccount — Returned for onramp orders — the virtual account to deposit fiat into
        - `institution` string — Institution label for the virtual account (human-readable; from provider or stored metadata).
        - `accountIdentifier` string — Account number or mobile number to send fiat to
        - `accountName` string
        - `amountToTransfer` string — Exact fiat amount the user must deposit
        - `currency` string — Fiat currency code
        - `validUntil` string, date-time — Deadline — order expires if fiat not received by this time
    - `source` union
      - V2CryptoSource
        - `type` 'crypto', required
        - `currency` string, required — Stablecoin symbol (e.g. USDT, USDC, cNGN)
        - `network` 'ethereum' | 'base' | 'bnb-smart-chain' | 'lisk' | 'scroll' | 'celo' | 'arbitrum-one' | 'polygon', required
        - `refundAddress` string, required — Wallet address for refunds if the order can't be fulfilled
      - V2FiatSource
        - `type` 'fiat', required
        - `currency` string, required — Fiat currency code (e.g. NGN, KES, BRL)
        - `country` string — ISO 3166-1 alpha-2 country code (optional)
        - `refundAccount` V2FiatRefundAccount, required
          - `institution` string, required — Bank or mobile provider code (SWIFT prefix or Paycrest institution code)
          - `institutionName` string — Human-readable institution name (e.g. OPay). Present on GET responses when the code resolves in Paycrest.
          - `accountIdentifier` string, required — Account number or mobile number
          - `accountName` string, required — Account holder name
    - `destination` union
      - V2FiatDestination
        - `type` 'fiat', required
        - `currency` string, required — Fiat currency code (e.g. NGN, KES)
        - `country` string — ISO 3166-1 alpha-2 country code (optional)
        - `providerId` string — Pin order to a specific provider (optional)
        - `kyc` object — Optional destination (recipient) KYC for offramp. Do not send sender or provider KYB on offramp create.
        - `recipient` V2FiatRecipient, required
          - `institution` string, required — Institution code (e.g. SAFAKEPC for Safaricom M-Pesa). Till and Paybill use the same mobile institution with channel metadata.
          - `institutionName` string — Human-readable institution name (e.g. OPay). Present on GET responses when the code resolves in Paycrest.
          - `accountIdentifier` string, required — Bank account, mobile phone (E.164 or local), till number, or paybill account reference depending on channel.
          - `accountName` string, required
          - `memo` string, required — Payment narration / reference
          - `metadata` object — Corridor-specific hints. For KES mobile offramp, use channel and optional businessNumber (see Sender API Integration guide).
            - `channel` 'Mobile' | 'Till' | 'Paybill' — KES payout channel. Mobile = phone M-Pesa; Till = buy goods; Paybill = paybill. Omit for default phone M-Pesa when accountIdentifier is a mobile number.
            - `businessNumber` string — Paybill business number (required for Paybill when not inferrable from accountIdentifier alone).
      - V2CryptoDestination
        - `type` 'crypto', required
        - `currency` string, required — Stablecoin symbol (e.g. USDT, USDC)
        - `providerId` string
        - `recipient` V2CryptoRecipient, required
          - `address` string, required — Wallet address to receive stablecoins
          - `network` 'ethereum' | 'base' | 'bnb-smart-chain' | 'lisk' | 'scroll' | 'celo' | 'arbitrum-one' | 'polygon', required

## Other responses

- `400` — Validation error
- `401` — Unauthorized
- `503` — No provider available for this corridor

---

[API](https://skmtc.net/paycrest/apis/paycrest-aggregator-api.md) · [All operations](https://skmtc.net/paycrest/apis/paycrest-aggregator-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/paycrest/paycrest-aggregator-api/revisions/f20903971a91/schema)
