Skip to main content
POST
Create an onramp order
Opens an order to convert fiat into a token. Paj hands you a virtual bank account, your user pays naira into it, and the token is delivered to the wallet you named. It is the mirror image of Create an offramp order, and the two share a shape: state the amount up front, get back somewhere to send funds, and let the deposit do the rest.

Amount: token or fiat, never both

Send exactly one of:
  • fiatAmount — what your user will pay, in currency. Paj works out how much token that buys.
  • amount — how much of mint your user should end up with. Paj works backwards to the fiat figure they must pay.
Sending both is a 400; so is sending neither. recipient, mint and chain are required either way.

Choosing the chain

chain is where the token is delivered, and can be any supported chain: SOLANA, TON, ETHEREUM, BASE, BSC, MONAD or ARC. recipient is a wallet on that chain and mint is the token’s address on it. Buying the chain’s settlement stablecoin (USDC, or USDT on TON) is a direct transfer. Any other token is swapped on-chain from that stablecoin, with the output delivered straight to recipient in the same step, so what arrives can differ slightly from the quote by the swap’s slippage.
On TON, mint is "TON" for Toncoin or a jetton master address for anything else. Any spelling of a TON address — EQ…, UQ… or raw 0:… — is accepted for both mint and recipient. recipient and mint must be addresses in the format of chain — a Solana address on an EVM order, or the reverse, is a 400.
An EVM address is valid on all five EVM chains, so the format alone cannot catch a user who gave you their wallet for the wrong EVM network. The token is sent on chain; confirm the wallet can receive there.

The account to pay

Four fields on the response describe where the money goes: accountName is worth a note: it comes back looking like Paj Inc.(Pay NGN 1,500.00). The amount is baked into the name deliberately, so the figure is visible inside the user’s own banking app while they are typing the transfer. Render it as-is, but drive your own UI from fiatAmount — parsing the name is fragile.
The virtual account is per-order and the amount is expected to match. Do not cache an account number and reuse it for a later order, and do not let a user send a different figure than the one quoted.

Charging your own fee

businessUSDCFee is your markup, in USDC, and it is added on top rather than taken out of the middle. If your user is buying 10ofatokenandyousetafeeof‘0.5‘,theyarebilledthenairaequivalentof10 of a token and you set a fee of `0.5`, they are billed the naira equivalent of 10.50 and still receive the full $10 of token. The fee comes back on the response as fee. Despite the name, it is counted in the chain’s settlement stablecoin, which on TON is USDT. Leave it off and you charge nothing beyond the rate, which already includes the spread configured for your business — see Rates.

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 stays a business-level order under your API key. If you only need your own identifier carried through, userExternalId is a free-text field Paj stores and echoes back without interpreting.

First-time recipients on Solana

If recipient has never held mint on Solana, a token account has to be created for it before the token can land, and that costs rent. Paj charges it to the order. Nothing is required from you — but a first purchase can cost fractionally more than a repeat one for the same user, which is worth knowing before a support ticket asks why.

Following the order

status starts at INIT and moves to PROCESSING when the deposit is confirmed, then COMPLETED once the token has been delivered. ERROR is terminal. Paj POSTs the whole order back to you at every one of those transitions, 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 on your API key; with neither, you are polling. Unpaid orders are not kept forever: an order is deleted 72 hours after it was created. Treat the quote as good for that window and open a fresh order rather than pointing a user at a stale account.

Authorizations

x-api-key
string
header
required

Body

application/json
currency
object
required

Local currency user wish to use

Example:

"NGN"

recipient
string
required

User wallet address

Example:

"4C8XFXBPG1Dm2eBs68oixjsVEzjxz5pwTDrLCR17ZRGz"

mint
string
required

Expected token mint address. On TON, a jetton master address or "TON" for Toncoin.

Example:

"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"

chain
object
required

Wallet Chain

Example:

"SOLANA"

fiatAmount
number

Amount user should doposite; in local currency. Mutually exclusive with amount.

Example:

100

amount
number

Amount of token user expected to receive. Mutually exclusive with fiatAmount.

webhookURL
string

Webhook URL to receive order status updates

Example:

"https://example.com/webhook"

userExternalId
string

User external id

Example:

"user-123"

businessUSDCFee
number
default:0

Business fee in USDC deducted from the token amount sent to the user

Example:

0.5

bvn
string

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"

Response

The created onramp order. accountNumber, accountName and bank are the account to pay; the order stays in INIT until the deposit lands.

id
string
required

Transaction Id

Example:

"679be2527f99f556d77b8cc2"

address
string
required

Address

Example:

"4KSLE7EU1P7PQ8Rc4hdb2ZKq2JmWHD8UXJp7guEdyT9j"

signature
string
required

Transaction Signature

Example:

"2oLx7XrXP7Df9dZca1difJ91ZFmA44EEadNqrZTecta6ugcX8BAETbpvKQs54r58fmJTQVLzUSuzvRBFwS1GfJLo"

mint
string
required

Mint Address

Example:

"So11111111111111111111111111111111111111112"

currency
object
required

Currency

Example:

"NGN"

amount
number
required

Mint Amount

Example:

100000

usdcAmount
number
required

Usdc Amount

Example:

100

fiatAmount
number
required

Fiat Amount

Example:

100

sender
string
required

Wallet Public Key

Example:

"4KSLE7EU1P7PQ8Rc4hdb2ZKq2JmWHD8UXJp7guEdyT9j"

recipient
string
required

Recipient Public Key

Example:

"4KSLE7EU1P7PQ8Rc4hdb2ZKq2JmWHD8UXJp7guEdyT9j"

rate
number
required

Rate of currency to usdc

Example:

9

status
object
required

Transaction Status

Example:

"PENDDING"

transactionType
object
required

Transaction Type

Example:

"OFF_RAMP"

createdAt
string<date-time>
required

Transaction creation date

Example:

"2026-09-28T14:55:27.097Z"

accountNumber
string
required

Account Number (for onramp transactions)

Example:

"0025635480"

accountName
string
required

Account Name (for onramp transactions)

Example:

"Paj Inc."

bank
string
required

Bank Name (for onramp transactions)

Example:

"First Bank"

fee
number
required

Transaction fee in usdc

Example:

0.2

chain
object
required

Chain

Example:

"SOLANA"