OnLink
Concepts

References and attribution

Which reference identifies which order, per leg — and why neither leg needs you to attribute a payment any more.

Neither leg has an attribution problem to solve. The buy leg debits your own KES balance directly. The sell leg takes the USDT from your own USDT balance (or collects it from your own wallet) at the moment you create the order, so there is no deposit of yours to match to an order.

ReferenceWhoseWhere it comes fromUsed for
partnerReferenceYoursYou choose it.Idempotent order creation, on both legs.

partnerReference makes creation idempotent — reusing it on create returns the existing order rather than a second one. It never attributes money; there is no partner-supplied payment left to attribute on either leg.

Buying — nothing to attribute

POST /v1/orders/buy debits your own KES VA balance directly, the instant the order is created. There is no payer, no rail, and no incoming payment for a reference to identify — so there is no attribution problem on this leg at all. kesDebit.status on the order tells you where that debit stands; see Buy USDT with KES.

Selling — nothing to attribute either

POST /v1/orders/sell takes your USDT the instant the order is created: it is debited from your USDT balance, or collected from your own wallet, depending on how your account is configured. You never send USDT for a specific order, so there is no deposit to link to one — see Sell USDT, receive KES.

Your Tron deposit address is long-lived and the same for every one of your orders. It tops up your USDT balance generally, so it cannot tell two of your orders apart and is not meant to: a deposit to it announces itself with usdt_credit.received, not against an order.

The transaction hash

PATCH /v1/orders/{id} still exists. It accepts the Tron transaction hash of a USDT send for a sell order that is still awaiting_usdt, and it is not part of the current sell flow — see Sell USDT, receive KES.

A hash is normalised before comparison — case and a leading 0x are ignored, because those are the same on-chain transaction. One hash attributes exactly one order.

GET /v1/orders/{id} carries the hash attached to an order, once there is one:

{
  "status": "usdt_received",
  "txHash": "5d6a3c7b1e4f2a908c6d5b4a3928170f6e5d4c3b2a1908f7e6d5c4b3a2918070"
}

txHash is null until one is attached.

Everything else that identifies a resource

partnerReference and the transaction hash are the only references THIS page is about. Three other identifiers are easy to confuse with them:

  • orderId / transferId / sendId — the resource's own id, minted by us and returned on creation. Read the resource back with it (GET /v1/orders/:id, GET /v1/transfers/:id, GET /v1/usdt/sends/:id); every webhook about it carries the same id.
  • idempotencyKey — required on transfers and USDT sends (an order uses partnerReference for this same role instead): a retried create with the same key returns the original resource rather than a second one. See Idempotency.
  • A collection's reference — unlike everything above, this one is ours, not yours: we mint it (a short prefix, a hyphen, and 6 characters drawn from 23456789ABCDEFGHJKMNPQRSTUVWXYZ — no 0, 1, I, L or O, the characters most easily misread off a screen or a bank statement). It is the handle you and we use for this collection — it is not what your contributor quotes. What they quote is depositMessage, from depositInstructions, which is a different code. Treat reference as a value you receive and display, never one you generate.

Rules of thumb

  • partnerReference is for creation, not attribution. Reusing it on create returns the original order, which is what makes retries safe — it does nothing for attributing money.
  • One transaction hash funds one order. A hash already attributed to another order is refused (409); attaching a different hash to an order that already has one is refused the same way, never an overwrite.
  • Neither leg needs you to attribute a payment. The debit is yours, from your own balance, the moment you create the order.

On this page