# USDT0 Transfers (https://dev.cosmospay.lat/docs/api/usdt0/)

> USDT0 out of Stellar through LayerZero: quote, build the Soroban transaction the holder signs, submit it and follow the message to its destination. Native USDT on Ethereum, USDT0 elsewhere; mainnet only.

Base URL: `https://api.cosmospay.lat/cosmos-api`

## The networks USDT0 can be sent to from Stellar, with what arrives there (mainnet only)

`GET /v1/usdt0/routes`

USDT0 is Tether’s omnichain USDT. From Stellar it travels through LayerZero’s OFT: Ethereum receives native USDT (Tether’s OFT adapter unlocks it), every other network receives USDT0. All routes take an EVM recipient. USDT0 exists on Stellar mainnet only: a dev (testnet) key gets `available: false` and no routes.

Requires the `swaps:read` scope. The shared public key may call it.

**Responses**

- `200` (`Usdt0RoutesEntity`): OK
  - `network` (string, required): Always `public`: USDT0 exists on Stellar mainnet only.
  - `available` (boolean, required): Whether this API key can send USDT0: true for a prod (mainnet) key. A dev (testnet) key gets `false` and no routes.
  - `token` (Usdt0TokenEntity, required): USDT0 on Stellar: its classic asset and Stellar Asset Contract.
  - `oft` (string, required): The LayerZero OFT contract the transaction calls (`send`).
  - `eid` (number, required): Stellar mainnet's LayerZero endpoint id.
  - `routes` (Usdt0RouteEntity[], required): The destination networks, Ethereum first and then by name. Empty for a dev (testnet) key.
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Quote a USDT0 transfer from Stellar; persists nothing

`POST /v1/usdt0/quote`

Simulates the OFT’s `quote_oft` and `quote_send` on Stellar mainnet. The OFT carries 6 decimals and the asset has 7, so the 7th is `dust` that stays in the account. `nativeFee` is LayerZero’s fee, paid in XLM on top of the USDT0; `nativeFeeLimit` is what a transfer built now would offer (20% more, the excess refunded in the same transaction). Mainnet only.

Requires the `swaps:read` scope. The shared public key may call it.

**Request body** (`application/json`, required): `QuoteUsdt0Dto`

- `to` (string, required): The destination network (`GET /v1/usdt0/routes`). `eth` receives native USDT; every other network receives USDT0. One of: `eth`, `arb`, `bera`, `conflux`, `flare`, `hedera`, `hyperevm`, `ink`, `mantle`, `megaeth`, `monad`, `morph`, `op`, `plasma`, `pol`, `rootstock`, `sei`, `stable`, `tempo`, `unichain`, `xlayer`.
- `amount` (string, required): USDT0 to send, decimal with up to 7 places. The OFT carries 6: a 7th decimal is dust that stays in the account (see `dust`).
- `source` (string, optional): The account that would send it: the quote is simulated as that account. Omitted, a fixed mainnet account is used; the price is the same.

**Responses**

- `200` (`Usdt0QuoteEntity`): OK
  - `to` (string, required): The destination network id, as requested. One of: `eth`, `arb`, `bera`, `conflux`, `flare`, `hedera`, `hyperevm`, `ink`, `mantle`, `megaeth`, `monad`, `morph`, `op`, `plasma`, `pol`, `rootstock`, `sei`, `stable`, `tempo`, `unichain`, `xlayer`.
  - `eid` (number, required): The destination network's LayerZero endpoint id.
  - `receives` (string, required): What arrives: native `USDT` on Ethereum, `USDT0` everywhere else. One of: `USDT`, `USDT0`.
  - `amount` (string, required): The amount asked for.
  - `feeBps` (number, required): Cosmos Pay's plan commission rate, in basis points. 0 when the deployment has no fee wrapper (USDT0_FEE_WRAPPER): a Soroban transaction has one operation, and only the wrapper can carry a fee.
  - `feeAmount` (string, required): The commission in USDT0, out of `amount`: `amount × feeBps / 10,000`, rounded down.
  - `amountSent` (string, required): What the OFT takes from the account: `amount` without its dust.
  - `amountReceived` (string, required): What arrives on the destination network (in its token’s 6 decimals). Equal to `amountSent` unless the OFT charges a fee of its own.
  - `dust` (string, required): The 7th decimal the OFT cannot carry (it shares 6 across chains). It stays in the account; nothing is lost.
  - `nativeFee` (string, required): LayerZero’s messaging fee, in XLM, paid by the account on top of the USDT0. It follows LayerZero’s price feeds and changes over time.
  - `nativeFeeLimit` (string, required): What a transfer built now would offer LayerZero, in XLM: `nativeFee` plus a 20% buffer for the minutes before it is signed. What LayerZero does not charge returns to the account in the same transaction, but the account must hold all of it.
  - `minAmount` (string, required): The smallest amount the OFT accepts, in USDT0.
  - `maxAmount` (string, required): The largest amount the OFT accepts, in USDT0.
- `400` (`ApiErrorBodyEntity`): `network_unsupported`: a dev (testnet) key; USDT0 is on Stellar mainnet only. `invalid_amount`: less than 0.000001 USDT0 (all dust), or outside the OFT’s limits. `provider_error`: the OFT refused the quote; `message` carries its contract error.
  - `statusCode` (number, required): Always the HTTP status of the response itself.
  - `code` (string, required): Stable machine-readable code. Branch on this, never on the message: messages are human-facing and may be reworded; codes are never renamed once published. Each response documents the subset it can return. One of: `insufficient_scope`, `no_authenticated_consumer`, `gateway_required`, `admin_console_only`, `not_found`, `validation_failed`, `payload_too_large`, `idempotency_conflict`, `operation_in_flight`, `invalid_state_transition`, `slippage_exceeded`, `insufficient_balance`, `no_path_found`, `trustline_missing`, `invalid_amount`, `invalid_memo`, `transaction_rejected`, `transaction_already_settled`, `recipient_not_registered`, `payment_transfer_mismatch`, `fee_transfer_mismatch`, `merchant_fee_transfer_mismatch`, `payer_mismatch`, `transaction_not_found`, `expired`, `network_unsupported`, `asset_unsupported`, `merchant_fee_unsupported`, `provider_error`, `provider_unavailable`, `quote_not_found`, `quote_expired`, `kyc_state_invalid`, `kyc_review_required`, `account_disabled`, `payload_expired`, `rate_limited`, `customer_wallet_taken`, `alias_taken`, `alias_name_invalid`, `alias_challenge_invalid`, `alias_signature_invalid`, `alias_recovery_invalid`, `alias_address_conflict`, `wallet_handshake_invalid`, `wallet_verifier_invalid`, `wallet_login_code_invalid`, `wallet_login_code_cooldown`, `wallet_session_invalid`, `wallet_signature_invalid`, `wallet_backup_invalid`, `wallet_backup_limit`, `wallet_account_mismatch`, `wallet_provider_unavailable`, `wallet_return_url_not_allowed`, `wallet_recovery_setup_refused`, `easy_recovery_not_found`, `easy_recovery_already_offered`, `easy_recovery_not_offered`, `easy_recovery_code_invalid`, `easy_recovery_burned`, `plugin_not_installed`, `plugin_consent_mismatch`, `plugin_rejected`, `plugin_quota_exceeded`, `plugin_failed`, `protected_payment_buyer_mismatch`, `protected_payment_signature_invalid`, `misconfigured`, `internal_error`.
  - `error` (string, required): The HTTP reason phrase for `statusCode`.
  - `message` (string | string[], required): Human-readable detail. An array when class-validator rejected the body.
  - `details` (object, optional): Machine-readable facts about this failure, present only on the codes whose example shows it: `easy_recovery_code_invalid` carries `{ "attemptsLeft": 4 }`. Absent everywhere else.
  - `path` (string, required): The path of the request that failed.
  - `timestamp` (string, required): When the envelope was produced, ISO 8601.
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `429`: RateLimited (see Shared responses)
- `500`: InternalError (see Shared responses)
- `502` (`ApiErrorBodyEntity`): `provider_error`: the Soroban RPC answered the simulation with no result, or in a shape the OFT never returns.
- `503` (`ApiErrorBodyEntity`): `provider_unavailable`: the Soroban RPC did not answer; retry. `misconfigured`: STELLAR_RPC_URL_MAINNET serves another network, or USDT0_FEE_WRAPPER is set with a plan commission and no STELLAR_SWAP_FEE_WALLET.

## List the consumer's USDT0 transfers (not on the shared public key)

`GET /v1/usdt0/transfers`

Answers from this service’s own table, as last refreshed; read one transfer to refresh it. Refused to the shared public key, which is every anonymous caller at once.

Requires the `swaps:read` scope.

**Query parameters**

- `status` (string, optional): Only transfers in this status, as last refreshed. One of: `PENDING`, `SUBMITTED`, `DELIVERED`, `FAILED`, `EXPIRED`.
- `take` (number, optional): How many transfers to return per page (1 to 100).
- `skip` (number, optional): How many matching transfers to skip before the page starts (newest first).

**Responses**

- `200` (`Usdt0TransferListEntity`): OK
  - `data` (Usdt0TransferListItemEntity[], required): The transfers on this page, newest first.
  - `total` (number, required): How many transfers match the filter, across all pages.
  - `take` (number, required): The page size applied.
  - `skip` (number, required): How many matching transfers were skipped before this page.
- `400`: ValidationFailed (see Shared responses)
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `500`: InternalError (see Shared responses)

## Create a USDT0 transfer from Stellar → the unsigned Soroban transaction to sign (XDR + SEP-7 link)

`POST /v1/usdt0/transfers`

Builds `send` on USDT0’s LayerZero OFT: it burns the USDT0 on Stellar and LayerZero delivers it to `recipient`, as native USDT on Ethereum and as USDT0 elsewhere. The source signs one transaction (Freighter, or the SEP-7 `uri`) and pays two fees in XLM: LayerZero’s (`nativeFeeLimit` is offered, the unused part refunded in the same transaction) and the network’s (`networkFee`). A 7th decimal of `amount` is `dust` and stays in the account. No Cosmos Pay commission is charged. Mainnet only. Submit the signed XDR to `POST /v1/usdt0/transfers/{id}/submit`, then follow `GET /v1/usdt0/transfers/{id}`.

Requires the `swaps:write` scope. The shared public key may call it.

**Headers**

- `Idempotency-Key` (string, optional): Optional idempotency key. A retry with the same key and the same request returns the stored transfer unchanged; the same key with a different request is 409 idempotency_conflict. Takes precedence over body.idempotencyKey.

**Request body** (`application/json`, required): `CreateUsdt0TransferDto`

- `source` (string, required): The Stellar account that holds the USDT0, signs the transaction and pays its fees in XLM (LayerZero fee plus network fee).
- `to` (string, required): The destination network (`GET /v1/usdt0/routes`). `eth` receives native USDT; every other network receives USDT0. One of: `eth`, `arb`, `bera`, `conflux`, `flare`, `hedera`, `hyperevm`, `ink`, `mantle`, `megaeth`, `monad`, `morph`, `op`, `plasma`, `pol`, `rootstock`, `sei`, `stable`, `tempo`, `unichain`, `xlayer`.
- `recipient` (string, required): The EVM address credited on the destination network (0x + 40 hex). A mixed-case address must carry a valid EIP-55 checksum.
- `amount` (string, required): USDT0 to send, decimal with up to 7 places. The OFT carries 6: a 7th decimal is dust that stays in the account (see `dust`).
- `idempotencyKey` (string, optional): Optional idempotency key. Prefer the `Idempotency-Key` request header; when both are set, the header wins. A retry with the same key and the same request returns the stored transfer; the same key with a different request is 409 `idempotency_conflict`.
- `merchantFee` (MerchantFeeDto, optional): Your own fee on this transfer, in USDT0, paid to `wallet` (a Stellar account that trusts USDT0) in the same transaction: the operation is then the fee wrapper (`USDT0_FEE_WRAPPER`), which pays the fee and calls the OFT's `send` under the holder's one authorization. `paidBy: recipient` takes it from `amount` (less is sent); `payer` adds it on top. Without a configured wrapper, `merchant_fee_unsupported`.

**Responses**

- `201` (`Usdt0TransferCreatedEntity`): The transfer. With the shared public key it carries `publicToken`: send it as `X-Record-Token` to read the transfer or submit it.
  - `id` (string, required): The transfer's id, used by the read and submit routes.
  - `status` (string, required): PENDING: built, waiting for the signature. SUBMITTED: on the Stellar ledger, LayerZero is delivering it. DELIVERED: credited on the destination network. FAILED: the Stellar transaction failed, or LayerZero gave up on the message (`failureReason`). EXPIRED: never reached the ledger before `expiresAt`. A read refreshes a PENDING or SUBMITTED transfer from the ledger and LayerZero Scan. One of: `PENDING`, `SUBMITTED`, `DELIVERED`, `FAILED`, `EXPIRED`.
  - `network` (string, required): Always mainnet.
  - `source` (string, required): The Stellar account that holds the USDT0, signs the transaction and pays its fees in XLM.
  - `to` (string, required): The destination network id (`GET /v1/usdt0/routes`). One of: `eth`, `arb`, `bera`, `conflux`, `flare`, `hedera`, `hyperevm`, `ink`, `mantle`, `megaeth`, `monad`, `morph`, `op`, `plasma`, `pol`, `rootstock`, `sei`, `stable`, `tempo`, `unichain`, `xlayer`.
  - `eid` (number, required): The destination network's LayerZero endpoint id.
  - `receives` (string, required): What arrives: native `USDT` on Ethereum, `USDT0` everywhere else. One of: `USDT`, `USDT0`.
  - `recipient` (string, required): The EVM address credited, EIP-55.
  - `amount` (string, required): The amount asked for.
  - `amountSent` (string, required): What the OFT takes from the account: `amount` without its dust.
  - `amountReceived` (string, required): What arrives, and the on-chain floor: the transaction fails rather than deliver less.
  - `dust` (string, required): The dust left in the account (`amount` - `amountSent`).
  - `nativeFee` (string, required): LayerZero’s quoted messaging fee, in XLM.
  - `nativeFeeLimit` (string, required): What the transaction offers LayerZero, in XLM: `nativeFee` plus a 20% buffer. The endpoint charges the real fee and returns the rest to the account in the same transaction.
  - `networkFee` (string, required): The Stellar network fee, in XLM: inclusion plus Soroban resources (part of it is refunded by the network).
  - `feeBps` (number, required): Cosmos Pay's plan commission rate, in basis points. 0 when the deployment has no fee wrapper (USDT0_FEE_WRAPPER): a Soroban transaction has one operation, and only the wrapper can carry a fee.
  - `feeAmount` (string, required): The commission in USDT0, out of `amount`: `amount × feeBps / 10,000`, rounded down.
  - `feeWallet` (string, required): Where the commission went (STELLAR_SWAP_FEE_WALLET); null without one.
  - `xdr` (string, required): The unsigned transaction (base64 XDR) to sign.
  - `uri` (string, required): A SEP-7 `tx` link carrying `xdr`.
  - `qr` (string, required): A QR of `uri` as a PNG data URL, or null when the transaction is too large for one, which a Soroban transaction usually is (its ledger footprint makes the XDR several kilobytes). Sign with a connected wallet (Freighter) or the link instead.
  - `txHash` (string, required): The Stellar transaction hash once it reached the network (SUBMITTED, DELIVERED, FAILED); null while PENDING or EXPIRED.
  - `guid` (string, required): LayerZero’s message id (0x + 64 hex), once the transaction landed.
  - `destinationTxHash` (string, required): The destination network’s transaction, once DELIVERED.
  - `scanStatus` (string, required): LayerZero Scan’s own status word, verbatim (`INFLIGHT`, `CONFIRMING`, `DELIVERED`, `PAYLOAD_STORED`, ...).
  - `scanUrl` (string, required): The transaction on LayerZero Scan (layerzeroscan.com), once it reached the network.
  - `failureReason` (string, required): Why a FAILED transfer failed.
  - `merchantFee` (MerchantFeeEntity, required): The merchant fee the request named, in USDT0, paid to its wallet in this transaction by the fee wrapper; null without one.
  - `idempotencyKey` (string, required): The Idempotency-Key it was created with, if any.
  - `expiresAt` (string (date-time), required): When the transaction's time bounds close: submit refuses it afterwards.
  - `submittedAt` (string (date-time), required): When it was first seen accepted by the network.
  - `createdAt` (string (date-time), required): When the transfer was built (ISO 8601 date-time).
  - `updatedAt` (string (date-time), required): When the transfer was last updated (ISO 8601 date-time).
  - `publicToken` (string, optional): Only when the caller is the shared public key: this record’s read token. Send it as `X-Record-Token` on the routes of this one record. Reading it by id (and submitting a USDT0 transfer) answers 404 without it; swap submit and cross-chain deposit still accept a request without it for now, and will require it once the deployment turns `PUBLIC_RECORD_TOKEN_REQUIRED_ON_LEGACY` on. The same create replayed with its Idempotency-Key answers the same token. Keep it like the record id: whoever holds both can read the record.
- `400` (`ApiErrorBodyEntity`): `merchant_fee_unsupported`: a `merchantFee` and no merchant fee wrapper configured (USDT0_FEE_WRAPPER). `network_unsupported`: a dev (testnet) key; USDT0 is on Stellar mainnet only. `validation_failed`: the source account does not exist, or the recipient has a bad EIP-55 checksum. `trustline_missing`: the source does not trust USDT0. `insufficient_balance`: it holds less USDT0 than the transfer takes, or too little XLM for LayerZero’s fee limit, the network fee and its reserve (the message says how much XLM to add). `invalid_amount`: all dust, or outside the OFT’s limits. `provider_error`: the OFT refused the transfer; `message` carries its contract error. With a merchant fee, `trustline_missing` also answers a fee wallet that does not trust USDT0, and `insufficient_balance` counts the fee the holder pays on top.
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `409` (`ApiErrorBodyEntity`): This Idempotency-Key was already used for a different USDT0 transfer request, or an identical transfer was built from the same account in the same second.
- `429`: RateLimited (see Shared responses)
- `500`: InternalError (see Shared responses)
- `502` (`ApiErrorBodyEntity`): `provider_error`: the OFT cannot be called right now (part of its state is archived on the ledger, or it asks for a signature the transaction cannot carry), or the RPC answered in an unexpected shape.
- `503` (`ApiErrorBodyEntity`): `provider_unavailable`: Horizon or the Soroban RPC did not answer; retry. `misconfigured`: STELLAR_RPC_URL_MAINNET serves another network, or USDT0_FEE_WRAPPER is not the reviewed wrapper bound to USDT0's OFT and token, or the plan commission has no STELLAR_SWAP_FEE_WALLET, or one that does not trust USDT0.

## Get a USDT0 transfer by id, refreshed from the Stellar ledger and LayerZero Scan

`GET /v1/usdt0/transfers/{id}`

While PENDING or SUBMITTED, a read asks the Stellar ledger (a wallet may have broadcast the transaction itself) and LayerZero Scan, at most once every 15 seconds per transfer, and moves it to SUBMITTED, DELIVERED (with `destinationTxHash`), FAILED or EXPIRED. Delivery takes about 27 minutes on every route: LayerZero’s verifiers wait for Stellar confirmations. The shared public key may call it, but only with the transfer’s `publicToken` in `X-Record-Token`: without it, or with another transfer’s, the answer is 404. Every other key reads its own transfers as before.

Requires the `swaps:read` scope. The shared public key may call it.

**Path parameters**

- `id` (string, required)

**Headers**

- `X-Record-Token` (string, optional): Required with the shared public key: the `publicToken` the create response returned for this record. Without it, or with the token of another record, the answer is 404, as for a record that does not exist. Ignored for every other API key.

**Responses**

- `200` (`Usdt0TransferEntity`): OK
  - `id` (string, required): The transfer's id, used by the read and submit routes.
  - `status` (string, required): PENDING: built, waiting for the signature. SUBMITTED: on the Stellar ledger, LayerZero is delivering it. DELIVERED: credited on the destination network. FAILED: the Stellar transaction failed, or LayerZero gave up on the message (`failureReason`). EXPIRED: never reached the ledger before `expiresAt`. A read refreshes a PENDING or SUBMITTED transfer from the ledger and LayerZero Scan. One of: `PENDING`, `SUBMITTED`, `DELIVERED`, `FAILED`, `EXPIRED`.
  - `network` (string, required): Always mainnet.
  - `source` (string, required): The Stellar account that holds the USDT0, signs the transaction and pays its fees in XLM.
  - `to` (string, required): The destination network id (`GET /v1/usdt0/routes`). One of: `eth`, `arb`, `bera`, `conflux`, `flare`, `hedera`, `hyperevm`, `ink`, `mantle`, `megaeth`, `monad`, `morph`, `op`, `plasma`, `pol`, `rootstock`, `sei`, `stable`, `tempo`, `unichain`, `xlayer`.
  - `eid` (number, required): The destination network's LayerZero endpoint id.
  - `receives` (string, required): What arrives: native `USDT` on Ethereum, `USDT0` everywhere else. One of: `USDT`, `USDT0`.
  - `recipient` (string, required): The EVM address credited, EIP-55.
  - `amount` (string, required): The amount asked for.
  - `amountSent` (string, required): What the OFT takes from the account: `amount` without its dust.
  - `amountReceived` (string, required): What arrives, and the on-chain floor: the transaction fails rather than deliver less.
  - `dust` (string, required): The dust left in the account (`amount` - `amountSent`).
  - `nativeFee` (string, required): LayerZero’s quoted messaging fee, in XLM.
  - `nativeFeeLimit` (string, required): What the transaction offers LayerZero, in XLM: `nativeFee` plus a 20% buffer. The endpoint charges the real fee and returns the rest to the account in the same transaction.
  - `networkFee` (string, required): The Stellar network fee, in XLM: inclusion plus Soroban resources (part of it is refunded by the network).
  - `feeBps` (number, required): Cosmos Pay's plan commission rate, in basis points. 0 when the deployment has no fee wrapper (USDT0_FEE_WRAPPER): a Soroban transaction has one operation, and only the wrapper can carry a fee.
  - `feeAmount` (string, required): The commission in USDT0, out of `amount`: `amount × feeBps / 10,000`, rounded down.
  - `feeWallet` (string, required): Where the commission went (STELLAR_SWAP_FEE_WALLET); null without one.
  - `xdr` (string, required): The unsigned transaction (base64 XDR) to sign.
  - `uri` (string, required): A SEP-7 `tx` link carrying `xdr`.
  - `qr` (string, required): A QR of `uri` as a PNG data URL, or null when the transaction is too large for one, which a Soroban transaction usually is (its ledger footprint makes the XDR several kilobytes). Sign with a connected wallet (Freighter) or the link instead.
  - `txHash` (string, required): The Stellar transaction hash once it reached the network (SUBMITTED, DELIVERED, FAILED); null while PENDING or EXPIRED.
  - `guid` (string, required): LayerZero’s message id (0x + 64 hex), once the transaction landed.
  - `destinationTxHash` (string, required): The destination network’s transaction, once DELIVERED.
  - `scanStatus` (string, required): LayerZero Scan’s own status word, verbatim (`INFLIGHT`, `CONFIRMING`, `DELIVERED`, `PAYLOAD_STORED`, ...).
  - `scanUrl` (string, required): The transaction on LayerZero Scan (layerzeroscan.com), once it reached the network.
  - `failureReason` (string, required): Why a FAILED transfer failed.
  - `merchantFee` (MerchantFeeEntity, required): The merchant fee the request named, in USDT0, paid to its wallet in this transaction by the fee wrapper; null without one.
  - `idempotencyKey` (string, required): The Idempotency-Key it was created with, if any.
  - `expiresAt` (string (date-time), required): When the transaction's time bounds close: submit refuses it afterwards.
  - `submittedAt` (string (date-time), required): When it was first seen accepted by the network.
  - `createdAt` (string (date-time), required): When the transfer was built (ISO 8601 date-time).
  - `updatedAt` (string (date-time), required): When the transfer was last updated (ISO 8601 date-time).
- `400`: ValidationFailed (see Shared responses)
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `404`: NotFound (see Shared responses)
- `500`: InternalError (see Shared responses)

## Relay the signed USDT0 transaction to Stellar mainnet

`POST /v1/usdt0/transfers/{id}/submit`

The signed XDR must hash to the transfer’s transaction and carry a signature. Accepted and applied: SUBMITTED, with LayerZero’s `guid`. Applied and failed: FAILED. Refused by the network: the transfer stays PENDING (`submitted: false`, `reason`) and can be submitted again until it expires. Waits up to 30 seconds for the ledger.

Requires the `swaps:write` scope. The shared public key may call it.

**Path parameters**

- `id` (string, required)

**Headers**

- `X-Record-Token` (string, optional): Required with the shared public key: the `publicToken` the create response returned for this record. Without it, or with the token of another record, the answer is 404, as for a record that does not exist. Ignored for every other API key.

**Request body** (`application/json`, required): `SubmitUsdt0TransferDto`

- `signedXdr` (string, required): The signed transaction envelope (base64 XDR).

**Responses**

- `200` (`Usdt0SubmitResultEntity`): OK
  - `submitted` (boolean, required): True when the network accepted the transaction (status SUBMITTED, or already DELIVERED).
  - `status` (string, required): The transfer's status after this submission. One of: `PENDING`, `SUBMITTED`, `DELIVERED`, `FAILED`, `EXPIRED`.
  - `txHash` (string, optional): The Stellar transaction hash, once it reached the network.
  - `reason` (string, optional): Why it was not submitted, when `submitted` is false: the network refused it (the transfer stays PENDING and can be submitted again until it expires), or it failed on the ledger (FAILED).
  - `transfer` (Usdt0TransferEntity, required): The transfer after this submission.
- `400` (`ApiErrorBodyEntity`): `validation_failed`: `signedXdr` is not a transaction, is not the one built for this transfer, or carries no signature. `invalid_state_transition`: the transfer is FAILED or EXPIRED, or its transaction expired; build a new one. `network_unsupported`: a dev (testnet) key.
- `401`: Unauthorized (see Shared responses)
- `403`: Forbidden (see Shared responses)
- `404`: NotFound (see Shared responses)
- `429`: RateLimited (see Shared responses)
- `500`: InternalError (see Shared responses)
- `503` (`ApiErrorBodyEntity`): `provider_unavailable`: the Soroban RPC did not answer, or the network asked to try again later; the transfer stays PENDING, submit again. `misconfigured`: STELLAR_RPC_URL_MAINNET serves another network.

## Shared responses

- **Unauthorized** (`ApiErrorBodyEntity`): `no_authenticated_consumer`: The gateway forwarded no API key identity
- **Forbidden** (`ApiErrorBodyEntity`): `insufficient_scope`: the API key does not hold the scope this route requires. The shared public API key also gets this on every route that is not marked `x-cosmos-public-key`, with a message saying so; more scopes will not help, the key is the wrong one. `gateway_required`: the request did not arrive through APISIX.
- **InternalError** (`ApiErrorBodyEntity`): Unexpected server error. The detail is logged server-side and never returned: there is nothing in the body to branch on beyond the code.
- **RateLimited** (`ApiErrorBodyEntity`): The budget in `x-cosmos-rate-limit` is spent for this caller. Honour `Retry-After`. The `ratelimit-*` triple rides along on successful responses too, so a client can pace itself instead of being refused. If the counter store itself is unreachable the guard fails closed and answers `503 provider_unavailable`.
- **ValidationFailed** (`ApiErrorBodyEntity`): The body, query or path failed validation. `message` is an array of the individual failures. Routes that reject a *valid* request for a reason of their own (an amount, a memo, a state) document the code for it on their own 400.
- **NotFound** (`ApiErrorBodyEntity`): No such resource, or it exists and belongs to another consumer. The two are deliberately the same answer: "exists but not yours" is an ownership oracle.
