> ## 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.

# Sign a paid withdrawal's clear

> Signs `clear_completed_withdrawal` of a withdrawal paid on its target chain (base58 of 64 bytes, `r ‖ s`). It signs with the MPC deposit wallet where omni's removal key for the chain is the MPC key, and with the removal key this service holds on the chains not moved to the MPC yet. A withdrawal not executed on its chain answers `400 Nonce was not used on target chain`. `POST /relay/clear` does this and sends the NEAR transaction too.



## OpenAPI

````yaml https://mpc.hex-api.app/openapi.json post /clear/sign
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:
  /clear/sign:
    post:
      tags:
        - Signatures
      summary: Sign a paid withdrawal's clear
      description: >-
        Signs `clear_completed_withdrawal` of a withdrawal paid on its target
        chain (base58 of 64 bytes, `r ‖ s`). It signs with the MPC deposit
        wallet where omni's removal key for the chain is the MPC key, and with
        the removal key this service holds on the chains not moved to the MPC
        yet. A withdrawal not executed on its chain answers `400 Nonce was not
        used on target chain`. `POST /relay/clear` does this and sends the NEAR
        transaction too.
      operationId: signClear
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NonceRequest'
            examples:
              clear:
                summary: A withdrawal's nonce
                value:
                  nonce: '1792107257000001836156'
      responses:
        '200':
          description: The signature.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MetaSignOut'
              examples:
                clear:
                  summary: Signed
                  value:
                    signature: >-
                      4sJhsuGTu8f9XoiAkZj3Si9GSjUT714yzQWdo5wZHkWpAKQHd69dfiT3RycMnUqhrT5FA4wokk6RbrFEFKkmPnW7
                    autopilot_hash: null
        '400':
          description: The clear cannot be signed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                unpaid:
                  value:
                    detail: Nonce was not used on target chain
                removalKey:
                  value:
                    detail: >-
                      The removal key of chain 56 is neither the MPC key nor
                      HOR's local one
                noKey:
                  value:
                    detail: Chain 1001 has no removal key
                mpc:
                  value:
                    detail: Cant sign clear by MPC
        '403':
          $ref: '#/components/responses/NodesUnavailable'
        '404':
          description: omni no longer holds the nonce.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                cleared:
                  value:
                    detail: Nonce was already cleared
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '422':
          $ref: '#/components/responses/InvalidNonce'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/SigningUnavailable'
components:
  schemas:
    NonceRequest:
      type: object
      required:
        - nonce
      properties:
        nonce:
          $ref: '#/components/schemas/NonceInput'
    MetaSignOut:
      type: object
      description: HOR's signature answer.
      required:
        - signature
        - autopilot_hash
      properties:
        signature:
          $ref: '#/components/schemas/Base58'
          description: >-
            The signature, base58. Withdrawals: 65 bytes in the target bridge's
            layout. Deposits and clears: 64 bytes, `r ‖ s`.
        autopilot_hash:
          type: 'null'
          description: Always null; kept from HOR's answer model.
    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
    NonceInput:
      description: >-
        omni's nonce: a decimal string (preferred) or a JSON integer, read
        exactly even above 2^53. Hex, floats and negatives are refused.
      oneOf:
        - $ref: '#/components/schemas/NonceString'
        - type: integer
          minimum: 0
    Base58:
      type: string
      pattern: ^[1-9A-HJ-NP-Za-km-z]+$
      description: Base58 (Bitcoin alphabet).
    NonceString:
      type: string
      pattern: ^\d{1,39}$
      description: omni's nonce (`unix seconds * 10^12 + n`), decimal.
      examples:
        - '1792944123000000004211'
  responses:
    NodesUnavailable:
      description: The MPC nodes refused or did not answer. Retry later.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            nodes:
              value:
                detail: RPC is not responding
    PayloadTooLarge:
      description: 'The body exceeds 32 KiB (`/intents/solver`: 128 KiB).'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            tooLarge:
              value:
                detail: Body exceeds 32768 bytes
    InvalidNonce:
      description: The nonce is not a decimal integer, or the body is not a JSON object.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            nonce:
              value:
                detail: nonce must be a decimal integer
            json:
              value:
                detail: Body must be JSON
    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
    BadGateway:
      description: >-
        A chain or NEAR RPC is unavailable, or an answer could not be read.
        Retry with backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            near:
              value:
                detail: NEAR RPC is unavailable, try again
            chain:
              value:
                detail: Stellar RPC of chain 1100 is unavailable, try again
    SigningUnavailable:
      description: >-
        The MPC nodes cannot take the signing now (busy, rate limited by the
        nodes, too few of them up, or the same signature is being made), with
        `Retry-After`; or something the route needs is not configured.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            busy:
              value:
                detail: MPC nodes are busy, try again shortly
            down:
              value:
                detail: MPC nodes are unavailable, try again shortly
            inFlight:
              value:
                detail: This signature is being made, try again shortly
            nodes:
              value:
                detail: MPC nodes are not configured
            relay:
              value:
                detail: The relay's NEAR keys are not configured
  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.