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

# Create a reverse swap

> Lightning → on-chain. You send the hash of your preimage and your claim public key; the maker returns a hold invoice locked to that hash, the lockup address it will fund, the swap tree, and its timeout. **Verify that the invoice commits to your hash and that the lockup is claimable with your key before paying.** The response carries `swapAuth`, issued once: store it with the swap.



## OpenAPI

````yaml /openapi.json post /v2/swap/reverse
openapi: 3.1.0
info:
  title: KaleidoSwap Maker API
  version: v2
  description: >-
    Public HTTP API of the KaleidoSwap maker. Wire-compatible with the Boltz
    `/v2` protocol for submarine, reverse, and chain swaps, with KaleidoSwap
    additions (RGB, atomic swaps, pay-through, LSPS1, swap credentials).
    Integrate through the Swap SDK where possible: it verifies every swap the
    maker proposes.
  contact:
    name: KaleidoSwap
    url: https://kaleidoswap.com
servers:
  - url: https://maker.signet.kaleidoswap.com
    description: Signet (Mutinynet)
security: []
tags:
  - name: Service
    description: Maker identity, version, and capabilities.
  - name: Pairs and quotes
    description: Routes the maker trades, their limits and fees, and quotes.
  - name: Submarine swaps
    description: On-chain → Lightning. You lock on chain; the maker pays your invoice.
  - name: Reverse swaps
    description: >-
      Lightning → on-chain. You pay a hold invoice; the maker locks on chain;
      you claim.
  - name: Chain swaps
    description: On-chain → on-chain. Both sides lock; you claim the maker's lockup.
  - name: Swap status
    description: Swap status over HTTP and WebSocket.
  - name: Recovery
    description: Restore swaps from an xpub and recover swap credentials.
  - name: Atomic RGB swaps
    description: BTC ↔ RGB asset swaps in a single transaction.
  - name: Pay-through
    description: Lightning payment → on-chain payout to any address.
  - name: Lightning channels (LSPS1)
    description: Buy inbound Lightning channels (LSPS1).
  - name: Chain data
    description: The maker's view of chain tips and fees.
paths:
  /v2/swap/reverse:
    post:
      tags:
        - Reverse swaps
      summary: Create a reverse swap
      description: >-
        Lightning → on-chain. You send the hash of your preimage and your claim
        public key; the maker returns a hold invoice locked to that hash, the
        lockup address it will fund, the swap tree, and its timeout. **Verify
        that the invoice commits to your hash and that the lockup is claimable
        with your key before paying.** The response carries `swapAuth`, issued
        once: store it with the swap.
      operationId: create_reverse_swap
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateReverseRequest'
        required: true
      responses:
        '201':
          description: Swap created; hold invoice minted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReverseCreateResponse'
        '400':
          description: Malformed input or webhook URL.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Active swap exists for this preimageHash.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >-
            Quote/inventory/derivation failure, unsafe timeout ordering, or
            disabled pair.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: >-
            Over the caller-rate or rolling notional budget; carries
            Retry-After.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: >-
            signing key, node, or chain provider unavailable, or no usable BTC
            fee rate for a Bitcoin L1 lockup.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - {}
        - PartnerAuth: []
        - OrgKey: []
components:
  schemas:
    CreateReverseRequest:
      type: object
      description: Body of `POST /v2/swap/reverse` — Boltz-shaped, camelCase.
      required:
        - invoiceAmount
      properties:
        address:
          type:
            - string
            - 'null'
          description: |-
            Optional taker-owned Liquid destination for an L-BTC Magic Routing
            Hint. Must be paired with `addressSignature`.
        addressSignature:
          type:
            - string
            - 'null'
          description: BIP-340 signature by `claimPublicKey` over SHA256(address UTF-8).
        beneficiary:
          type:
            - string
            - 'null'
          description: >-
            A `kaleidoswap:` beneficiary handoff, in place of `preimageHash` +

            `claimPublicKey`. This is how a payer pays **someone else** without
            having to take the

            recipient's hash and key apart: the recipient's wallet emits one

            string, the payer's passes it through. The maker checks the
            request's

            network, expiry, destination layer and asset against the route it

            resolves, and refuses to under-deliver what the recipient asked for.
        bolt12Refund:
          type:
            - string
            - 'null'
          description: >-
            **BOLT12**: an `lnr1…` refund (a BOLT12 invoice request not tied to

            an offer) the taker's node created for `invoiceAmount`. When present

            the maker answers it — instead of minting a BOLT11 hold invoice —

            with a BOLT12 invoice locked to `preimageHash`, holds it
            identically,

            and delivers it back over the refund's onion-message paths; the

            response's `invoice` is then that `lni1…`. The refund's amount must

            equal `invoiceAmount`.
        claimPublicKey:
          type:
            - string
            - 'null'
          description: |-
            The 33-byte compressed claim public key, hex — the key that claims
            the maker's lockup. Optional only when `beneficiary` carries it.
        from:
          type:
            - string
            - 'null'
          description: 'Boltz: Lightning currency symbol (e.g. `"BTC"`). Combined with `to`.'
        invoiceAmount:
          type: integer
          format: int64
          description: |-
            Amount, in sats, the taker pays via the hold invoice (Boltz
            convention: `invoiceAmount` on Reverse). v0 BTC/BTC is 1:1 so this
            is also what the taker receives on-chain.
          minimum: 0
        pairHash:
          type:
            - string
            - 'null'
          description: >-
            Optional `pairHash` rate-lock: the hash the taker quoted against.
            Verified against the pair's current rate card when present;

            a mismatch is rejected with `400 pair_hash_mismatch`.
        pairId:
          type:
            - string
            - 'null'
          description: >-
            Trading-pair key, e.g. `"BTC/BTC"`. Optional when `from`+`to` are
            given.
        preimageHash:
          type:
            - string
            - 'null'
          description: >-
            The BOLT11 payment hash — `SHA256(preimage)`, 32 bytes hex. The hold

            invoice is locked to this hash; whoever holds the preimage reveals
            it

            on-chain when claiming the maker's lockup. Optional only when
            `beneficiary` carries it instead.
        to:
          type:
            - string
            - 'null'
          description: 'Boltz: on-chain currency symbol the taker receives (e.g. `"BTC"`).'
        webhook:
          oneOf:
            - $ref: '#/components/schemas/WebhookConfig'
              description: >-
                Optional HTTPS callback for status changes (Boltz `webhook`
                shape).
            - type: 'null'
    ReverseCreateResponse:
      type: object
      description: '`POST /v2/swap/reverse` response.'
      required:
        - id
        - swapAuth
        - invoice
        - refundPublicKey
        - lockupAddress
        - swapTree
        - timeoutBlockHeight
        - onchainAmount
      properties:
        assetId:
          type:
            - string
            - 'null'
        blindingKey:
          type:
            - string
            - 'null'
          description: >-
            `null` for Liquid; absent for Bitcoin, which has no such field. The
            maker mints its Liquid HTLC lockups **unconfidential** on

            purpose, so no output blinding key exists to return: treat

            `lockupAddress` as explicit — fund it with an unblinded output

            where the taker funds, and build claims against an explicit

            prevout where the taker claims.
        feeAssetId:
          type:
            - string
            - 'null'
        id:
          type: string
        invoice:
          type: string
          description: BOLT11 hold invoice the taker pays.
        lockupAddress:
          type: string
          description: Maker's on-chain (or Liquid/Arkade) lockup address.
        onchainAmount:
          type: integer
          format: int64
          description: On-chain amount the maker locks for the taker to claim.
          minimum: 0
        refundPublicKey:
          type: string
          description: 33-byte compressed maker refund pubkey (hex).
        rgb:
          oneOf:
            - $ref: '#/components/schemas/RgbLock'
              description: >-
                **RGB routes only** (`to` on `rgb_l1`): how to find and claim
                the

                RGB asset the maker locks in the swap tree's P2TR
                `lockupAddress`. `onchainAmount` is then the asset amount in the
                contract's units,

                not sats.
            - type: 'null'
        swapAuth:
          type: string
          description: |-
            Per-swap taker credential, 32 bytes hex — see
            `swapAuth`.
        swapTree:
          $ref: '#/components/schemas/SwapTree'
        timeoutBlockHeight:
          type: integer
          format: int64
          description: |-
            Block height (BTC/Liquid) or unix-ts (Arkade) at which the maker's
            refund branch opens.
    ErrorResponse:
      type: object
      description: Boltz-shaped error envelope.
      required:
        - error
      properties:
        details:
          type:
            - string
            - 'null'
          description: Optional human-readable detail. Present on 4xx; absent on 5xx.
        error:
          type: string
          description: Stable machine-readable error code, e.g. `pair_hash_mismatch`.
    WebhookConfig:
      type: object
      description: |-
        Opt-in HTTPS callbacks for a swap's status changes. ```json
        "webhook": {
          "url": "https://merchant.example/callback",
          "hashSwapId": true,
          "status": ["transaction.confirmed", "invoice.paid"]
        }
        ```
      required:
        - url
      properties:
        hashSwapId:
          type: boolean
          description: >-
            When `true`, the swap id in the callback payload is
            `SHA256(swap_id)`

            — for merchants that don't want correlatable ids on the wire.
        status:
          type:
            - array
            - 'null'
          items:
            type: string
          description: |-
            `None` (the
            field absent) means *every* transition is delivered.
        url:
          type: string
          description: Callback URL.
    RgbLock:
      type: object
      description: >-
        The RGB lock of a swap whose deposit (submarine) or payout (reverse) is

        an RGB asset in the swap tree's P2TR output. **Submarine:** the taker's
        rgb-lib `send` pays a witness recipient:

        `recipientId` (the HTLC script) with `WitnessData { amount_sat: htlcSat,

        blinding }`, assigning `amount` of `assetId`, and posts the consignment
        to

        `transportEndpoints`. The maker pays the invoice once the lock has

        `minConfirmations` and it holds exactly `amount` on the HTLC output;
        after

        `timeoutBlockHeight` the taker can reclaim through the refund leaf, with
        a

        colored spend (an uncolored one burns the asset). **Reverse:** once the
        hold invoice is paid (held) the maker's rgb-lib send

        pays `htlcSat` to `scriptPubkey` assigning `amount` of `assetId`, and

        posts the consignment to `transportEndpoints` under `recipientId`; the

        lock txid is then on `GET /v2/swap/reverse/{id}/transaction`. The taker

        accepts it with `blinding`, waits for `minConfirmations`, and claims

        through the claim leaf with a colored spend of the HTLC alone (output 0
        an

        OP_RETURN commitment): `htlcSat` pays the claim at `claimFeeRate` and

        leaves a 546-sat colored output, so the taker needs no BTC of their own.
        The claim reveals the preimage, which settles the hold. An uncolored

        spend burns the asset. After `timeoutBlockHeight` the maker refunds.
      required:
        - assetId
        - amount
        - recipientId
        - blinding
        - htlcSat
        - scriptPubkey
        - transportEndpoints
        - minConfirmations
      properties:
        amount:
          type: integer
          format: int64
          description: >-
            Asset amount in the contract's smallest unit; equals
            `expectedAmount`

            (submarine) or `onchainAmount` (reverse).
          minimum: 0
        assetId:
          type: string
          description: RGB contract id (`rgb:…`).
        blinding:
          type: string
          description: |-
            Decimal blinding chosen by the maker. A string preserves all 63 bits
            in JavaScript clients, whose JSON numbers lose precision above 2^53.
        claimFeeRate:
          type:
            - integer
            - 'null'
          format: int64
          description: '**Reverse only**: fee rate, sat/vB, `htlcSat` funds the claim at.'
          minimum: 0
        cooperativeRefund:
          type:
            - string
            - 'null'
        htlcSat:
          type: integer
          format: int64
          description: |-
            Sats of the HTLC output: at least this (submarine); 546 plus the
            claim fee at `claimFeeRate` (reverse).
          minimum: 0
        minConfirmations:
          type: integer
          format: int32
          description: |-
            Confirmations the lock needs before the other side acts on it; the
            timeout leaves room for them and for the claim to confirm.
          minimum: 0
        recipientId:
          type: string
          description: |-
            rgb-lib recipient id of the HTLC script: the proxy key of the lock
            consignment.
        scriptPubkey:
          type: string
          description: |-
            The HTLC output script (hex), the same P2TR as `address` /
            `lockupAddress`.
        transportEndpoints:
          type: array
          items:
            type: string
          description: RGB proxy the lock consignment is posted to.
    SwapTree:
      type: object
      description: '`swapTree` returned on every swap creation + status response.'
      required:
        - claimLeaf
        - refundLeaf
      properties:
        claimLeaf:
          $ref: '#/components/schemas/SwapLeaf'
        refundLeaf:
          $ref: '#/components/schemas/SwapLeaf'
    SwapLeaf:
      type: object
      description: |-
        One tapscript leaf — leaf-version byte (`196` / `0xc4` for elements,
        `192` / `0xc0` for Bitcoin) plus the hex script.
      required:
        - version
        - output
      properties:
        output:
          type: string
          description: Hex-encoded leaf script.
        version:
          type: integer
          format: int32
          description: Tapscript leaf-version byte.
          minimum: 0
  securitySchemes:
    PartnerAuth:
      type: http
      scheme: bearer
      bearerFormat: kld_test_… / kld_live_…
      description: >-
        Secret organization API key from the partner panel, for servers. Sent on
        swap creation as `Authorization: Bearer <key>` to attribute the swap to
        your organization. Optional; an invalid key is rejected. Never use it in
        client-side code.
    OrgKey:
      type: apiKey
      in: header
      name: X-Kaleido-Org-Key
      description: >-
        Public organization key (64 hex characters) for client-side attribution.
        A label, not a credential. Sent on swap creation only. Never combine
        with `PartnerAuth`.

````

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