Ir al contenido
KOTOVADOCS
Lanzar App

Order statuses

Ver como Markdown

Esta página aún no está disponible en tu idioma.

An order has exactly one status at a time. The set of statuses is fixed within v1, so you can map every one of them to what your user sees.

status is one of these nine values. A new one would only come with a new API version, never within v1. is_final says whether the order can still change.

status What it means is_final
waiting_for_deposit The order exists at the source and waits for your user’s deposit. false
confirming_deposit The source has seen the deposit and is waiting for its network confirmations. false
exchanging The deposit is confirmed and the source is performing the swap. false
sending The source is sending the payout. The order stays here until the payout’s transaction is recorded, even when the source already reports the swap as done. false
completed The payout was sent: transactions.payout has its hash, and completed_at is set. true
action_required The source reported a problem with the order, or is holding it. status_detail says why. false
refunding A refund is under way. false
refunded The refund was sent. true
expired No deposit arrived before the deadline. false at first, true once a late deposit can no longer revive the order

The status is worked out from the order’s stored state each time you read it, and a read may first refresh that state from the source. Read the order with GET /orders/{id} until is_final is true.

  • completed and refunded are final as soon as they are reached.
  • expired becomes final only once the source’s late-deposit window has passed. The window is counted from the order’s creation: usually 24 hours, and shorter at some sources for some rate types. Until then a deposit that arrives late can still revive the order, and it moves on to confirming_deposit, or to action_required with the reason late_deposit. Whether a late deposit is honoured is the source’s decision.
  • At most sources, an order still waiting when its expires_at passes shows as expired straight away. Where the source can extend its deadline, the order stays waiting_for_deposit until the source says otherwise.

Decide on is_final, never on the status name: an expired order whose is_final is false can still change.

A typical order goes through these statuses in this order:

  1. waiting_for_deposit
  2. confirming_deposit
  3. exchanging
  4. sending
  5. completed

Other paths:

  • No deposit: waiting_for_deposit → expired. A late deposit inside the window: expired → confirming_deposit and on along the typical path, or expired → action_required (late_deposit).
  • A problem with the deposit or the swap: usually confirming_deposit or exchanging → action_required. Then, by your user’s choice, the automatic resolution or the source’s own decision: → refunding → refunded, or back to the typical path (exchanging → sending → completed).
  • A refund the source starts itself: → refunding → refunded.
  • A rejected refund address: action_required (refund_address_rejected) until your user gives a new one, then usually refunding → refunded.
  • A payout on hold: sending → action_required (payout_on_hold) → completed once the source sends the payout.

You will not necessarily see every step. A read shows the status at that moment, and a fast order can move several steps between two reads. Statuses do not always move forward through the table either: an expired order can come back, and a sending order can become action_required.

  • waiting_for_deposit: deposit.address, deposit.amount and from.network, and deposit.memo under the name in deposit.memo_label when it is set. Your user must send the memo with the deposit, so show it prominently. Show the time left until expires_at, and ask your user to send exactly deposit.amount on from.network.
  • confirming_deposit: the deposit has arrived and is being confirmed. Show transactions.deposit.confirmations out of required_confirmations when both are known, and link to transactions.deposit.explorer_url.
  • exchanging: the source is performing the swap. estimated_duration_seconds gives a rough idea of the time left.
  • sending: the payout is on its way to to.address. Link to transactions.payout.explorer_url once the payout transaction is there.
  • completed: the amount sent, to.amount_sent, and a link to the payout transaction.
  • action_required: what status_detail says, as described in Status detail.
  • refunding: a refund to refund.address is under way. status_detail.reason says why, when it is known.
  • refunded: the refund was sent. Link to transactions.refund.explorer_url.
  • expired: no deposit arrived in time. If your user sent nothing, nothing is owed: offer a new quote. If they did send funds, keep following the order while is_final is false, and write to api@kotova.io with the order id if it does not move.

Telling your user about each change is up to you. The order page of an API order has no e-mail updates (see The order page).

status_detail explains an order that needs attention. It is set for every action_required order, and for a refunding order when the reason is known. Otherwise it is null.

Field What it is
reason Why the order needs attention. See the table below.
since When the source first reported the problem, or for payout_on_hold when the hold was detected. null when unknown.
auto_resolution What happens at auto_resolution_at if nobody acts first: refund (the deposit goes back to refund.address) or continue (the source carries on with the swap at its current rate). null when nothing happens on its own: the source resolves it itself, a choice has already been made, or someone has to act.
auto_resolution_at When the automatic resolution happens: about an hour after the problem was first reported, or after the source last refused a refund address. null without an automatic resolution, or when unknown.
resolve_url The order page, where your user can choose between the options the source offers, or give a new refund address. null when there is nothing to choose.

On a refunding order, only reason and since are set; the other three fields are null.

reason is an extensible list: treat a value you do not know as other.

reason What happened What to do
amount_mismatch The deposit differs from the order’s amount, or is outside the source’s limits. When resolve_url is set, send your user there to choose. Show what auto_resolution will do, and when.
late_deposit The deposit arrived after the order had expired. The same.
source_review The source holds the order for a review, and resolves it itself. Nothing to choose. Tell your user the source is reviewing the order, and keep following it.
payout_on_hold The source reports the swap as done, but has not sent the payout. Write to api@kotova.io with the order id. See Payout on hold.
refund_address_rejected The source refused the refund address, and it was removed. Your user gives a new refund address at resolve_url.
other Any other problem the source reported. When resolve_url is set, send your user there. Otherwise write to api@kotova.io with the order id.

When you send your user to resolve_url, tell them that the page opens with the address the order pays out to (to.address), and show what happens if they do nothing:

  • auto_resolution: refund: the deposit is refunded to refund.address at auto_resolution_at.
  • auto_resolution: continue: the swap continues at the source’s current rate at auto_resolution_at.
  • auto_resolution: null: nothing happens on its own, so your user’s choice matters.

Endpoints for these choices, and for giving a new refund address, are not available yet in the API: your user makes the choice on the order page. How each source handles these cases is described in Emergency states and Refunds, cancellations and emergencies.

At some sources, an order can be reported as done while the source still holds the payout. When no payout transaction has been recorded ten minutes after the source reported the swap as done, the order changes from sending to action_required, with this status_detail:

{
"reason": "payout_on_hold",
"since": "2026-11-10T10:38:20Z",
"auto_resolution": null,
"auto_resolution_at": null,
"resolve_url": null
}

Kotova keeps checking with the source for a while, and the order becomes completed on a later read once the payout is recorded. If it stays on hold, support follows it up.

The order page at order_url uses the app’s own labels. They correspond like this:

API status Order page
waiting_for_deposit Initiated
confirming_deposit Received
exchanging Confirmed
sending Sending
completed Complete
action_required Emergency (“Action required”), or On hold (“Payout on hold”) for payout_on_hold
refunding Refunding
refunded Reverted
expired Expired

See Status vocabulary for what your user reads there.