P2P trading and all other Bitania services are temporarily disabled until further notice. Only swaps are available for now.
REST API Endpoint

Get swap status

POST /swap/status

Get the current status of a swap. Poll it every 10–30 seconds until a terminal status.

Status values:

  • NEW — Awaiting deposit (time.left counts down)
  • PENDING — Deposit detected, not confirmed yet (0 confirmations)
  • CONFIRMING — Deposit confirming; from.tx.confirmations vs from.reqConfirmations
  • EXCHANGING — Deposit confirmed and credited at the applicable rate; payout being prepared
  • SENDING — Payout broadcast, waiting for it to land
  • DONE — Swap completed; to.tx.id has the payout hash, rateActual the applied rate
  • EXPIRED — No deposit within the payment window
  • REFUNDED — Deposit returned to the refund address (refund.tx)
  • RATE_CHANGED — A fixed-rate deposit differs from the order by more than 0.5 % (issue.type is LESS or MORE, proposed holds the re-quote). The user decides: EXCHANGE or REFUND via Resolve a swap.
  • REFUNDING — The deposit is going back: because the user chose it, or automatically because it is below the pair minimum (issue.type BELOW_MINIMUM) or larger than we can pay out (NO_LIQUIDITY). If issue.needsRefundAddress is true we are waiting for a refund address: send one with REFUND. Ends in REFUNDED with refund.tx.
  • FAILED — Under manual review by Bitania (for example a payout that failed on-chain); issue.reason says why. No self-service action; it resolves to DONE or REFUNDED.

Floating-rate swaps never enter RATE_CHANGED: whatever amount arrives is converted at the market rate of the moment it confirms, and extra deposits sent to the same address while the swap is open are credited the same way. The minimum and liquidity rules apply to both rate types.

Authentication: HMAC-signed (v2) request — X-API-KEY, X-API-SIGN, X-API-TIMESTAMP, X-API-NONCE headers. See the Swap Aggregator Guide for the signing scheme.

Authorization (dual-mode):

  • Default: the swap must belong to your API key (it was created with your key, or through your referral link). No body changes required.
  • Optional: include the token returned by /swap/create. If it matches, the call is authorized regardless of which key created the swap — for cross-aggregator status views.

An unknown id and a swap you may not see both return 404 Swap not found.

Request

Request Body (required)

Content-Type: application/json

{
  id: string, required, e.g. "k7m3px9qw2" — Swap id (10 characters; dry-run ids start with DR)
  token: string — Optional per-swap token from /swap/create; authorizes the call from a different API key
}

Response 200

Success

{
  code: integer, e.g. 0 — 0 = success, 1 = error
  msg: string, e.g. "" — Error message (empty on success)
  data: object — Swap order (returned by create, status, advance and emergency)
    {
      id: string, e.g. "k7m3px9qw2" — Swap id: 10 characters (dry-run swaps: "DR" + 8). Use it for status and emergency calls.
      token: string, e.g. "uYx9j2k3Lm4nOp5qRs6tUw" — Per-swap access token (22 characters). Lets another API key, or a shared link, read the status. Treat it as a secret.
      type: string, enum: float|fixed — Rate type
      status: string, enum: NEW|PENDING|CONFIRMING|RATE_CHANGED|EXCHANGING|SENDING|REFUNDING|DONE|EXPIRED|REFUNDED|FAILED — Current status (see Get swap status)
      time: object — UNIX timestamps in seconds
        {
          reg: integer — Swap creation time
          start: integer|null — When the deposit was first detected
          finish: integer|null — When the swap ended (DONE or REFUNDED)
          update: integer — Last change
          expiration: integer — End of the payment window
          left: integer|null — Seconds left in the payment window; null once a deposit was seen or the swap ended
        }
      from: object — What the user sends
        {
          code: string, e.g. "TRX" — Currency code
          coin: string, e.g. "TRX" — Coin ticker
          network: string, e.g. "TRX" — Chain
          name: string, e.g. "Tron" — Display name
          amount: string, e.g. "1000" — Amount the user is expected to send (string, full precision)
          amountDeposited: string, e.g. "0" — Sum of the confirmed deposits so far
          address: string — Deposit address to show the user
          reqConfirmations: integer, e.g. 1 — Confirmations we wait for before crediting a deposit
          tx: object|null — The deposit transaction, once detected
            {
              id: string — Transaction hash
              amount: string — Deposited amount
              fee: string|null — Network fee (not known for deposits)
              feeCurrency: string|null — Currency of the fee
              timeReg: integer — When we first saw the transaction
              timeBlock: integer|null — When it reached the required confirmations
              confirmations: integer — Current confirmation count
            }
        }
      to: object — What the user receives
        {
          code, coin, network, name — as in from
          amount: string, e.g. "339.15" — Amount we pay out: the quote until the deposit is confirmed, the final amount afterwards
          address: string — Destination address
          tx: object|null — The payout transaction, once sent: id, amount, fee (the network fee we paid), feeCurrency, timeReg, confirmations (refreshed while you poll, until the coin's own threshold), txKey (Monero only: the transaction key that proves the payment to the recipient's address; null elsewhere)
        }
      refund: object
        {
          address: string|null — Refund address (from the create call, or from an emergency REFUND call)
          tx: object|null — The refund transaction, once sent
        }
      issue: object — Why the swap is not simply executing, and what was decided
        {
          type: string|null, enum: LESS|MORE|BELOW_MINIMUM|NO_LIQUIDITY — LESS / MORE: a fixed-rate deposit under / over the ordered amount (RATE_CHANGED). BELOW_MINIMUM: the deposit is under the pair minimum. NO_LIQUIDITY: the payout is more than we hold. Both of the latter are refunded automatically.
          reason: string|null — Human-readable explanation while the swap is RATE_CHANGED, REFUNDING or FAILED
          needsRefundAddress: boolean — true when we want to refund but no refund address is known: send one with POST /swap/emergency (choice REFUND)
          choice: string, enum: NONE|EXCHANGE|REFUND — What was decided: EXCHANGE (executed at the new rate), REFUND (being / been refunded)
        }
      rate: string, e.g. "0.34" — Rate at creation: to-coin per 1 from-coin
      rateActual: string|null — Rate actually applied; set when the swap is DONE
      fee: object — Our service fee: { percent: number, e.g. 0.25 — amount: string, in the to-coin }
      slippage: number|null — Applied rate vs quoted rate, in percent; set when the deposit is credited (0 for a fixed-rate swap honoured as quoted)
      proposed: object|null — While RATE_CHANGED: the re-quote the user accepts with EXCHANGE: { rate, amount }
      dryrun: boolean — true for simulated swaps
      url: string|null — Public status page of the swap on bitania.com (null for dry-run swaps)
    }
}

Response 404

Unknown swap, or a swap that does not belong to your key (and no valid token was given)

{
  code: integer, e.g. 1
  msg: string, e.g. "Swap not found"
  data: null
}

Response 400

Validation or business error, for example: Missing required fields: id

{
  code: integer, e.g. 1 — Error code (1)
  msg: string, e.g. "Missing required fields: from, to, amount" — Error message
  data: null
}

Response 401

Authentication failed: unknown or disabled key, IP not whitelisted (Invalid credentials), or a bad signature, stale timestamp or reused nonce (Invalid signature)

{
  code: integer, e.g. 1
  msg: string, e.g. "Invalid credentials"
  data: null
}

Response 429

Rate limit of this endpoint exhausted; wait retry_after seconds (also sent as the Retry-After header)

{
  code: integer, e.g. 1
  msg: string, e.g. "Rate limit exceeded. Please retry after 12 seconds."
  data: null
  retry_after: integer, e.g. 12
}