Order statuses
Questi contenuti non sono ancora disponibili nella tua lingua.
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 table
Section titled “Status table”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.
Final statuses
Section titled “Final statuses”completedandrefundedare final as soon as they are reached.expiredbecomes 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 toconfirming_deposit, or toaction_requiredwith the reasonlate_deposit. Whether a late deposit is honoured is the source’s decision.- At most sources, an order still waiting when its
expires_atpasses shows asexpiredstraight away. Where the source can extend its deadline, the order stayswaiting_for_deposituntil the source says otherwise.
Decide on is_final, never on the status name: an expired order whose is_final is
false can still change.
How an order moves
Section titled “How an order moves”A typical order goes through these statuses in this order:
waiting_for_depositconfirming_depositexchangingsendingcompleted
Other paths:
- No deposit:
waiting_for_deposit→expired. A late deposit inside the window:expired→confirming_depositand on along the typical path, orexpired→action_required(late_deposit). - A problem with the deposit or the swap: usually
confirming_depositorexchanging→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 usuallyrefunding→refunded. - A payout on hold:
sending→action_required(payout_on_hold) →completedonce 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.
What to show your user
Section titled “What to show your user”waiting_for_deposit:deposit.address,deposit.amountandfrom.network, anddeposit.memounder the name indeposit.memo_labelwhen it is set. Your user must send the memo with the deposit, so show it prominently. Show the time left untilexpires_at, and ask your user to send exactlydeposit.amountonfrom.network.confirming_deposit: the deposit has arrived and is being confirmed. Showtransactions.deposit.confirmationsout ofrequired_confirmationswhen both are known, and link totransactions.deposit.explorer_url.exchanging: the source is performing the swap.estimated_duration_secondsgives a rough idea of the time left.sending: the payout is on its way toto.address. Link totransactions.payout.explorer_urlonce the payout transaction is there.completed: the amount sent,to.amount_sent, and a link to the payout transaction.action_required: whatstatus_detailsays, as described in Status detail.refunding: a refund torefund.addressis under way.status_detail.reasonsays why, when it is known.refunded: the refund was sent. Link totransactions.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 whileis_finalisfalse, 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
Section titled “Status detail”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 torefund.addressatauto_resolution_at.auto_resolution: continue: the swap continues at the source’s current rate atauto_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.
Payout on hold
Section titled “Payout on hold”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.
How these map to the app
Section titled “How these map to the app”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.