> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hex-api.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Deposits and withdrawals, pending first

> Every deposit and withdrawal over the HOT bridge from all sources (kit's direct ones in the registry, 1Click's legs, omni's pending withdrawals), deduplicated where they can be matched. Pending live and stuck first, then pending backlog and refund-only, then finished; newest first within each. Paginated by `cursor`.



## OpenAPI

````yaml https://mpc.hex-api.app/openapi.json get /bridge/transfers
openapi: 3.1.0
info:
  title: HEX MPC API
  version: 1.0.0
  summary: HOT bridge signatures and relay, the bridge registry and monitor.
  description: >
    The public API of `hex-mpc`, a Cloudflare Worker in front of the HOT MPC
    nodes. It replaces the old HOT backend's bridge endpoints

    (`api0.herewallet.app`: `process_bridge_deposit`, `auto_deposit_register`,
    ...) and HOR (`rpc1.hotdao.ai`, `rpc2.hotdao.ai`).


    ## Which routes to use


    - **Credit a deposit to NEAR Intents**: `POST /relay/deposit` with the
    source tx (or the deposit's fields). The service reads the deposit on its
    chain, signs it and sends `mt_deposit_call` on NEAR, paying the gas. This is
    what `process_bridge_deposit` did.

    - **Pay out withdrawals**: `POST /relay/withdraw` with the chain and the
    receiver; poll `GET /relay/jobs/{chain}/{id}`.

    - **Clear a paid withdrawal**: `POST /relay/clear`.

    - **Submit transactions yourself**: the `Signatures` routes return the MPC
    signatures only.

    - **Record what your users do** (optional, for support and recovery): `POST
    /bridge/register`, `/bridge/deposits`, `/bridge/withdrawals`.


    Every relay call sends only what holds on chain (a deposit that happened,
    the payout of a withdrawal omni holds, the clear of a paid one), and each at
    most once, so retrying a call is safe.


    ## Conventions


    - **Bodies** are JSON objects, at most 32 KiB (`/intents/solver`: 128 KiB).
    A body that is not a JSON object is a `422`, a larger one a `413`.

    - **Big integers.** Nonces and amounts are answered as decimal strings. In
    requests they may be decimal strings or JSON integers: integers above 2^53
    are read exactly (the bridge's nonces are about 1.8e21), but a decimal
    string is the safer choice for clients whose JSON encoder uses doubles.

    - **Nonces** are omni's: `unix seconds * 10^12 + n`.

    - **Encodings.** omni's token ids, receivers and the bridge signatures are
    base58; NEAR tx hashes are base58.

    - **Chain ids.** Chain ids are omni's (`v2_1.omni.hot.tg`), not always the
    chain's own: EVM chains use their EIP-155 id (Ethereum 1, Optimism 10, BNB
    56, Polygon 137, Monad 143, X Layer 196, Base 8453, Arbitrum 42161,
    Avalanche 43114, ...); the others have omni's numbers: Solana 1001, NEAR
    1010, Stellar 1100, TON 1117 (TON v1, 1111, is dead), Juno 4444118, Gonka
    4444119.

    - **Errors** are `{ "detail": "..." }` with an HTTP status (FastAPI's
    format, kept from HOR), the router's own `404`, `405` and `429` included.
    Clients should branch on the status and show or log the `detail`. A `5xx`
    (and a `502`/`503` in particular) is worth retrying with backoff; a `4xx`
    will answer the same until something changes on chain.

    - **CORS.** Any origin; the request's `Origin` is echoed with
    `access-control-allow-credentials: true`, and preflights allow `GET, POST,
    OPTIONS` with any header.

    - **Times** in answers are milliseconds since the epoch unless named `*_s`
    (seconds).


    ## Rate limits


    Per client IP (an IPv6 client by its /64), over 60 seconds, counted per
    Cloudflare location:


    | Class | Limit | Routes |

    | --- | --- | --- |

    | `bridge` | 300 / 60 s | `/withdraw/sign`, `/deposit/sign`, `/clear/sign`,
    `/relay/*`, `/bridge/*` |

    | `solver` | 120 / 60 s | `/intents/solver` |


    `/v1/health`, `/v1/time` and `/openapi.json` are not limited. Over the limit
    the answer is `429` `{ "detail": "Too many requests" }` with `Retry-After:
    60`.


    ## Load protection


    The MPC nodes are a fixed quorum: every signature is a round on each of
    them. So on top of the per-IP limits, every call that reaches the nodes (the
    `Signatures` routes, and the relay's own signing) is admitted globally,
    whoever asks:


    - **Rate per kind of signing**, by default 300 a minute each for
    withdrawals, deposits and clears: over it, `429` with `Retry-After`.

    - **Signings at once**, 60 in all, each kind its own share: over it, `503`
    `MPC nodes are busy, try again shortly` with `Retry-After`. Also `503` with
    `Retry-After` when the nodes answer `429` or too few of them are up.

    - **One signing per message.** A signature is kept for a day and answered
    again (a retry, another client, the relay), and while it is being made a
    second request waits for it (or gets `503` `This signature is being made,
    try again shortly` after 45 s). A refusal of the bridge (`400`) is answered
    again for 5 seconds.

    - **Refusals before the nodes**: a deposit omni already credited (`400`
    `Deposit … is already credited`), a withdrawal no payout can land (`400`
    `Withdrawal … : it can only be refunded`: it pays the token contract itself,
    the zero address, or a Stellar nonce past its 60 days).


    Retry a `429` or `503` after its `Retry-After`.
servers:
  - url: https://mpc.hex-api.app
    description: Production
security: []
tags:
  - name: Relay
    description: >-
      The recommended integration: the service sends the bridge's transactions
      and pays for them. Deposits are credited to NEAR Intents; withdrawals are
      paid out on their chain and cleared on omni.
  - name: Signatures
    description: >-
      The bridge's MPC signatures, for callers that submit the transactions
      themselves (HOR-compatible: same bodies, answers and errors). Each
      signature needs omni's word, and a deposit or clear also its AuthCall on
      chain, so a caller cannot forge or redirect one.
  - name: Registry
    description: >-
      The bridge registry: what users do on the bridge, as clients report it and
      as the relay sees it on chain. A post only records a claim: nothing is
      signed or sent for it, and what the relay reads on chain overrides it.
      Lookups answer 503 while the registry's database is not configured.
  - name: Monitor
    description: Health of every bridge HEX moves funds through, over 24 hours.
  - name: Intents
    description: >-
      NEAR Intents solver relay passthrough, used by HEX/HOT kit to publish
      signed intents.
  - name: Service
    description: Health, time and this document.
paths:
  /bridge/transfers:
    get:
      tags:
        - Monitor
      summary: Deposits and withdrawals, pending first
      description: >-
        Every deposit and withdrawal over the HOT bridge from all sources (kit's
        direct ones in the registry, 1Click's legs, omni's pending withdrawals),
        deduplicated where they can be matched. Pending live and stuck first,
        then pending backlog and refund-only, then finished; newest first within
        each. Paginated by `cursor`.
      operationId: listBridgeTransfers
      parameters:
        - name: chain
          in: query
          required: false
          description: omni's chain id, or `all`.
          schema:
            type: string
            default: all
        - name: direction
          in: query
          required: false
          description: ''
          schema:
            type: string
            enum:
              - deposit
              - withdrawal
              - all
            default: all
        - name: status
          in: query
          required: false
          description: '`refund` is taken for `refunded`.'
          schema:
            type: string
            enum:
              - pending
              - done
              - failed
              - refunded
              - all
            default: all
        - name: source
          in: query
          required: false
          description: '`1click` is taken for `oneclick`.'
          schema:
            type: string
            enum:
              - direct
              - oneclick
              - omni
              - all
            default: all
        - name: q
          in: query
          required: false
          description: >-
            A substring of the receiver, intent account, nonce, tx hash or
            1Click deposit address.
          schema:
            type: string
            maxLength: 200
        - name: from
          in: query
          required: false
          description: Created at or after, ms.
          schema:
            type: integer
        - name: to
          in: query
          required: false
          description: Created before, ms.
          schema:
            type: integer
        - name: limit
          in: query
          required: false
          description: ''
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
        - name: cursor
          in: query
          required: false
          description: '`next_cursor` of the previous page.'
          schema:
            type: string
      responses:
        '200':
          description: A page of transfers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransfersResponse'
        '400':
          description: A bad query parameter.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                bad:
                  value:
                    detail: direction must be one of deposit, withdrawal, all
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    TransfersResponse:
      type: object
      required:
        - now
        - items
        - next_cursor
        - pending
        - sources
      properties:
        now:
          type: number
        items:
          type: array
          items:
            $ref: '#/components/schemas/TransferRow'
        next_cursor:
          type:
            - string
            - 'null'
          description: Pass as `cursor` for the next page; null at the end.
        pending:
          type: integer
          description: Pending transfers matching the filters.
        sources:
          $ref: '#/components/schemas/MonitorSources'
    Error:
      type: object
      description: 'Every error: FastAPI''s `{ detail }` with the HTTP status.'
      required:
        - detail
      properties:
        detail:
          type: string
          description: What went wrong, readable.
      examples:
        - detail: Nonce was not used on target chain
    TransferRow:
      type: object
      required:
        - key
        - chain
        - chain_name
        - direction
        - source
        - status
        - stage
        - amount
        - usd
        - receiver
        - intent_account
        - txs
        - created_at
        - finished_at
        - duration_s
      properties:
        key:
          type: string
          description: >-
            `direct:deposit:<chain>:<tx|nonce:N>`, `direct:withdrawal:<nonce>`,
            `oneclick:<id>#<leg>` or `omni:<nonce>`.
        chain:
          type: string
        chain_name:
          type: string
        direction:
          type: string
          enum:
            - deposit
            - withdrawal
        source:
          type: string
          enum:
            - direct
            - oneclick
            - omni
          description: >-
            `direct`: kit reported it; `oneclick`: a 1Click leg over the HOT
            bridge; `omni`: pending in omni, origin unknown.
        status:
          type: string
          enum:
            - pending
            - done
            - failed
            - refunded
        triage:
          type: string
          enum:
            - live
            - stuck
            - backlog
            - refund
          description: Pending only.
        reason:
          type: string
          description: Why a refund-only withdrawal can never be paid.
        stage:
          type: string
          description: The registry's or 1Click's status, and the relay's job.
          examples:
            - PROCESSING, active
        amount:
          type:
            - string
            - 'null'
          description: '`12.5 BNB` when the symbol is known, else `<raw> <omni token id>`.'
        amount_raw:
          type: string
        token:
          type: string
        usd:
          type:
            - number
            - 'null'
        receiver:
          type:
            - string
            - 'null'
        intent_account:
          type:
            - string
            - 'null'
        nonce:
          type: string
        oneclick_id:
          type: string
        txs:
          type: array
          items:
            $ref: '#/components/schemas/MonitorTx'
        created_at:
          type: number
        finished_at:
          type:
            - number
            - 'null'
        duration_s:
          type:
            - integer
            - 'null'
          description: 'Finished: the time it took; pending: its age.'
        detail:
          type: string
        gasless:
          type: boolean
          description: >-
            A pending withdrawal paid through bridge-refuel.hot.tg: the user
            paid its payout's gas there (HOT's backend relayer and the relay's
            refuel sweep pay it out).
    MonitorSources:
      type: object
      required:
        - hot_sweep
        - oneclick
        - oneclick_enabled
      properties:
        hot_sweep:
          type:
            - number
            - 'null'
          description: When the refuel sweep last read omni's pending withdrawals, ms.
        oneclick:
          type:
            - number
            - 'null'
          description: When 1Click Explorer was last read, ms.
        oneclick_enabled:
          type: boolean
    MonitorTx:
      type: object
      required:
        - kind
        - hash
      properties:
        kind:
          type: string
          enum:
            - source
            - near
            - target
        hash:
          type: string
        url:
          type: string
          format: uri
  responses:
    TooManyRequests:
      description: >-
        Over the route's per-IP rate limit (60 s), or, on a route that signs,
        over the MPC nodes' signing rate (see Load protection). Wait
        `Retry-After` seconds.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            limited:
              value:
                detail: Too many requests
            signing:
              value:
                detail: Too many bridge_deposit signings, try again in 1 s
    InternalError:
      description: An unexpected error. Its message is not exposed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            internal:
              value:
                detail: Internal Server Error
  headers:
    RetryAfter:
      description: Seconds to wait.
      schema:
        type: integer
      example: 60

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.