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

# Create an offramp order

> Opens an offramp order that pays out to a bank account identified by bank code and account number. The account is confirmed with the provider first, so an unknown bank code or an account number that cannot be resolved is rejected before any order exists. When a bvn is given the order is credited to that end user — traced through their KYC record, or verified and registered if the BVN is new; without one the order is not attributed to any user. Provide either amount (token) or fiatAmount, not both. The returned address is where the tokens should be sent to fund the order.

Opens an order to convert a token into fiat and pay it into a bank account. This
is the explicit alternative to the [bank account
address](/concepts/bank-account-addresses) flow: instead of a standing address
that pays out whatever it receives, you state the amount up front, get back a
quote and a one-off funding address, and send the tokens there.

Reach for this when the amount matters — you are quoting a user a specific naira
figure, or you need the payout tied to a single deposit rather than to an
address that anyone can pay at any time.

## Naming the destination

The bank account is given as a `bankCode` (from [Get
banks](/api-reference/get-banks)) plus an `accountNumber`. Before any order is
written, Paj confirms that pair with the payout rail. An account number the bank
cannot resolve is a `400` and leaves nothing behind — there is no half-created
order to clean up.

The confirmed account holder's name comes back on the response as `accountName`.
It is the bank's answer, not an echo of your input, so it is worth showing to
the user as a last check before they part with funds.

## Amount: token or fiat, never both

Send **exactly one** of:

* **`amount`** — the quantity of `mint` you are selling. Paj prices it and tells
  you the `fiatAmount` that will land.
* **`fiatAmount`** — the payout you want the recipient to receive. Paj works
  backwards and tells you the `amount` of `mint` to send.

Sending both is a `400`; so is sending neither. `mint` is required either way,
and `chain` defaults to `SOLANA`.

## Choosing the chain

Orders open on any [supported chain](/concepts/chains): `SOLANA`, `TON`,
`ETHEREUM`, `BASE`, `BSC`, `MONAD` or `ARC`. This is the only way to pay out
from a chain other than Solana — the [bank account
address](/concepts/bank-account-addresses) is Solana only.

`mint` is the token's address on that chain: a Solana mint, an ERC-20 contract,
or a TON jetton master (`"TON"` for Toncoin). It is checked against `chain`, so
an EVM contract sent without a `chain` — which defaults to `SOLANA` — is a
`400`. The chain's settlement stablecoin —
USDC, or USDT on TON — pays out directly; anything else is priced at its USD
value when it lands.

```json theme={null}
{
  "bankCode": "000016",
  "accountNumber": "0025635480",
  "currency": "NGN",
  "amount": 20,
  "chain": "BASE",
  "mint": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
}
```

The `address` that comes back is in that chain's format, and is watched on that
chain alone. On the EVM chains the address is valid on all five networks, so a
user sending from a multi-chain wallet can easily pick the wrong one — make the
chain as prominent as the address when you show it.

## Attributing the order to a user

`bvn` is optional and identifies the end user the order belongs to. When you
send one, Paj traces it to that user through their KYC record; if the BVN is new
to Paj, it is verified with the identity provider and the user is registered from
the verified bio before the order is created. A BVN that fails verification is a
`400`.

Omit it and the order is simply not attributed to any individual — it stays a
business-level order under your API key. The payout still works, but it goes out
without a payer name attached.

## Funding the order

The response `address` is where the tokens go. Send `amount` of `mint` on
`chain` to that address and the order settles on its own — the deposit is the
instruction, and there is no second call to confirm it. Track progress by
`status`, which starts at `INIT` and ends at `COMPLETED` or `ERROR`.

<Warning>
  Funding addresses are drawn from a shared pool and reused. Creating a new order
  deprecates any earlier order sitting on the same address, so always send to the
  `address` from the response you are acting on — never to one you cached from a
  previous order.
</Warning>

Orders are not kept forever: an unfunded order is deleted 72 hours after it was
created. Treat the quote as good for that window, and re-create the order rather
than funding a stale one.

## Getting told when it settles

Paj `POST`s the order back to you on every status change, in the same shape as
this endpoint's response. It goes to the order's `webhookURL` if you set one,
and otherwise to the `rampWebhookURL` configured on your API key — so a key set
up once with [Update your webhook URLs](/api-reference/update-webhooks) covers
every order without repeating the URL. With neither, you are polling.

Deliveries are signed; see [Webhook signatures](/concepts/webhook-signatures).


## OpenAPI

````yaml POST /pub/v2/offramp
openapi: 3.0.0
info:
  title: Paj Public API
  description: >-
    Programmatic access to Paj's on/off ramp. Register a Nigerian bank account,
    get

    the on-chain address that pays it, create offramp orders for a specific
    amount,

    and read the live conversion rates.


    Every request must carry an `x-api-key` header. Keys are scoped to a
    business,

    and the rates you receive already have that business's fee applied.
  version: 2.0.0
  contact: {}
servers:
  - url: https://api.paj.cash
    description: Production
security: []
tags: []
paths:
  /pub/v2/offramp:
    post:
      tags:
        - Pub V2
      summary: Create an offramp order
      description: >-
        Opens an offramp order that pays out to a bank account identified by
        bank code and account number. The account is confirmed with the provider
        first, so an unknown bank code or an account number that cannot be
        resolved is rejected before any order exists. When a bvn is given the
        order is credited to that end user — traced through their KYC record, or
        verified and registered if the BVN is new; without one the order is not
        attributed to any user. Provide either amount (token) or fiatAmount, not
        both. The returned address is where the tokens should be sent to fund
        the order.
      operationId: PubV2Controller_createOfframpOrder
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOfframpOrderDto'
      responses:
        '201':
          description: The created offramp order
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionInterfaceDto'
        '400':
          description: >-
            The bvn could not be verified, the account number could not be
            confirmed, or the order failed validation
        '401':
          description: Missing or invalid API key (x-api-key header)
        '404':
          description: Unknown bank code
      security:
        - x-api-key: []
components:
  schemas:
    CreateOfframpOrderDto:
      type: object
      properties:
        accountNumber:
          type: string
          description: Account Number to receive funds
          example: 679be2527f99f556d77b8cc2
        currency:
          type: object
          description: Currency to receive funds
          example: NGN
        amount:
          type: number
          description: Token amount (provide either amount or fiatAmount, not both)
          example: 100
        fiatAmount:
          type: number
          description: Fiat amount (provide either amount or fiatAmount, not both)
          example: 100
        chain:
          type: object
          description: Chain
          example: SOLANA
          default: SOLANA
        webhookURL:
          type: string
          description: Callback webhook url
          example: https://mydomain.com/webhook
        saveBeneficiary:
          type: boolean
          description: Save beneficiary
          example: true
        description:
          type: string
          description: Payment description
          example: 'Payment for order #123'
        businessUSDCFee:
          type: number
          description: Business fee
          example: 0.5
          default: 0
        bankCode:
          type: string
          description: Code of the bank that receives the payout
          example: '000016'
        mint:
          type: string
          description: >-
            Mint address of the token being sold, on the given chain. On TON, a
            jetton master address or "TON" for Toncoin.
          example: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
        bvn:
          type: string
          description: >-
            BVN of the end user the order is created for. It is traced to that
            user's KYC record; if the BVN is not on file it is verified and the
            user is registered before the order is opened.
          example: '22222222222'
      required:
        - accountNumber
        - currency
        - bankCode
        - mint
    TransactionInterfaceDto:
      type: object
      properties:
        id:
          type: string
          description: Transaction Id
          example: 679be2527f99f556d77b8cc2
        address:
          type: string
          description: Address
          example: 4KSLE7EU1P7PQ8Rc4hdb2ZKq2JmWHD8UXJp7guEdyT9j
        signature:
          type: string
          description: Transaction Signature
          example: >-
            2oLx7XrXP7Df9dZca1difJ91ZFmA44EEadNqrZTecta6ugcX8BAETbpvKQs54r58fmJTQVLzUSuzvRBFwS1GfJLo
        mint:
          type: string
          description: Mint Address
          example: So11111111111111111111111111111111111111112
        currency:
          type: object
          description: Currency
          example: NGN
        amount:
          type: number
          description: Mint Amount
          example: 100000
        usdcAmount:
          type: number
          description: Usdc Amount
          example: 100
        fiatAmount:
          type: number
          description: Fiat Amount
          example: 100
        sender:
          type: string
          description: Wallet Public Key
          example: 4KSLE7EU1P7PQ8Rc4hdb2ZKq2JmWHD8UXJp7guEdyT9j
        recipient:
          type: string
          description: Recipient Public Key
          example: 4KSLE7EU1P7PQ8Rc4hdb2ZKq2JmWHD8UXJp7guEdyT9j
        rate:
          type: number
          description: Rate of currency to usdc
          example: 9
        status:
          type: object
          description: Transaction Status
          example: PENDDING
        transactionType:
          type: object
          description: Transaction Type
          example: OFF_RAMP
        createdAt:
          format: date-time
          type: string
          description: Transaction creation date
          example: '2026-09-28T14:55:27.097Z'
        accountNumber:
          type: string
          description: Account Number (for onramp transactions)
          example: '0025635480'
        accountName:
          type: string
          description: Account Name (for onramp transactions)
          example: Paj Inc.
        bank:
          type: string
          description: Bank Name (for onramp transactions)
          example: First Bank
        fee:
          type: number
          description: Transaction fee in usdc
          example: 0.2
        chain:
          type: object
          description: Chain
          example: SOLANA
      required:
        - id
        - address
        - signature
        - mint
        - currency
        - amount
        - usdcAmount
        - fiatAmount
        - sender
        - recipient
        - rate
        - status
        - transactionType
        - createdAt
        - accountNumber
        - accountName
        - bank
        - fee
        - chain
  securitySchemes:
    x-api-key:
      type: apiKey
      in: header
      name: x-api-key

````

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