Quotes
A quote locks a rate for a short window and is spent by the order that uses it.
Every order is created against a quote. You cannot create one at "the current rate" — the rate has to be locked first, and the quote is the lock.
Taking a quote
POST /v1/quotes with a side and one of the two legs. The other is
derived:
{
"side": "sell",
"usdtAmount": "250.000000"
}side is sell (USDT in, KES out) or buy (KES in, USDT out). Whichever leg
you did not supply is the computed one, and it rounds in OnLink's favour — which
is why you should always display the amounts from the response rather than your
own multiplication.
What comes back
{
"quoteId": "f1c0a5d2-3b4e-4a71-9c8d-0e1f2a3b4c5d",
"side": "sell",
"kesAmount": "32025.00",
"usdtAmount": "250.000000",
"rate": "128.10",
"expiresAt": "2026-09-04T09:31:30.000Z",
"settlementEstimateSeconds": 1800
}rateis KES per USDT, locked for this quote.kesAmountalways carries 2 decimal places,usdtAmountalways 6. Both are strings. See Money.expiresAtis when the lock stops being executable.settlementEstimateSecondsis a coarse band, not a commitment. Use it to set your user's expectation; do not build a timeout around it.
Single-use, and short-lived
A quote is consumed by the order that uses it. Presenting a spent or expired
quote is a 409 with QUOTE_EXPIRED_OR_CONSUMED in the message — not a
silent re-quote, because a re-quote would execute at a rate you never saw.
The default window is 90 seconds. It can be configured per partner, so read
expiresAt rather than assuming the default; a quote you took under one setting
is not proof of the next.
A quote is also side-specific. A buy quote presented to POST /v1/orders/sell
is refused with QUOTE_SIDE_MISMATCH.
Practical shape
Take the quote at the moment your user is ready to commit, not when they open
the screen. If they hesitate past expiresAt, take a new one and show them the
new amounts — that is the whole point of a lock with an expiry.
There is no minimum beyond an amount greater than zero. Your ceilings are per-partner: see Caps and limits.