> For the complete documentation index, see [llms.txt](https://developers.unigox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.unigox.com/api-reference/orders.md).

# Orders

Order management, status tracking, and lifecycle actions

## Order details

> Get the current status, amounts, and full timeline for a specific order.\
> The \`next\_action\` field indicates what the partner \*\*must\*\* do to advance the order.\
> \`null\` means no action is required from the partner at this stage — the order is waiting\
> for the counterparty (e.g. the buyer to submit fiat payment proof).\
> \
> The \`allowed\_actions\` array lists all API actions the partner \*\*can\*\* perform at the current\
> status. An action can be in \`allowed\_actions\` even when \`next\_action\` is \`null\` — this means\
> the action is optional. For example, \`confirm-fiat-received\` is available at \`crypto\_received\`\
> as a fast-track: if you already know the fiat has arrived (via your own systems), you can\
> confirm immediately without waiting for the buyer's payment proof flow to complete.\
> \
> \`allowed\_actions\` is \`\[]\` for a \*\*widget order\*\* — one your customer created through the\
> embedded widget under your \`widgetKey\`. Those orders are attributed to you, and readable\
> here, but the crypto is the end user's, so every action endpoint answers \`404\
> ORDER\_NOT\_FOUND\` for them. \`status\`, \`next\_action\` and the timeline still describe the\
> order; they describe your customer's step, not one for you to take.\
> \
> \*\*A \`cancelled\` order can still owe you money.\*\* An off-ramp order that stopped after its\
> escrow was funded reads \`cancelled\` — the same as one that never funded and the same as one\
> whose refund has already been paid out. The status does not distinguish them and never will.\
> What distinguishes them is \`allowed\_actions\`: \`\["authorize-refund"]\` means the crypto is\
> still in the escrow and your signature is the only thing that can send it back, with\
> \`next\_action: "authorize\_refund"\` and \`action\_required\` naming the endpoint. Check it before\
> writing an order off. The \`order.refund.required\` webhook says the same thing once, if you\
> would rather not poll.\
> \
> \*\*Order flow summary:\*\*\
> \
> \| Status | next\_action | Who acts |\
> \|---|---|---|\
> \| \`created\` | — | Partner (or wait for vendor match) |\
> \| \`awaiting\_crypto\_transfer\_authorization\` | \`authorize\_crypto\_transfer\` | \*\*Partner\*\* |\
> \| \`crypto\_transfer\_authorization\_pending\` | — | System (on-chain confirmation) |\
> \| \`crypto\_received\` | — | \*\*Buyer\*\* submits fiat payment proof |\
> \| \`fiat\_payment\_started\` | — | System reviews proof |\
> \| \`fiat\_payment\_review\_started\` | — | System accepts/rejects proof |\
> \| \`awaiting\_fiat\_received\_confirmation\` | \`confirm\_fiat\_received\` | \*\*Partner\*\* |\
> \| \`completed\` | — | — |\
> \
> The "Who acts" column describes an order \*\*you\*\* created. On a widget order the rows\
> reading \*\*Partner\*\* are your customer's step, not yours — \`next\_action\` is populated the\
> same way for both, because it describes where the order stands rather than who may move\
> it. \`allowed\_actions\` is what tells you apart: \`\[]\` on a widget order at every status.\
> Acting on a \`next\_action\` for a widget order returns \`404 ORDER\_NOT\_FOUND\`.\
> \
> \*\*Fiat settlement and confirmation:\*\*\
> \
> You can call \`confirm-fiat-received\` at any time after crypto is in escrow.\
> You do not need to wait for a system notification. If you know through your\
> own systems that the recipient has received the fiat payment, confirm immediately.\
> \
> Some liquidity providers also send automatic settlement confirmations when the\
> recipient receives the fiat. When the order's \`has\_fiat\_settlement\_notification\`\
> is \`true\` (see the quote/order response), the order moves to \`completed\` on its own\
> and you receive the \`status=completed\` webhook — no manual confirm needed. If you\
> already confirmed manually, the auto-confirmation is a no-op; if the auto-confirmation\
> arrives first, your manual confirm call is also a no-op. Both paths are safe. See the\
> Webhooks page → "Settlement notifications" for details.\
> \
> \*\*How to implement:\*\*\
> \- Always implement a \`confirm-fiat-received\` call in your flow.\
> \- Listen for webhooks. If you receive \`status=completed\`, no further action needed.\
> \- If \`next\_action=confirm\_fiat\_received\`, call \`confirm-fiat-received\` when you\
> &#x20; know fiat has been received.\
> \- Do not wait for \`next\_action\` if you already have confirmation from your\
> &#x20; own banking or payment systems.\
> \
> \*\*Possible statuses:\*\* \`created\`, \`awaiting\_liquidity\_provider\`, \`awaiting\_crypto\_transfer\_authorization\`, \`crypto\_transfer\_authorization\_pending\`, \`crypto\_received\`, \`fiat\_payment\_started\`, \`awaiting\_fiat\_received\_confirmation\`, \`fiat\_received\_confirmed\`, \`crypto\_release\_pending\`, \`completed\`, \`cancelled\`, \`failed\`, \`price\_changed\_requote\_needed\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}},"schemas":{"APIResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","description":"Indicates if the request was successful"},"data":{"description":"Response data (structure varies by endpoint) or error information if success is false"}}},"PartnerOrderResponse":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid","description":"Unique order identifier"},"status":{"$ref":"#/components/schemas/PartnerOrderStatus"},"next_action":{"type":"string","nullable":true,"description":"The action the partner **must** perform to advance the order. `null` means\nno action is required from the partner at this stage — the order is waiting\nfor the counterparty or for an automated system step.\n\nPossible values:\n- `authorize_crypto_transfer` — partner must authorize escrow funding\n- `confirm_fiat_received` — partner must confirm they received the fiat payment\n- `request_new_quote` — price changed, partner must request a new quote\n- `update_kyc_address` — address fields are required for EUR/AUD/GBP payouts; see `action_required` for the endpoint and fields to submit\n- `authorize_refund` — the order ended without a payout and its crypto is still in escrow; only your\n  signature can send it back. Note that this appears on an order whose `status` is `cancelled`, which\n  is the one case where a terminal status still needs something from you\n- `deposit_to_user_account` — an on-ramp order with `fiat_funding_source: own_iban` is waiting for the\n  customer to transfer the order's fiat amount into the fiat account issued to them. The transfer\n  itself confirms the payment; there is nothing to call\n- `null` — no required action (waiting for buyer or system)\n","enum":["authorize_crypto_transfer","confirm_fiat_received","request_new_quote","update_kyc_address","authorize_refund","deposit_to_user_account",null]},"action_required":{"type":"object","nullable":true,"description":"Present when the order needs partner intervention before it can proceed.\nContains machine-readable type, human-readable message, the API endpoint to call,\nand the fields to provide. Null/omitted when no action is needed.\n","required":["type","message"],"properties":{"type":{"type":"string","description":"Machine-readable action identifier"},"message":{"type":"string","description":"Human-readable explanation of what is needed and why"},"endpoint":{"type":"string","description":"API endpoint to call to resolve this action"},"fields":{"type":"array","description":"Fields the partner needs to provide","items":{"type":"object","required":["field","label"],"properties":{"field":{"type":"string","description":"API field name"},"label":{"type":"string","description":"Human-readable description of the field"}}}}}},"allowed_actions":{"type":"array","items":{"type":"string"},"description":"List of API actions the partner **can** perform at the current status. An action\nmay be present here even when `next_action` is `null` — meaning it is optional.\n\nNotable case: `confirm-fiat-received` appears at both `crypto_received` and\n`awaiting_fiat_received_confirmation`. At `crypto_received` it is a **fast-track**:\nif you already know the fiat has arrived via your own systems, you can confirm\nimmediately. Otherwise, wait for the buyer's proof flow to complete — the order\nwill reach `awaiting_fiat_received_confirmation` automatically.\n\nStatus-to-actions mapping:\n- `created` → `[\"cancel\"]`\n- `awaiting_liquidity_provider` → `[\"cancel\"]`\n- `awaiting_crypto_transfer_authorization` → `[\"authorize-crypto-transfer\", \"cancel\"]`\n- `crypto_transfer_authorization_pending` → `[\"cancel\"]`\n- `crypto_received` → `[\"confirm-fiat-received\"]` (optional fast-track)\n- `fiat_payment_started` → `[\"confirm-fiat-received\"]` (optional fast-track after buyer proof submission)\n- `awaiting_fiat_received_confirmation` → `[\"confirm-fiat-received\"]` (required)\n- `fiat_received_confirmed`, `crypto_release_pending`, `completed`, `failed` → `[]`\n- `cancelled` → `[]`, **except** when the order's crypto is still sitting in escrow: then\n  `[\"authorize-refund\"]`. An off-ramp order that stops after funding — expired payment window,\n  declined payment proof, returned bank payment, dispute resolved for the seller — reads as\n  `cancelled` like every other stopped order, and the escrow is a 2-of-3 Safe your key is an\n  owner of. This is the only thing that tells the two apart, so poll it on `cancelled` orders\n  rather than assuming a cancelled order is finished with. `next_action` is\n  `authorize_refund` and `action_required` names the endpoint at the same time.\n\nOn-ramp orders with `fiat_funding_source: own_iban` never offer `confirm-payment-sent`: the\ntransfer into the customer's own account is the confirmation.\nCustody outranks the mapping above: on a **widget order** — one your customer created\nthrough the embedded widget under your `widgetKey` — this is `[]` at every status,\nbecause the crypto is the end user's and every action endpoint answers `404\nORDER_NOT_FOUND` for it.\n"},"fiat_funding_source":{"type":"string","enum":["vendor_details","own_iban"],"description":"On-ramp orders only. Where the fiat for this order is paid:\n- `vendor_details` — to the vendor's bank account in `vendor_payment_details`; then call\n  `confirm-payment-sent`.\n- `own_iban` — into the fiat account you issued to the customer. There are no\n  `vendor_payment_details` and no `confirm-payment-sent`: the transfer landing on the customer's\n  account is matched to the order by amount and the order proceeds on its own.\n\nRead it on every order rather than assuming one or the other.\n"},"crypto_transfer_authorization_seconds_left":{"type":"integer","format":"int64","nullable":true,"description":"Remaining seconds to authorize crypto transfer while order is in\n`awaiting_crypto_transfer_authorization` / `crypto_transfer_authorization_pending`.\n`null` for all other statuses.\n"},"amounts":{"$ref":"#/components/schemas/PartnerOrderAmounts"},"fee_breakdown":{"$ref":"#/components/schemas/FeeBreakdown"},"timeline":{"type":"array","items":{"$ref":"#/components/schemas/TimelineEntry"},"description":"Chronological list of status changes"},"has_fiat_settlement_notification":{"type":"boolean","description":"Whether the matched liquidity provider sends fiat settlement notifications.\nWhen `true`, the order will complete automatically when fiat is delivered.\nWhen `false`, you must call `confirm-fiat-received`. You can call\n`confirm-fiat-received` at any time regardless of this value.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"order_type":{"type":"string","nullable":true,"description":"Order type. Present for on-ramp orders. Absent for off-ramp orders.\n- `onramp` — buy crypto with fiat\n"},"vendor_payment_details":{"type":"object","nullable":true,"description":"Vendor's payment details for the end-user to send fiat to.\nPresent only for on-ramp orders at `awaiting_fiat_transfer` status and beyond.\n","properties":{"payment_method_name":{"type":"string"},"payment_network_name":{"type":"string"},"details":{"type":"object","description":"Payment method-specific fields (e.g. account_number, phone)"}}},"payment_request":{"type":"boolean","nullable":true,"description":"`true` if the vendor uses payment request flow — the partner must call\n`submit-payer-details` before `confirm-payment-sent`.\n"},"send_out_tx_hash":{"type":"string","nullable":true,"description":"Destination-chain transaction hash after a send-out completes.\nPresent only for on-ramp orders with `send_out_completed` status.\n"},"recipient_context":{"allOf":[{"$ref":"#/components/schemas/PartnerRecipientContext"}],"nullable":true,"description":"Immutable third-party recipient context; absent for self-payout and on-ramp."},"compliance":{"allOf":[{"$ref":"#/components/schemas/PartnerComplianceCase"}],"nullable":true,"description":"Current durable compliance-case state for a third-party payout."}}},"PartnerOrderStatus":{"type":"string","description":"Order status.\n\n**Off-ramp statuses (crypto → fiat):**\n- `created` — order created, quote locked\n- `awaiting_liquidity_provider` — order initiated, waiting for vendor acceptance\n- `awaiting_crypto_transfer_authorization` — partner must authorize crypto transfer via EIP-712 signature\n- `crypto_transfer_authorization_pending` — authorization submitted, awaiting on-chain confirmation\n- `crypto_received` — crypto locked in escrow\n- `fiat_payment_started` — buyer submitted fiat payment proof\n- `awaiting_fiat_received_confirmation` — waiting for partner to confirm fiat receipt\n- `fiat_received_confirmed` — fiat confirmed, crypto release pending\n- `crypto_release_pending` — escrow release in progress\n- `completed` — order fully completed\n- `cancelled` — order cancelled\n- `failed` — terminal error\n- `price_changed_requote_needed` — slippage exceeded at initiation (not a trade status)\n\n**On-ramp statuses (fiat → crypto):**\n- `awaiting_liquidity_provider` — order initiated, waiting for vendor acceptance\n- `awaiting_vendor_escrow_funding` — vendor accepted, funding escrow with crypto\n- `awaiting_fiat_transfer` — crypto locked in escrow; the partner pays the vendor and confirms payment sent (`fiat_funding_source: vendor_details`), or the customer transfers into their own fiat account (`own_iban`)\n- `fiat_transfer_pending` — fiat payment confirmed, awaiting vendor confirmation of receipt\n- `completed` — vendor confirmed fiat received, crypto released to end-user wallet\n- `cancelled` — order cancelled\n- `failed` — escrow error\n\n**On-ramp send-out statuses (optional post-trade cross-chain transfer):**\n\n> After an on-ramp order reaches `completed`, the partner may optionally initiate a\n> **send-out** — a cross-chain transfer of the received crypto to a destination network\n> (e.g. XAI → Arbitrum). This is an additional flow and does not affect the core trade lifecycle.\n> The `completed` status reflects that the trade itself is done; send-out statuses track\n> the subsequent cross-chain transfer only.\n\n- `send_out_pending` — send-out initiated, cross-chain transfer in progress\n- `send_out_completed` — cross-chain transfer successfully delivered to destination\n- `send_out_failed` — cross-chain transfer failed; the on-ramp trade itself remains completed\n","enum":["created","awaiting_liquidity_provider","awaiting_crypto_transfer_authorization","crypto_transfer_authorization_pending","crypto_received","fiat_payment_started","awaiting_fiat_received_confirmation","fiat_received_confirmed","crypto_release_pending","awaiting_vendor_escrow_funding","awaiting_fiat_transfer","fiat_transfer_pending","completed","cancelled","failed","price_changed_requote_needed","send_out_pending","send_out_completed","send_out_failed"]},"PartnerOrderAmounts":{"type":"object","properties":{"crypto_amount":{"type":"string","description":"Total crypto amount (standard units) — the fee-exclusive gross: the buy/sell amount plus the\nplatform fee. Partner-fee-exclusive, except for a crypto-anchored onramp order (originally\nquoted with `crypto_amount`): there the amount was sized up so the delivered amount stays\nexact after the partner fee is withheld, so this field includes the markup. A crypto-anchored\nofframp order carves both fees out of the pinned deposit instead, so this field and\n`fee_breakdown.platform_fee` both shrink relative to a no-markup request, even though the\nmarkup itself stays out of this field. Every other case is unaffected — the markup is\nreported separately in `fee_breakdown.partner_fee`.\n\nOn-ramp — what the end user receives: `crypto_amount − fee_breakdown.platform_fee −\nfee_breakdown.partner_fee` for a fiat-anchored order, or exactly this `crypto_amount` for a\ncrypto-anchored order (both fees are withheld at bridge send-out without changing this\nfield). Off-ramp — what the partner funds at transfer authorization:\n`crypto_amount + fee_breakdown.partner_fee`.\n"},"fiat_amount":{"type":"string","description":"Fiat amount the user receives"},"crypto_currency":{"type":"string","description":"Cryptocurrency code"},"fiat_currency":{"type":"string","description":"Fiat currency code"},"rate":{"type":"string","description":"Crypto-to-fiat exchange rate"}}},"FeeBreakdown":{"type":"object","description":"Transparent breakdown of all fee components (amounts in crypto)","properties":{"platform_fee":{"type":"string","description":"Platform fee in crypto"},"platform_fee_pct":{"type":"number","format":"double","description":"Platform fee as a percentage"},"partner_fee":{"type":"string","description":"Your markup in crypto, computed from the `partner_fee_pct` you declared on the\nquote/estimate request, on the same base as the platform fee. `0` when no markup was declared.\n"},"partner_fee_pct":{"type":"number","format":"double","description":"Your markup percentage as declared on the request (`1` means 1%); `0` when none."},"total_fee":{"type":"string","description":"Total fee in crypto (platform_fee + partner_fee)"}}},"TimelineEntry":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/PartnerOrderStatus"},"timestamp":{"type":"string","format":"date-time","description":"When this status was reached"},"description":{"type":"string","description":"Human-readable description of the status change"}}},"PartnerRecipientContext":{"type":"object","required":["sender_id","recipient_id","recipient_destination_id","sender_recipient_relationship","purpose_of_payment","screening_status"],"properties":{"sender_id":{"type":"string","format":"uuid"},"recipient_id":{"type":"string","format":"uuid"},"recipient_destination_id":{"type":"string","format":"uuid"},"sender_recipient_relationship":{"type":"string"},"purpose_of_payment":{"type":"string"},"purpose_details":{"type":"string"},"screening_status":{"type":"string"}}},"PartnerComplianceCase":{"type":"object","required":["case_id","status","risk_decision","requires_review"],"description":"The compliance record for a third-party payout. In v1 the controls run BEFORE the order is\ncreated, so a payout that fails one is rejected with an error rather than returned as a held\norder — see the error codes in the Third-party payouts guide.\n","properties":{"case_id":{"type":"string","format":"uuid","description":"Identifier of the compliance record — the payout's `quote_id`, so a partner and a Unigox\noperator refer to the same record.\n"},"status":{"type":"string","enum":["authorized"],"description":"v1 emits `authorized`; a rejected payout returns an error instead."},"risk_decision":{"type":"string","enum":["allow"],"description":"v1 emits `allow`; a blocking decision surfaces as an error, not a status."},"requires_review":{"type":"boolean","description":"Always false in v1. Operator review happens Unigox-side over the same record."}}},"PartnerErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Possible values:\n- `QUOTE_EXPIRED` — quote TTL has passed\n- `QUOTE_NOT_FOUND` — quote ID does not exist\n- `QUOTE_ALREADY_USED` — quote was already consumed by initiate\n- `PRICE_CHANGED_REQUOTE` — price changed beyond slippage tolerance, partner should request a new quote\n- `ORDER_NOT_FOUND` — order ID does not exist or belongs to another partner\n- `NO_OFFERS_AVAILABLE` — no vendor offers for the requested pair\n- `INVALID_REQUEST` — malformed request or missing fields\n- `INVALID_PAYMENT_DETAILS` — payment details not found or invalid\n- `RAIL_ROUTE_MISMATCH` — rail or route does not match payment details\n- `UNAUTHORIZED` — authentication failed\n- `INTERNAL_ERROR` — unexpected server error\n- `INVALID_STATUS` — order is not in the correct status for the requested action\n- `TRANSACTOR_ERROR` — on-chain transaction relay failed (e.g. simulation reverted)\n- `INSUFFICIENT_BALANCE` — partner wallet lacks tokens to fund escrow\n- `OPERATION_NOT_ALLOWED` — action is not permitted for the current order state\n- `KYC_NOT_CLEARED` — the customer is not KYC-cleared for this transaction; `error.details.kyc_status` carries their current partner-facing status\n- `SENDER_IDENTITY_REQUIRED` — the payout corridor settles consumer-to-consumer and the customer's record cannot name them as the remitter; `error.details.kyc_fields` lists what to send to `PATCH /partner/users/{user_uuid}/kyc`, and `error.details.field_limits` carries the rail's length ceiling on any listed field that has one\n\nFiat account endpoints (`/partner/fiat-accounts/config` and the `/partner/users/{user_uuid}`\n`identity`, `identification` and `fiat-accounts` routes) answer with their own codes, each\ndescribed on the response that returns it: `FIAT_ACCOUNT_NOT_FOUND`,\n`ACCOUNT_HOLDER_NOT_FOUND`, `ACCOUNT_NOT_PROVISIONED`, `CUSTOMER_NOT_FOUND`,\n`CUSTOMER_NOT_VERIFIED`, `CLIENT_NOT_APPROVED`, `HOLDER_REGISTRATION_IN_PROGRESS`,\n`IDENTIFICATION_MISSING`, `IDENTIFICATION_ALREADY_LINKED`, `INVALID_DOCUMENT_TYPE`,\n`POSTAL_CODE_REQUIRED`, `INVALID_POSTAL_CODE`, `MISSING_FIELDS`, `PRODUCT_NOT_ACTIVATED`,\n`ISSUANCE_NOT_GRANTED`, `ISSUANCE_DISABLED`, `PROVISIONING_IN_PROGRESS`,\n`UNSUPPORTED_CURRENCY`, `UNSUPPORTED_ISSUER_COUNTRY`, `CURRENCY_NOT_PERMITTED`,\n`CURRENCY_NOT_PRICED`, `RECORD_FAILED`, `BANKING_ERROR`, `BANKING_UNAVAILABLE`.\n\nThis list is not closed: codes are added as endpoints grow. Treat a code you do not recognise\nas an error of the kind its HTTP status says, rather than rejecting the response.\n"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"Additional context (e.g., quoted_rate, current_rate for slippage errors)"}}}}}}},"paths":{"/api/v1/partner/orders/{order_id}":{"get":{"tags":["Orders"],"summary":"Order details","description":"Get the current status, amounts, and full timeline for a specific order.\nThe `next_action` field indicates what the partner **must** do to advance the order.\n`null` means no action is required from the partner at this stage — the order is waiting\nfor the counterparty (e.g. the buyer to submit fiat payment proof).\n\nThe `allowed_actions` array lists all API actions the partner **can** perform at the current\nstatus. An action can be in `allowed_actions` even when `next_action` is `null` — this means\nthe action is optional. For example, `confirm-fiat-received` is available at `crypto_received`\nas a fast-track: if you already know the fiat has arrived (via your own systems), you can\nconfirm immediately without waiting for the buyer's payment proof flow to complete.\n\n`allowed_actions` is `[]` for a **widget order** — one your customer created through the\nembedded widget under your `widgetKey`. Those orders are attributed to you, and readable\nhere, but the crypto is the end user's, so every action endpoint answers `404\nORDER_NOT_FOUND` for them. `status`, `next_action` and the timeline still describe the\norder; they describe your customer's step, not one for you to take.\n\n**A `cancelled` order can still owe you money.** An off-ramp order that stopped after its\nescrow was funded reads `cancelled` — the same as one that never funded and the same as one\nwhose refund has already been paid out. The status does not distinguish them and never will.\nWhat distinguishes them is `allowed_actions`: `[\"authorize-refund\"]` means the crypto is\nstill in the escrow and your signature is the only thing that can send it back, with\n`next_action: \"authorize_refund\"` and `action_required` naming the endpoint. Check it before\nwriting an order off. The `order.refund.required` webhook says the same thing once, if you\nwould rather not poll.\n\n**Order flow summary:**\n\n| Status | next_action | Who acts |\n|---|---|---|\n| `created` | — | Partner (or wait for vendor match) |\n| `awaiting_crypto_transfer_authorization` | `authorize_crypto_transfer` | **Partner** |\n| `crypto_transfer_authorization_pending` | — | System (on-chain confirmation) |\n| `crypto_received` | — | **Buyer** submits fiat payment proof |\n| `fiat_payment_started` | — | System reviews proof |\n| `fiat_payment_review_started` | — | System accepts/rejects proof |\n| `awaiting_fiat_received_confirmation` | `confirm_fiat_received` | **Partner** |\n| `completed` | — | — |\n\nThe \"Who acts\" column describes an order **you** created. On a widget order the rows\nreading **Partner** are your customer's step, not yours — `next_action` is populated the\nsame way for both, because it describes where the order stands rather than who may move\nit. `allowed_actions` is what tells you apart: `[]` on a widget order at every status.\nActing on a `next_action` for a widget order returns `404 ORDER_NOT_FOUND`.\n\n**Fiat settlement and confirmation:**\n\nYou can call `confirm-fiat-received` at any time after crypto is in escrow.\nYou do not need to wait for a system notification. If you know through your\nown systems that the recipient has received the fiat payment, confirm immediately.\n\nSome liquidity providers also send automatic settlement confirmations when the\nrecipient receives the fiat. When the order's `has_fiat_settlement_notification`\nis `true` (see the quote/order response), the order moves to `completed` on its own\nand you receive the `status=completed` webhook — no manual confirm needed. If you\nalready confirmed manually, the auto-confirmation is a no-op; if the auto-confirmation\narrives first, your manual confirm call is also a no-op. Both paths are safe. See the\nWebhooks page → \"Settlement notifications\" for details.\n\n**How to implement:**\n- Always implement a `confirm-fiat-received` call in your flow.\n- Listen for webhooks. If you receive `status=completed`, no further action needed.\n- If `next_action=confirm_fiat_received`, call `confirm-fiat-received` when you\n  know fiat has been received.\n- Do not wait for `next_action` if you already have confirmation from your\n  own banking or payment systems.\n\n**Possible statuses:** `created`, `awaiting_liquidity_provider`, `awaiting_crypto_transfer_authorization`, `crypto_transfer_authorization_pending`, `crypto_received`, `fiat_payment_started`, `awaiting_fiat_received_confirmation`, `fiat_received_confirmed`, `crypto_release_pending`, `completed`, `cancelled`, `failed`, `price_changed_requote_needed`.\n","operationId":"getOrder","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID returned by the initiate endpoint","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Order retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/APIResponse"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PartnerOrderResponse"}}}]}}}},"401":{"description":"Unauthorized — invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}},"404":{"description":"Order not found or does not belong to this partner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}}}}}}}
```

## Get transfer authorization parameters

> Returns pre-filled parameters required to build and sign the EIP-712 forward request.\
> Use this endpoint first, then sign locally and send the signature to\
> \`/api/v1/partner/orders/{order\_id}/authorize-crypto-transfer\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}},"schemas":{"APIResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","description":"Indicates if the request was successful"},"data":{"description":"Response data (structure varies by endpoint) or error information if success is false"}}},"PartnerErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Possible values:\n- `QUOTE_EXPIRED` — quote TTL has passed\n- `QUOTE_NOT_FOUND` — quote ID does not exist\n- `QUOTE_ALREADY_USED` — quote was already consumed by initiate\n- `PRICE_CHANGED_REQUOTE` — price changed beyond slippage tolerance, partner should request a new quote\n- `ORDER_NOT_FOUND` — order ID does not exist or belongs to another partner\n- `NO_OFFERS_AVAILABLE` — no vendor offers for the requested pair\n- `INVALID_REQUEST` — malformed request or missing fields\n- `INVALID_PAYMENT_DETAILS` — payment details not found or invalid\n- `RAIL_ROUTE_MISMATCH` — rail or route does not match payment details\n- `UNAUTHORIZED` — authentication failed\n- `INTERNAL_ERROR` — unexpected server error\n- `INVALID_STATUS` — order is not in the correct status for the requested action\n- `TRANSACTOR_ERROR` — on-chain transaction relay failed (e.g. simulation reverted)\n- `INSUFFICIENT_BALANCE` — partner wallet lacks tokens to fund escrow\n- `OPERATION_NOT_ALLOWED` — action is not permitted for the current order state\n- `KYC_NOT_CLEARED` — the customer is not KYC-cleared for this transaction; `error.details.kyc_status` carries their current partner-facing status\n- `SENDER_IDENTITY_REQUIRED` — the payout corridor settles consumer-to-consumer and the customer's record cannot name them as the remitter; `error.details.kyc_fields` lists what to send to `PATCH /partner/users/{user_uuid}/kyc`, and `error.details.field_limits` carries the rail's length ceiling on any listed field that has one\n\nFiat account endpoints (`/partner/fiat-accounts/config` and the `/partner/users/{user_uuid}`\n`identity`, `identification` and `fiat-accounts` routes) answer with their own codes, each\ndescribed on the response that returns it: `FIAT_ACCOUNT_NOT_FOUND`,\n`ACCOUNT_HOLDER_NOT_FOUND`, `ACCOUNT_NOT_PROVISIONED`, `CUSTOMER_NOT_FOUND`,\n`CUSTOMER_NOT_VERIFIED`, `CLIENT_NOT_APPROVED`, `HOLDER_REGISTRATION_IN_PROGRESS`,\n`IDENTIFICATION_MISSING`, `IDENTIFICATION_ALREADY_LINKED`, `INVALID_DOCUMENT_TYPE`,\n`POSTAL_CODE_REQUIRED`, `INVALID_POSTAL_CODE`, `MISSING_FIELDS`, `PRODUCT_NOT_ACTIVATED`,\n`ISSUANCE_NOT_GRANTED`, `ISSUANCE_DISABLED`, `PROVISIONING_IN_PROGRESS`,\n`UNSUPPORTED_CURRENCY`, `UNSUPPORTED_ISSUER_COUNTRY`, `CURRENCY_NOT_PERMITTED`,\n`CURRENCY_NOT_PRICED`, `RECORD_FAILED`, `BANKING_ERROR`, `BANKING_UNAVAILABLE`.\n\nThis list is not closed: codes are added as endpoints grow. Treat a code you do not recognise\nas an error of the kind its HTTP status says, rather than rejecting the response.\n"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"Additional context (e.g., quoted_rate, current_rate for slippage errors)"}}}}}}},"paths":{"/api/v1/partner/orders/{order_id}/transfer-authorization-parameters":{"get":{"tags":["SDK","Orders"],"summary":"Get transfer authorization parameters","description":"Returns pre-filled parameters required to build and sign the EIP-712 forward request.\nUse this endpoint first, then sign locally and send the signature to\n`/api/v1/partner/orders/{order_id}/authorize-crypto-transfer`.\n","operationId":"getTransferAuthorizationParameters","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Transfer authorization parameters returned","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/APIResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid"},"network_preset":{"type":"string"},"chain_id":{"type":"string"},"rpc_url":{"type":"string","description":"JSON-RPC URL for the target chain"},"token_address":{"type":"string"},"forwarder_address":{"type":"string"},"recipient_address":{"type":"string","description":"Escrow address to receive the crypto"},"sender_address":{"type":"string","description":"Partner wallet address (must match the signing private key)"},"amount_atomic":{"type":"string"},"amount_human":{"type":"string"},"crypto_currency":{"type":"string"},"crypto_decimals":{"type":"integer"},"recommended_gas_limit":{"type":"string"},"recommended_ttl_seconds":{"type":"integer"},"transfer_data":{"type":"string","description":"Pre-encoded ERC20 transfer(address,uint256) calldata (hex with 0x prefix)"},"forwarder_nonce":{"type":"string","description":"Current forwarder nonce for the sender address (used in EIP-712 signing)"},"authorization_path":{"type":"string"}}}}}]}}}},"401":{"description":"Unauthorized"},"404":{"description":"No order with this id belongs to your partner account."},"409":{"description":"The order exists but is not at a stage where it can be funded. A new order starts at `awaiting_liquidity_provider` with no escrow yet, so this is the normal answer until a provider accepts — poll `GET /orders/{order_id}` until `next_action` becomes `authorize_crypto_transfer`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}}}}}}}
```

## Authorize crypto transfer

> Submit signed EIP-712 \`forward\_request\` to authorize transfer of order crypto to escrow.\
> \
> \*\*Security note:\*\* Your private key is never sent to the API. The SDK uses it locally to\
> construct and sign the EIP-712 ForwardRequest on your machine. Only the resulting signature\
> and the unsigned forward\_request fields are submitted. You can verify this by reading the\
> SDK source code.\
> \
> Recommended: use SDK helper files (only 4 arguments needed):\
> \- Python: \`<https://github.com/Unigox/sdk\\_python/blob/main/partner\\_authorize\\_crypto\\_transfer\\_sdk.py\\`\\>
> \- JavaScript: \`<https://github.com/Unigox/sdk\\_javascript/blob/main/partner\\_authorize\\_crypto\\_transfer\\_sdk.js\\`\\>
> \
> The SDK automatically fetches all required parameters (chain, token, forwarder, escrow\
> address, RPC URL) from the \`transfer-authorization-parameters\` endpoint.\
> \
> SDK helper options:\
> \- End-to-end one call: \`authorize\_crypto\_transfer(...)\` / \`authorizeCryptoTransfer(...)\`\
> \- Build unsigned request only: \`build\_forward\_request(...)\` / \`buildForwardRequest(...)\`\
> \- Sign existing request only: \`sign\_forward\_request(...)\` / \`signForwardRequest(...)\`\
> \- Build full request body \`{forward\_request, signature}\`:\
> &#x20; \`build\_authorize\_crypto\_transfer\_payload(...)\` / \`buildAuthorizeCryptoTransferPayload(...)\`\
> \
> Manual implementation: call \`GET /transfer-authorization-parameters\` first, then build\
> the EIP-712 typed data and sign with your partner wallet private key locally.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}},"schemas":{"PartnerErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Possible values:\n- `QUOTE_EXPIRED` — quote TTL has passed\n- `QUOTE_NOT_FOUND` — quote ID does not exist\n- `QUOTE_ALREADY_USED` — quote was already consumed by initiate\n- `PRICE_CHANGED_REQUOTE` — price changed beyond slippage tolerance, partner should request a new quote\n- `ORDER_NOT_FOUND` — order ID does not exist or belongs to another partner\n- `NO_OFFERS_AVAILABLE` — no vendor offers for the requested pair\n- `INVALID_REQUEST` — malformed request or missing fields\n- `INVALID_PAYMENT_DETAILS` — payment details not found or invalid\n- `RAIL_ROUTE_MISMATCH` — rail or route does not match payment details\n- `UNAUTHORIZED` — authentication failed\n- `INTERNAL_ERROR` — unexpected server error\n- `INVALID_STATUS` — order is not in the correct status for the requested action\n- `TRANSACTOR_ERROR` — on-chain transaction relay failed (e.g. simulation reverted)\n- `INSUFFICIENT_BALANCE` — partner wallet lacks tokens to fund escrow\n- `OPERATION_NOT_ALLOWED` — action is not permitted for the current order state\n- `KYC_NOT_CLEARED` — the customer is not KYC-cleared for this transaction; `error.details.kyc_status` carries their current partner-facing status\n- `SENDER_IDENTITY_REQUIRED` — the payout corridor settles consumer-to-consumer and the customer's record cannot name them as the remitter; `error.details.kyc_fields` lists what to send to `PATCH /partner/users/{user_uuid}/kyc`, and `error.details.field_limits` carries the rail's length ceiling on any listed field that has one\n\nFiat account endpoints (`/partner/fiat-accounts/config` and the `/partner/users/{user_uuid}`\n`identity`, `identification` and `fiat-accounts` routes) answer with their own codes, each\ndescribed on the response that returns it: `FIAT_ACCOUNT_NOT_FOUND`,\n`ACCOUNT_HOLDER_NOT_FOUND`, `ACCOUNT_NOT_PROVISIONED`, `CUSTOMER_NOT_FOUND`,\n`CUSTOMER_NOT_VERIFIED`, `CLIENT_NOT_APPROVED`, `HOLDER_REGISTRATION_IN_PROGRESS`,\n`IDENTIFICATION_MISSING`, `IDENTIFICATION_ALREADY_LINKED`, `INVALID_DOCUMENT_TYPE`,\n`POSTAL_CODE_REQUIRED`, `INVALID_POSTAL_CODE`, `MISSING_FIELDS`, `PRODUCT_NOT_ACTIVATED`,\n`ISSUANCE_NOT_GRANTED`, `ISSUANCE_DISABLED`, `PROVISIONING_IN_PROGRESS`,\n`UNSUPPORTED_CURRENCY`, `UNSUPPORTED_ISSUER_COUNTRY`, `CURRENCY_NOT_PERMITTED`,\n`CURRENCY_NOT_PRICED`, `RECORD_FAILED`, `BANKING_ERROR`, `BANKING_UNAVAILABLE`.\n\nThis list is not closed: codes are added as endpoints grow. Treat a code you do not recognise\nas an error of the kind its HTTP status says, rather than rejecting the response.\n"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"Additional context (e.g., quoted_rate, current_rate for slippage errors)"}}}}}}},"paths":{"/api/v1/partner/orders/{order_id}/authorize-crypto-transfer":{"post":{"tags":["SDK","Orders"],"summary":"Authorize crypto transfer","description":"Submit signed EIP-712 `forward_request` to authorize transfer of order crypto to escrow.\n\n**Security note:** Your private key is never sent to the API. The SDK uses it locally to\nconstruct and sign the EIP-712 ForwardRequest on your machine. Only the resulting signature\nand the unsigned forward_request fields are submitted. You can verify this by reading the\nSDK source code.\n\nRecommended: use SDK helper files (only 4 arguments needed):\n- Python: `https://github.com/Unigox/sdk_python/blob/main/partner_authorize_crypto_transfer_sdk.py`\n- JavaScript: `https://github.com/Unigox/sdk_javascript/blob/main/partner_authorize_crypto_transfer_sdk.js`\n\nThe SDK automatically fetches all required parameters (chain, token, forwarder, escrow\naddress, RPC URL) from the `transfer-authorization-parameters` endpoint.\n\nSDK helper options:\n- End-to-end one call: `authorize_crypto_transfer(...)` / `authorizeCryptoTransfer(...)`\n- Build unsigned request only: `build_forward_request(...)` / `buildForwardRequest(...)`\n- Sign existing request only: `sign_forward_request(...)` / `signForwardRequest(...)`\n- Build full request body `{forward_request, signature}`:\n  `build_authorize_crypto_transfer_payload(...)` / `buildAuthorizeCryptoTransferPayload(...)`\n\nManual implementation: call `GET /transfer-authorization-parameters` first, then build\nthe EIP-712 typed data and sign with your partner wallet private key locally.\n","operationId":"authorizeCryptoTransfer","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["forward_request","signature"],"properties":{"forward_request":{"type":"object","description":"Signed EIP-712 ForwardRequest payload"},"signature":{"type":"string","description":"Hex-encoded signature from partner wallet"}}}}}},"responses":{"200":{"description":"Crypto authorization accepted"},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"},"404":{"description":"Order not found"},"409":{"description":"Order is not in the correct status for crypto authorization"},"422":{"description":"Insufficient token balance — the partner wallet does not hold enough\ntokens to fund the escrow. Top up the wallet and retry.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}},"502":{"description":"Transactor service error (e.g. on-chain simulation failed)"}}}}}}
```

## Get refund authorization parameters

> Returns the EIP-712 Safe transaction to sign in order to send a funded escrow back to the\
> seller. This is the way out of an off-ramp order that stopped before settlement — the payment\
> window expired, a payment proof was declined, the bank returned the payment, or a dispute was\
> resolved for the seller. In every one of those the crypto is still sitting in escrow and owes\
> its way back.\
> \
> Use this endpoint first, sign the returned typed data locally with the key that owns\
> \`signer\_address\`, then send the signature to\
> \`/api/v1/partner/orders/{order\_id}/authorize-refund\`.\
> \
> \*\*Who signs.\*\* The escrow is a 2-of-3 Safe whose owners are the buyer side, the seller side\
> and Unigox. On an order you opened for your own end customer, the seller-side owner is \*your\*\
> wallet — the customer never holds a key. \`signer\_address\` names it explicitly; sign with that\
> key and no other, or the Safe rejects the transaction.\
> \
> \*\*Where the money goes is not yours to choose.\*\* The recipient is read from the escrow's\
> seller address on the server. \`recipient\_address\` is returned so you can verify it before\
> signing; there is no parameter that changes it.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}},"schemas":{"APIResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","description":"Indicates if the request was successful"},"data":{"description":"Response data (structure varies by endpoint) or error information if success is false"}}},"PartnerErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Possible values:\n- `QUOTE_EXPIRED` — quote TTL has passed\n- `QUOTE_NOT_FOUND` — quote ID does not exist\n- `QUOTE_ALREADY_USED` — quote was already consumed by initiate\n- `PRICE_CHANGED_REQUOTE` — price changed beyond slippage tolerance, partner should request a new quote\n- `ORDER_NOT_FOUND` — order ID does not exist or belongs to another partner\n- `NO_OFFERS_AVAILABLE` — no vendor offers for the requested pair\n- `INVALID_REQUEST` — malformed request or missing fields\n- `INVALID_PAYMENT_DETAILS` — payment details not found or invalid\n- `RAIL_ROUTE_MISMATCH` — rail or route does not match payment details\n- `UNAUTHORIZED` — authentication failed\n- `INTERNAL_ERROR` — unexpected server error\n- `INVALID_STATUS` — order is not in the correct status for the requested action\n- `TRANSACTOR_ERROR` — on-chain transaction relay failed (e.g. simulation reverted)\n- `INSUFFICIENT_BALANCE` — partner wallet lacks tokens to fund escrow\n- `OPERATION_NOT_ALLOWED` — action is not permitted for the current order state\n- `KYC_NOT_CLEARED` — the customer is not KYC-cleared for this transaction; `error.details.kyc_status` carries their current partner-facing status\n- `SENDER_IDENTITY_REQUIRED` — the payout corridor settles consumer-to-consumer and the customer's record cannot name them as the remitter; `error.details.kyc_fields` lists what to send to `PATCH /partner/users/{user_uuid}/kyc`, and `error.details.field_limits` carries the rail's length ceiling on any listed field that has one\n\nFiat account endpoints (`/partner/fiat-accounts/config` and the `/partner/users/{user_uuid}`\n`identity`, `identification` and `fiat-accounts` routes) answer with their own codes, each\ndescribed on the response that returns it: `FIAT_ACCOUNT_NOT_FOUND`,\n`ACCOUNT_HOLDER_NOT_FOUND`, `ACCOUNT_NOT_PROVISIONED`, `CUSTOMER_NOT_FOUND`,\n`CUSTOMER_NOT_VERIFIED`, `CLIENT_NOT_APPROVED`, `HOLDER_REGISTRATION_IN_PROGRESS`,\n`IDENTIFICATION_MISSING`, `IDENTIFICATION_ALREADY_LINKED`, `INVALID_DOCUMENT_TYPE`,\n`POSTAL_CODE_REQUIRED`, `INVALID_POSTAL_CODE`, `MISSING_FIELDS`, `PRODUCT_NOT_ACTIVATED`,\n`ISSUANCE_NOT_GRANTED`, `ISSUANCE_DISABLED`, `PROVISIONING_IN_PROGRESS`,\n`UNSUPPORTED_CURRENCY`, `UNSUPPORTED_ISSUER_COUNTRY`, `CURRENCY_NOT_PERMITTED`,\n`CURRENCY_NOT_PRICED`, `RECORD_FAILED`, `BANKING_ERROR`, `BANKING_UNAVAILABLE`.\n\nThis list is not closed: codes are added as endpoints grow. Treat a code you do not recognise\nas an error of the kind its HTTP status says, rather than rejecting the response.\n"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"Additional context (e.g., quoted_rate, current_rate for slippage errors)"}}}}}}},"paths":{"/api/v1/partner/orders/{order_id}/refund-authorization-parameters":{"get":{"tags":["SDK","Orders"],"summary":"Get refund authorization parameters","description":"Returns the EIP-712 Safe transaction to sign in order to send a funded escrow back to the\nseller. This is the way out of an off-ramp order that stopped before settlement — the payment\nwindow expired, a payment proof was declined, the bank returned the payment, or a dispute was\nresolved for the seller. In every one of those the crypto is still sitting in escrow and owes\nits way back.\n\nUse this endpoint first, sign the returned typed data locally with the key that owns\n`signer_address`, then send the signature to\n`/api/v1/partner/orders/{order_id}/authorize-refund`.\n\n**Who signs.** The escrow is a 2-of-3 Safe whose owners are the buyer side, the seller side\nand Unigox. On an order you opened for your own end customer, the seller-side owner is *your*\nwallet — the customer never holds a key. `signer_address` names it explicitly; sign with that\nkey and no other, or the Safe rejects the transaction.\n\n**Where the money goes is not yours to choose.** The recipient is read from the escrow's\nseller address on the server. `recipient_address` is returned so you can verify it before\nsigning; there is no parameter that changes it.\n","operationId":"getRefundAuthorizationParameters","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Refund authorization parameters returned","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/APIResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"The order's current status"},"escrow_address":{"type":"string","description":"The Safe holding the crypto"},"signer_address":{"type":"string","description":"The escrow's seller-side owner — the address whose key must produce the signature. On an order opened for your end customer this is your wallet."},"recipient_address":{"type":"string","description":"Where the refund lands. Server-derived and identical to `signer_address` on a partner order; returned for verification, not as an input."},"amount_human":{"type":"string","description":"Amount to be refunded, in whole units"},"crypto_currency":{"type":"string"},"crypto_decimals":{"type":"integer"},"direction":{"type":"string","description":"Always `to_seller`. Refunds have no other direction."},"safe_params":{"type":"object","description":"The Safe transaction fields to sign","properties":{"to":{"type":"string","description":"Token contract address"},"value":{"type":"string"},"data":{"type":"string","description":"Encoded ERC20 transfer calldata"},"operation":{"type":"integer"},"safeTxGas":{"type":"string"},"baseGas":{"type":"string"},"gasPrice":{"type":"string"},"gasToken":{"type":"string"},"refundReceiver":{"type":"string"},"nonce":{"type":"string","description":"Safe nonce"}}},"domain":{"type":"object","description":"EIP-712 domain","properties":{"chainId":{"type":"integer"},"verifyingContract":{"type":"string"}}},"types":{"type":"object","description":"EIP-712 type definitions (`SafeTx`)"},"authorization_path":{"type":"string","description":"The endpoint to POST the signature to"}}}}}]}}}},"401":{"description":"Unauthorized"},"404":{"description":"No order with this id belongs to your partner account."},"409":{"description":"The order does not owe a refund. Either it has already been refunded or released, its status is one where the crypto is not owed back (`INVALID_STATUS`), or it is held for review and no automatic refund may run against it (`OPERATION_NOT_ALLOWED`) — the message says which. A held order is settled by our operations team, not by retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}}}}}}}
```

## Authorize refund

> Submit the signature produced from \`GET /refund-authorization-parameters\` to send the escrow\
> back to the seller. Unigox adds the second of the two signatures the Safe requires and\
> executes the transaction.\
> \
> \*\*Security note:\*\* your private key is never sent to the API. Sign the typed data locally and\
> submit only the resulting signature.\
> \
> The recipient is fixed server-side to the escrow's seller address. A signature is an\
> authorization to move the money back, never an instruction about where it goes.\
> \
> Safe to retry: the on-chain Safe executes a given transaction at most once, so a duplicate\
> call after a successful refund is refused on status rather than paying twice.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}},"schemas":{"APIResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","description":"Indicates if the request was successful"},"data":{"description":"Response data (structure varies by endpoint) or error information if success is false"}}},"PartnerErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Possible values:\n- `QUOTE_EXPIRED` — quote TTL has passed\n- `QUOTE_NOT_FOUND` — quote ID does not exist\n- `QUOTE_ALREADY_USED` — quote was already consumed by initiate\n- `PRICE_CHANGED_REQUOTE` — price changed beyond slippage tolerance, partner should request a new quote\n- `ORDER_NOT_FOUND` — order ID does not exist or belongs to another partner\n- `NO_OFFERS_AVAILABLE` — no vendor offers for the requested pair\n- `INVALID_REQUEST` — malformed request or missing fields\n- `INVALID_PAYMENT_DETAILS` — payment details not found or invalid\n- `RAIL_ROUTE_MISMATCH` — rail or route does not match payment details\n- `UNAUTHORIZED` — authentication failed\n- `INTERNAL_ERROR` — unexpected server error\n- `INVALID_STATUS` — order is not in the correct status for the requested action\n- `TRANSACTOR_ERROR` — on-chain transaction relay failed (e.g. simulation reverted)\n- `INSUFFICIENT_BALANCE` — partner wallet lacks tokens to fund escrow\n- `OPERATION_NOT_ALLOWED` — action is not permitted for the current order state\n- `KYC_NOT_CLEARED` — the customer is not KYC-cleared for this transaction; `error.details.kyc_status` carries their current partner-facing status\n- `SENDER_IDENTITY_REQUIRED` — the payout corridor settles consumer-to-consumer and the customer's record cannot name them as the remitter; `error.details.kyc_fields` lists what to send to `PATCH /partner/users/{user_uuid}/kyc`, and `error.details.field_limits` carries the rail's length ceiling on any listed field that has one\n\nFiat account endpoints (`/partner/fiat-accounts/config` and the `/partner/users/{user_uuid}`\n`identity`, `identification` and `fiat-accounts` routes) answer with their own codes, each\ndescribed on the response that returns it: `FIAT_ACCOUNT_NOT_FOUND`,\n`ACCOUNT_HOLDER_NOT_FOUND`, `ACCOUNT_NOT_PROVISIONED`, `CUSTOMER_NOT_FOUND`,\n`CUSTOMER_NOT_VERIFIED`, `CLIENT_NOT_APPROVED`, `HOLDER_REGISTRATION_IN_PROGRESS`,\n`IDENTIFICATION_MISSING`, `IDENTIFICATION_ALREADY_LINKED`, `INVALID_DOCUMENT_TYPE`,\n`POSTAL_CODE_REQUIRED`, `INVALID_POSTAL_CODE`, `MISSING_FIELDS`, `PRODUCT_NOT_ACTIVATED`,\n`ISSUANCE_NOT_GRANTED`, `ISSUANCE_DISABLED`, `PROVISIONING_IN_PROGRESS`,\n`UNSUPPORTED_CURRENCY`, `UNSUPPORTED_ISSUER_COUNTRY`, `CURRENCY_NOT_PERMITTED`,\n`CURRENCY_NOT_PRICED`, `RECORD_FAILED`, `BANKING_ERROR`, `BANKING_UNAVAILABLE`.\n\nThis list is not closed: codes are added as endpoints grow. Treat a code you do not recognise\nas an error of the kind its HTTP status says, rather than rejecting the response.\n"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"Additional context (e.g., quoted_rate, current_rate for slippage errors)"}}}}}}},"paths":{"/api/v1/partner/orders/{order_id}/authorize-refund":{"post":{"tags":["SDK","Orders"],"summary":"Authorize refund","description":"Submit the signature produced from `GET /refund-authorization-parameters` to send the escrow\nback to the seller. Unigox adds the second of the two signatures the Safe requires and\nexecutes the transaction.\n\n**Security note:** your private key is never sent to the API. Sign the typed data locally and\nsubmit only the resulting signature.\n\nThe recipient is fixed server-side to the escrow's seller address. A signature is an\nauthorization to move the money back, never an instruction about where it goes.\n\nSafe to retry: the on-chain Safe executes a given transaction at most once, so a duplicate\ncall after a successful refund is refused on status rather than paying twice.\n","operationId":"authorizeRefund","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["signature"],"properties":{"signature":{"type":"string","description":"Hex-encoded signature over the returned `safe_params`"},"signed_data":{"type":"string","description":"The exact payload that was signed. Optional — the server rebuilds it from the order and uses its own copy for verification."}}}}}},"responses":{"200":{"description":"Refund accepted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/APIResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid"},"status":{"type":"string","description":"The status the order landed in after the refund"},"tx_hash":{"type":"string","description":"On-chain transaction hash. Absent when the refund still needs another signature or is executing — poll `GET /orders/{order_id}`."}}}}}]}}}},"400":{"description":"Missing or malformed signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"No order with this id belongs to your partner account."},"409":{"description":"The order does not owe a refund — already refunded, already released, or in a status where the crypto is not owed back (`INVALID_STATUS`); or it is held for review and no automatic refund may run against it (`OPERATION_NOT_ALLOWED`), in which case retrying will not clear it and our operations team settles the order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}},"502":{"description":"The refund could not be executed on-chain — most often a signature from a key that does not own the escrow. Verify you signed with `signer_address` and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}}}}}}}
```

## Confirm fiat received

> Confirm that the recipient has received the fiat payment for an off-ramp order.\
> This triggers the crypto release from escrow.\
> \
> Call this endpoint as soon as you know fiat has been received. You do not need\
> to wait for a system prompt. If you have confirmation from your own banking or\
> payment systems, confirm immediately.\
> \
> This endpoint is idempotent. If the order already completed (via automatic\
> settlement confirmation from the liquidity provider), calling this returns\
> the current order status with no side effects.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}}},"paths":{"/api/v1/partner/orders/{order_id}/confirm-fiat-received":{"post":{"tags":["Orders"],"summary":"Confirm fiat received","description":"Confirm that the recipient has received the fiat payment for an off-ramp order.\nThis triggers the crypto release from escrow.\n\nCall this endpoint as soon as you know fiat has been received. You do not need\nto wait for a system prompt. If you have confirmation from your own banking or\npayment systems, confirm immediately.\n\nThis endpoint is idempotent. If the order already completed (via automatic\nsettlement confirmation from the liquidity provider), calling this returns\nthe current order status with no side effects.\n","operationId":"confirmFiatReceived","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Fiat receipt confirmed successfully"},"400":{"description":"Bad Request"},"401":{"description":"Unauthorized"},"404":{"description":"Order not found"}}}}}}
```

## Cancel order

> Cancel an order if cancellation is allowed at the current status.\
> Check \`allowed\_actions\` on the order response — \`cancel\` is available when cancellation is permitted.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}}},"paths":{"/api/v1/partner/orders/{order_id}/cancel":{"post":{"tags":["Orders"],"summary":"Cancel order","description":"Cancel an order if cancellation is allowed at the current status.\nCheck `allowed_actions` on the order response — `cancel` is available when cancellation is permitted.\n","operationId":"cancelOrder","parameters":[{"name":"order_id","in":"path","required":true,"description":"Order UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Order cancelled successfully"},"400":{"description":"Bad Request — cancellation not allowed at current status"},"401":{"description":"Unauthorized"},"404":{"description":"Order not found"}}}}}}
```

## List orders

> Get a paginated list of orders with optional filtering by status.\
> Each order includes \`allowed\_actions\` indicating which API actions are available.\
> \
> The list also contains \*\*widget orders\*\* — orders your customers created through the\
> embedded Unigox widget under your \`widgetKey\`. Those are attributed to you for reporting\
> and markup, but the crypto belongs to the end user, so they are \*\*notify-only\*\*: they\
> appear here and in your webhook stream, and every action endpoint answers \`404\
> ORDER\_NOT\_FOUND\` for them.\
> \
> The guarantee runs one way only. A widget order is always \`\[]\`, and any action listed is\
> one the endpoint will accept — but \`\[]\` does NOT mean an order is a widget order. Your own\
> orders are also \`\[]\` whenever their status carries no action for you, including the\
> mid-flight \`crypto\_transfer\_authorization\_pending\`, \`fiat\_received\_confirmed\` and\
> \`crypto\_release\_pending\`. Reading an empty array as "this is a customer's order" would\
> misclassify your own live orders and stop you tracking them.\
> \
> Keep acting only on order ids your own \`initiate\` call returned. That rule still holds as\
> defence in depth, and it is the one that does not depend on reading a field correctly.\
> \
> To read a specific widget order, the embedded widget's \`onTradeStarted\` and\
> \`onTradeCompleted\` callbacks carry \`orderId\` — the same \`order\_id\` used here and in your\
> webhooks. Its sibling \`tradeId\` is a Unigox-internal numeric id and is \*\*not\*\* accepted by\
> this API: \`GET /partner/orders/{order\_id}\` validates the path segment as a UUID and answers\
> \`400 invalid order\_id format\` for it.<br>

```json
{"openapi":"3.0.3","info":{"title":"Unigox API Gateway","version":"1.0.0"},"tags":[{"name":"Orders","description":"Order management, status tracking, and lifecycle actions"}],"servers":[{"url":"https://api-staging.unigox.com","description":"Sandbox server"},{"url":"https://api.unigox.com","description":"Production server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key for authentication. Required for all partner account endpoints."}},"schemas":{"APIResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean","description":"Indicates if the request was successful"},"data":{"description":"Response data (structure varies by endpoint) or error information if success is false"}}},"PartnerOrderResponse":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid","description":"Unique order identifier"},"status":{"$ref":"#/components/schemas/PartnerOrderStatus"},"next_action":{"type":"string","nullable":true,"description":"The action the partner **must** perform to advance the order. `null` means\nno action is required from the partner at this stage — the order is waiting\nfor the counterparty or for an automated system step.\n\nPossible values:\n- `authorize_crypto_transfer` — partner must authorize escrow funding\n- `confirm_fiat_received` — partner must confirm they received the fiat payment\n- `request_new_quote` — price changed, partner must request a new quote\n- `update_kyc_address` — address fields are required for EUR/AUD/GBP payouts; see `action_required` for the endpoint and fields to submit\n- `authorize_refund` — the order ended without a payout and its crypto is still in escrow; only your\n  signature can send it back. Note that this appears on an order whose `status` is `cancelled`, which\n  is the one case where a terminal status still needs something from you\n- `deposit_to_user_account` — an on-ramp order with `fiat_funding_source: own_iban` is waiting for the\n  customer to transfer the order's fiat amount into the fiat account issued to them. The transfer\n  itself confirms the payment; there is nothing to call\n- `null` — no required action (waiting for buyer or system)\n","enum":["authorize_crypto_transfer","confirm_fiat_received","request_new_quote","update_kyc_address","authorize_refund","deposit_to_user_account",null]},"action_required":{"type":"object","nullable":true,"description":"Present when the order needs partner intervention before it can proceed.\nContains machine-readable type, human-readable message, the API endpoint to call,\nand the fields to provide. Null/omitted when no action is needed.\n","required":["type","message"],"properties":{"type":{"type":"string","description":"Machine-readable action identifier"},"message":{"type":"string","description":"Human-readable explanation of what is needed and why"},"endpoint":{"type":"string","description":"API endpoint to call to resolve this action"},"fields":{"type":"array","description":"Fields the partner needs to provide","items":{"type":"object","required":["field","label"],"properties":{"field":{"type":"string","description":"API field name"},"label":{"type":"string","description":"Human-readable description of the field"}}}}}},"allowed_actions":{"type":"array","items":{"type":"string"},"description":"List of API actions the partner **can** perform at the current status. An action\nmay be present here even when `next_action` is `null` — meaning it is optional.\n\nNotable case: `confirm-fiat-received` appears at both `crypto_received` and\n`awaiting_fiat_received_confirmation`. At `crypto_received` it is a **fast-track**:\nif you already know the fiat has arrived via your own systems, you can confirm\nimmediately. Otherwise, wait for the buyer's proof flow to complete — the order\nwill reach `awaiting_fiat_received_confirmation` automatically.\n\nStatus-to-actions mapping:\n- `created` → `[\"cancel\"]`\n- `awaiting_liquidity_provider` → `[\"cancel\"]`\n- `awaiting_crypto_transfer_authorization` → `[\"authorize-crypto-transfer\", \"cancel\"]`\n- `crypto_transfer_authorization_pending` → `[\"cancel\"]`\n- `crypto_received` → `[\"confirm-fiat-received\"]` (optional fast-track)\n- `fiat_payment_started` → `[\"confirm-fiat-received\"]` (optional fast-track after buyer proof submission)\n- `awaiting_fiat_received_confirmation` → `[\"confirm-fiat-received\"]` (required)\n- `fiat_received_confirmed`, `crypto_release_pending`, `completed`, `failed` → `[]`\n- `cancelled` → `[]`, **except** when the order's crypto is still sitting in escrow: then\n  `[\"authorize-refund\"]`. An off-ramp order that stops after funding — expired payment window,\n  declined payment proof, returned bank payment, dispute resolved for the seller — reads as\n  `cancelled` like every other stopped order, and the escrow is a 2-of-3 Safe your key is an\n  owner of. This is the only thing that tells the two apart, so poll it on `cancelled` orders\n  rather than assuming a cancelled order is finished with. `next_action` is\n  `authorize_refund` and `action_required` names the endpoint at the same time.\n\nOn-ramp orders with `fiat_funding_source: own_iban` never offer `confirm-payment-sent`: the\ntransfer into the customer's own account is the confirmation.\nCustody outranks the mapping above: on a **widget order** — one your customer created\nthrough the embedded widget under your `widgetKey` — this is `[]` at every status,\nbecause the crypto is the end user's and every action endpoint answers `404\nORDER_NOT_FOUND` for it.\n"},"fiat_funding_source":{"type":"string","enum":["vendor_details","own_iban"],"description":"On-ramp orders only. Where the fiat for this order is paid:\n- `vendor_details` — to the vendor's bank account in `vendor_payment_details`; then call\n  `confirm-payment-sent`.\n- `own_iban` — into the fiat account you issued to the customer. There are no\n  `vendor_payment_details` and no `confirm-payment-sent`: the transfer landing on the customer's\n  account is matched to the order by amount and the order proceeds on its own.\n\nRead it on every order rather than assuming one or the other.\n"},"crypto_transfer_authorization_seconds_left":{"type":"integer","format":"int64","nullable":true,"description":"Remaining seconds to authorize crypto transfer while order is in\n`awaiting_crypto_transfer_authorization` / `crypto_transfer_authorization_pending`.\n`null` for all other statuses.\n"},"amounts":{"$ref":"#/components/schemas/PartnerOrderAmounts"},"fee_breakdown":{"$ref":"#/components/schemas/FeeBreakdown"},"timeline":{"type":"array","items":{"$ref":"#/components/schemas/TimelineEntry"},"description":"Chronological list of status changes"},"has_fiat_settlement_notification":{"type":"boolean","description":"Whether the matched liquidity provider sends fiat settlement notifications.\nWhen `true`, the order will complete automatically when fiat is delivered.\nWhen `false`, you must call `confirm-fiat-received`. You can call\n`confirm-fiat-received` at any time regardless of this value.\n"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"order_type":{"type":"string","nullable":true,"description":"Order type. Present for on-ramp orders. Absent for off-ramp orders.\n- `onramp` — buy crypto with fiat\n"},"vendor_payment_details":{"type":"object","nullable":true,"description":"Vendor's payment details for the end-user to send fiat to.\nPresent only for on-ramp orders at `awaiting_fiat_transfer` status and beyond.\n","properties":{"payment_method_name":{"type":"string"},"payment_network_name":{"type":"string"},"details":{"type":"object","description":"Payment method-specific fields (e.g. account_number, phone)"}}},"payment_request":{"type":"boolean","nullable":true,"description":"`true` if the vendor uses payment request flow — the partner must call\n`submit-payer-details` before `confirm-payment-sent`.\n"},"send_out_tx_hash":{"type":"string","nullable":true,"description":"Destination-chain transaction hash after a send-out completes.\nPresent only for on-ramp orders with `send_out_completed` status.\n"},"recipient_context":{"allOf":[{"$ref":"#/components/schemas/PartnerRecipientContext"}],"nullable":true,"description":"Immutable third-party recipient context; absent for self-payout and on-ramp."},"compliance":{"allOf":[{"$ref":"#/components/schemas/PartnerComplianceCase"}],"nullable":true,"description":"Current durable compliance-case state for a third-party payout."}}},"PartnerOrderStatus":{"type":"string","description":"Order status.\n\n**Off-ramp statuses (crypto → fiat):**\n- `created` — order created, quote locked\n- `awaiting_liquidity_provider` — order initiated, waiting for vendor acceptance\n- `awaiting_crypto_transfer_authorization` — partner must authorize crypto transfer via EIP-712 signature\n- `crypto_transfer_authorization_pending` — authorization submitted, awaiting on-chain confirmation\n- `crypto_received` — crypto locked in escrow\n- `fiat_payment_started` — buyer submitted fiat payment proof\n- `awaiting_fiat_received_confirmation` — waiting for partner to confirm fiat receipt\n- `fiat_received_confirmed` — fiat confirmed, crypto release pending\n- `crypto_release_pending` — escrow release in progress\n- `completed` — order fully completed\n- `cancelled` — order cancelled\n- `failed` — terminal error\n- `price_changed_requote_needed` — slippage exceeded at initiation (not a trade status)\n\n**On-ramp statuses (fiat → crypto):**\n- `awaiting_liquidity_provider` — order initiated, waiting for vendor acceptance\n- `awaiting_vendor_escrow_funding` — vendor accepted, funding escrow with crypto\n- `awaiting_fiat_transfer` — crypto locked in escrow; the partner pays the vendor and confirms payment sent (`fiat_funding_source: vendor_details`), or the customer transfers into their own fiat account (`own_iban`)\n- `fiat_transfer_pending` — fiat payment confirmed, awaiting vendor confirmation of receipt\n- `completed` — vendor confirmed fiat received, crypto released to end-user wallet\n- `cancelled` — order cancelled\n- `failed` — escrow error\n\n**On-ramp send-out statuses (optional post-trade cross-chain transfer):**\n\n> After an on-ramp order reaches `completed`, the partner may optionally initiate a\n> **send-out** — a cross-chain transfer of the received crypto to a destination network\n> (e.g. XAI → Arbitrum). This is an additional flow and does not affect the core trade lifecycle.\n> The `completed` status reflects that the trade itself is done; send-out statuses track\n> the subsequent cross-chain transfer only.\n\n- `send_out_pending` — send-out initiated, cross-chain transfer in progress\n- `send_out_completed` — cross-chain transfer successfully delivered to destination\n- `send_out_failed` — cross-chain transfer failed; the on-ramp trade itself remains completed\n","enum":["created","awaiting_liquidity_provider","awaiting_crypto_transfer_authorization","crypto_transfer_authorization_pending","crypto_received","fiat_payment_started","awaiting_fiat_received_confirmation","fiat_received_confirmed","crypto_release_pending","awaiting_vendor_escrow_funding","awaiting_fiat_transfer","fiat_transfer_pending","completed","cancelled","failed","price_changed_requote_needed","send_out_pending","send_out_completed","send_out_failed"]},"PartnerOrderAmounts":{"type":"object","properties":{"crypto_amount":{"type":"string","description":"Total crypto amount (standard units) — the fee-exclusive gross: the buy/sell amount plus the\nplatform fee. Partner-fee-exclusive, except for a crypto-anchored onramp order (originally\nquoted with `crypto_amount`): there the amount was sized up so the delivered amount stays\nexact after the partner fee is withheld, so this field includes the markup. A crypto-anchored\nofframp order carves both fees out of the pinned deposit instead, so this field and\n`fee_breakdown.platform_fee` both shrink relative to a no-markup request, even though the\nmarkup itself stays out of this field. Every other case is unaffected — the markup is\nreported separately in `fee_breakdown.partner_fee`.\n\nOn-ramp — what the end user receives: `crypto_amount − fee_breakdown.platform_fee −\nfee_breakdown.partner_fee` for a fiat-anchored order, or exactly this `crypto_amount` for a\ncrypto-anchored order (both fees are withheld at bridge send-out without changing this\nfield). Off-ramp — what the partner funds at transfer authorization:\n`crypto_amount + fee_breakdown.partner_fee`.\n"},"fiat_amount":{"type":"string","description":"Fiat amount the user receives"},"crypto_currency":{"type":"string","description":"Cryptocurrency code"},"fiat_currency":{"type":"string","description":"Fiat currency code"},"rate":{"type":"string","description":"Crypto-to-fiat exchange rate"}}},"FeeBreakdown":{"type":"object","description":"Transparent breakdown of all fee components (amounts in crypto)","properties":{"platform_fee":{"type":"string","description":"Platform fee in crypto"},"platform_fee_pct":{"type":"number","format":"double","description":"Platform fee as a percentage"},"partner_fee":{"type":"string","description":"Your markup in crypto, computed from the `partner_fee_pct` you declared on the\nquote/estimate request, on the same base as the platform fee. `0` when no markup was declared.\n"},"partner_fee_pct":{"type":"number","format":"double","description":"Your markup percentage as declared on the request (`1` means 1%); `0` when none."},"total_fee":{"type":"string","description":"Total fee in crypto (platform_fee + partner_fee)"}}},"TimelineEntry":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/PartnerOrderStatus"},"timestamp":{"type":"string","format":"date-time","description":"When this status was reached"},"description":{"type":"string","description":"Human-readable description of the status change"}}},"PartnerRecipientContext":{"type":"object","required":["sender_id","recipient_id","recipient_destination_id","sender_recipient_relationship","purpose_of_payment","screening_status"],"properties":{"sender_id":{"type":"string","format":"uuid"},"recipient_id":{"type":"string","format":"uuid"},"recipient_destination_id":{"type":"string","format":"uuid"},"sender_recipient_relationship":{"type":"string"},"purpose_of_payment":{"type":"string"},"purpose_details":{"type":"string"},"screening_status":{"type":"string"}}},"PartnerComplianceCase":{"type":"object","required":["case_id","status","risk_decision","requires_review"],"description":"The compliance record for a third-party payout. In v1 the controls run BEFORE the order is\ncreated, so a payout that fails one is rejected with an error rather than returned as a held\norder — see the error codes in the Third-party payouts guide.\n","properties":{"case_id":{"type":"string","format":"uuid","description":"Identifier of the compliance record — the payout's `quote_id`, so a partner and a Unigox\noperator refer to the same record.\n"},"status":{"type":"string","enum":["authorized"],"description":"v1 emits `authorized`; a rejected payout returns an error instead."},"risk_decision":{"type":"string","enum":["allow"],"description":"v1 emits `allow`; a blocking decision surfaces as an error, not a status."},"requires_review":{"type":"boolean","description":"Always false in v1. Operator review happens Unigox-side over the same record."}}},"PartnerErrorResponse":{"type":"object","required":["success","error"],"properties":{"success":{"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Possible values:\n- `QUOTE_EXPIRED` — quote TTL has passed\n- `QUOTE_NOT_FOUND` — quote ID does not exist\n- `QUOTE_ALREADY_USED` — quote was already consumed by initiate\n- `PRICE_CHANGED_REQUOTE` — price changed beyond slippage tolerance, partner should request a new quote\n- `ORDER_NOT_FOUND` — order ID does not exist or belongs to another partner\n- `NO_OFFERS_AVAILABLE` — no vendor offers for the requested pair\n- `INVALID_REQUEST` — malformed request or missing fields\n- `INVALID_PAYMENT_DETAILS` — payment details not found or invalid\n- `RAIL_ROUTE_MISMATCH` — rail or route does not match payment details\n- `UNAUTHORIZED` — authentication failed\n- `INTERNAL_ERROR` — unexpected server error\n- `INVALID_STATUS` — order is not in the correct status for the requested action\n- `TRANSACTOR_ERROR` — on-chain transaction relay failed (e.g. simulation reverted)\n- `INSUFFICIENT_BALANCE` — partner wallet lacks tokens to fund escrow\n- `OPERATION_NOT_ALLOWED` — action is not permitted for the current order state\n- `KYC_NOT_CLEARED` — the customer is not KYC-cleared for this transaction; `error.details.kyc_status` carries their current partner-facing status\n- `SENDER_IDENTITY_REQUIRED` — the payout corridor settles consumer-to-consumer and the customer's record cannot name them as the remitter; `error.details.kyc_fields` lists what to send to `PATCH /partner/users/{user_uuid}/kyc`, and `error.details.field_limits` carries the rail's length ceiling on any listed field that has one\n\nFiat account endpoints (`/partner/fiat-accounts/config` and the `/partner/users/{user_uuid}`\n`identity`, `identification` and `fiat-accounts` routes) answer with their own codes, each\ndescribed on the response that returns it: `FIAT_ACCOUNT_NOT_FOUND`,\n`ACCOUNT_HOLDER_NOT_FOUND`, `ACCOUNT_NOT_PROVISIONED`, `CUSTOMER_NOT_FOUND`,\n`CUSTOMER_NOT_VERIFIED`, `CLIENT_NOT_APPROVED`, `HOLDER_REGISTRATION_IN_PROGRESS`,\n`IDENTIFICATION_MISSING`, `IDENTIFICATION_ALREADY_LINKED`, `INVALID_DOCUMENT_TYPE`,\n`POSTAL_CODE_REQUIRED`, `INVALID_POSTAL_CODE`, `MISSING_FIELDS`, `PRODUCT_NOT_ACTIVATED`,\n`ISSUANCE_NOT_GRANTED`, `ISSUANCE_DISABLED`, `PROVISIONING_IN_PROGRESS`,\n`UNSUPPORTED_CURRENCY`, `UNSUPPORTED_ISSUER_COUNTRY`, `CURRENCY_NOT_PERMITTED`,\n`CURRENCY_NOT_PRICED`, `RECORD_FAILED`, `BANKING_ERROR`, `BANKING_UNAVAILABLE`.\n\nThis list is not closed: codes are added as endpoints grow. Treat a code you do not recognise\nas an error of the kind its HTTP status says, rather than rejecting the response.\n"},"message":{"type":"string","description":"Human-readable error message"},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"Additional context (e.g., quoted_rate, current_rate for slippage errors)"}}}}}}},"paths":{"/api/v1/partner/orders":{"get":{"tags":["Orders"],"summary":"List orders","description":"Get a paginated list of orders with optional filtering by status.\nEach order includes `allowed_actions` indicating which API actions are available.\n\nThe list also contains **widget orders** — orders your customers created through the\nembedded Unigox widget under your `widgetKey`. Those are attributed to you for reporting\nand markup, but the crypto belongs to the end user, so they are **notify-only**: they\nappear here and in your webhook stream, and every action endpoint answers `404\nORDER_NOT_FOUND` for them.\n\nThe guarantee runs one way only. A widget order is always `[]`, and any action listed is\none the endpoint will accept — but `[]` does NOT mean an order is a widget order. Your own\norders are also `[]` whenever their status carries no action for you, including the\nmid-flight `crypto_transfer_authorization_pending`, `fiat_received_confirmed` and\n`crypto_release_pending`. Reading an empty array as \"this is a customer's order\" would\nmisclassify your own live orders and stop you tracking them.\n\nKeep acting only on order ids your own `initiate` call returned. That rule still holds as\ndefence in depth, and it is the one that does not depend on reading a field correctly.\n\nTo read a specific widget order, the embedded widget's `onTradeStarted` and\n`onTradeCompleted` callbacks carry `orderId` — the same `order_id` used here and in your\nwebhooks. Its sibling `tradeId` is a Unigox-internal numeric id and is **not** accepted by\nthis API: `GET /partner/orders/{order_id}` validates the path segment as a UUID and answers\n`400 invalid order_id format` for it.\n","operationId":"listOrders","parameters":[{"name":"status","in":"query","required":false,"description":"Filter by partner order status","schema":{"type":"string","enum":["created","awaiting_liquidity_provider","awaiting_crypto_transfer_authorization","crypto_transfer_authorization_pending","crypto_received","awaiting_fiat_received_confirmation","fiat_received_confirmed","crypto_release_pending","completed","cancelled","failed","price_changed_requote_needed"]}},{"name":"page","in":"query","required":false,"description":"Page number (default 1)","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","required":false,"description":"Results per page (default 20, max 100)","schema":{"type":"integer","default":20,"maximum":100}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/APIResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/PartnerOrderResponse"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total_count":{"type":"integer"},"total_pages":{"type":"integer"}}}}}}}]}}}},"401":{"description":"Unauthorized — invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerErrorResponse"}}}}}}}}}
```
