Partner API

Create a sell order (USDT in, KES out)

Consumes a sell quote and takes your USDT at create — from your USDT balance, or from your own wallet, depending on your account. Payout is asynchronous: nothing is paid out until the order’s USDT is confirmed. A signed webhook tells you when it settles; polling is the fallback. Retry-safe: creating twice with the same partnerReference returns the original order rather than a second one. The response carries your deposit address, which is the same for every order: it tops up your USDT balance and is not tied to any one order.

post/v1/orders/sell

Request

  • Base URL
    https://sandbox.onlink.africa
  • Auth
    API key in header X-OnLink-Key

Request body

quoteIdstring required

A quote id from POST /v1/quotes with side=sell. Single-use, and the amounts are taken from it — they are not restated here.

partnerReferencestring required

Your own reconciliation handle. Unique per partner, and RETRY-SAFE: creating twice with the same reference returns the original order rather than a second one.

payoutAccountIdstring required

Which of your registered KES destinations to pay out to. Destinations are set up by OnLink, not through this API — see GET /v1/funding.

Response

Order created, awaiting your USDT

orderIdstring uuid required

The order id. Use it for PATCH and GET /v1/orders/{id}.

status'awaiting_payment' | 'awaiting_usdt' | 'payment_matched' | 'usdt_received' | 'funds_reserved' | 'awaiting_approval' | 'rejected' | 'sending' | 'paying_out' | 'settled' | 'expired' | 'review' required

Where the order is now. A newly created sell order is awaiting_usdt; attaching the hash moves it on once your deposit is attributed to this order. settled, rejected and expired are the terminal states. Settlement is asynchronous — subscribe to webhooks rather than polling this field to completion.

kesAmountstring required

The trade PRINCIPAL in KES, decimal string, always 2 decimal places (KES cents). Taken from the quote — never restated by you, never a JSON number. This is not what you receive: we pay kesTotalAmount, which is this figure less the disclosed fee.

usdtAmountstring required

USDT to send us, decimal string, always 6 decimal places. Never a JSON number.

ratestring required

KES per USDT the order is priced at, from the consumed quote.

kesTotalAmountstring required

What we pay you: principal − fee. This is the figure that appears on your bank statement, so it is the one to reconcile against.

expiresAtstring date-time required

Deposit deadline, ISO 8601 UTC. The same instant as sendBefore. This is the deposit window, not the quote TTL — the rate is already locked.

depositAddressstring required

Your Tron (TRC-20) deposit address, in full. It is permanent and the same for every one of your orders; USDT sent to it tops up your USDT balance, and a sell order is paid from that balance — nothing is sent per order. Compare the whole string, never a prefix: a lookalike address differing only in the middle is an irrecoverable burn.

chain'tron' required

Deposit network. Tron only at launch.

sendBeforestring date-time required

The deposit deadline again, under the name the integration guide uses. The same instant as expiresAt; both are present so you need not know they are one field.

Example response

{
  "orderId": "3a7c1f90-8b2d-4e56-9a01-cd23ef456789",
  "status": "awaiting_usdt",
  "kesAmount": "1281000.00",
  "usdtAmount": "10000.000000",
  "rate": "128.1000",
  "kesTotalAmount": "1268180.00",
  "fee": {
    "kesAmount": "12820.00",
    "currency": "KES",
    "percentBps": 100,
    "flatKesAmount": "10.00"
  },
  "expiresAt": "2026-09-01T09:30:00.000Z",
  "depositAddress": "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb",
  "chain": "tron",
  "sendBefore": "2026-09-01T09:30:00.000Z"
}

Changes

No recorded changes to this operation across all 1 revision of this API.