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

# Swap

> Build an unsigned swap transaction from a quote.

**Visibility modes:**

- **`visibility: "public"`** (default) — pure pass-through to the Jupiter/Metis upstream. The returned transaction is whatever the upstream produces.
- **`visibility: "private"`** — the server forces Jupiter's output into a program-owned stash ATA (deterministically derived from `(userPublicKey, quoteResponse.outputMint)`), prepends an idempotent ATA-create, and appends a `schedule_private_transfer` instruction that registers a one-shot Hydra crank. When the crank fires, it self-CPIs into the on-chain private-transfer flow to deliver the swapped tokens to `destination` with the requested delay/split policy. The returned transaction is a v0 `VersionedTransaction` that is still unsigned — the client signs and submits.

When `visibility = "private"`, the fields `destination`, `minDelayMs`, `maxDelayMs`, and `split` are **required**. `clientRefId` and `validator` are optional. Explicitly setting `destinationTokenAccount` to anything other than the server-derived stash ATA returns `400`.



## OpenAPI

````yaml /pages/private-ephemeral-rollups-pers/api-reference/per/openapi/swap.openapi.json POST /v1/swap/swap
openapi: 3.1.0
info:
  title: Private Payments API
  version: 0.1.0
  description: >-
    Build an unsigned swap transaction from a quote. Supports public swaps
    (transparent Jupiter/Metis pass-through) and private swaps (forces output
    into a program-owned stash ATA and appends a scheduled private transfer).
servers:
  - url: https://payments.magicblock.app
    description: Mainnet - Private Payments API
security: []
paths:
  /v1/swap/swap:
    post:
      summary: Swap
      description: >-
        Build an unsigned swap transaction from a quote.


        **Visibility modes:**


        - **`visibility: "public"`** (default) — pure pass-through to the
        Jupiter/Metis upstream. The returned transaction is whatever the
        upstream produces.

        - **`visibility: "private"`** — the server forces Jupiter's output into
        a program-owned stash ATA (deterministically derived from
        `(userPublicKey, quoteResponse.outputMint)`), prepends an idempotent
        ATA-create, and appends a `schedule_private_transfer` instruction that
        registers a one-shot Hydra crank. When the crank fires, it self-CPIs
        into the on-chain private-transfer flow to deliver the swapped tokens to
        `destination` with the requested delay/split policy. The returned
        transaction is a v0 `VersionedTransaction` that is still unsigned — the
        client signs and submits.


        When `visibility = "private"`, the fields `destination`, `minDelayMs`,
        `maxDelayMs`, and `split` are **required**. `clientRefId` and
        `validator` are optional. Explicitly setting `destinationTokenAccount`
        to anything other than the server-derived stash ATA returns `400`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
              properties:
                userPublicKey:
                  type: string
                  description: >-
                    Public key of the wallet that will sign the swap
                    transaction.
                  example: 3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE
                quoteResponse:
                  type: object
                  additionalProperties: true
                  description: Quote response from `GET /v1/swap/quote`.
                payer:
                  type: string
                  description: Optional fee payer for transaction fees and rent.
                  example: 3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE
                wrapAndUnwrapSol:
                  type: boolean
                  description: Automatically wrap and unwrap native SOL when needed.
                  example: true
                useSharedAccounts:
                  type: boolean
                  description: Allow shared accounts for intermediate routing state.
                  example: true
                feeAccount:
                  type: string
                  description: >-
                    Optional initialized token account used to collect platform
                    fees.
                trackingAccount:
                  type: string
                  description: >-
                    Optional public key used for downstream transaction
                    tracking.
                prioritizationFeeLamports:
                  anyOf:
                    - type: integer
                      minimum: 0
                    - type: object
                      additionalProperties: true
                  description: Optional priority fee configuration or fixed lamport amount.
                asLegacyTransaction:
                  type: boolean
                  description: >-
                    Build a legacy transaction instead of a versioned one. Not
                    allowed when `visibility = "private"`.
                destinationTokenAccount:
                  type: string
                  description: >-
                    Optional destination token account for the output mint. When
                    `visibility = "private"`, this is server-controlled and must
                    match the derived stash ATA.
                nativeDestinationAccount:
                  type: string
                  description: >-
                    Optional destination account for native SOL output. Not
                    supported when `visibility = "private"`.
                dynamicComputeUnitLimit:
                  type: boolean
                  description: >-
                    Estimate compute usage and set the compute unit limit
                    automatically.
                skipUserAccountsRpcCalls:
                  type: boolean
                  description: Skip extra RPC checks for required user accounts.
                dynamicSlippage:
                  type: boolean
                  description: >-
                    Let the upstream swap builder overwrite slippage on the
                    transaction.
                computeUnitPriceMicroLamports:
                  type: integer
                  minimum: 0
                  description: Optional exact compute unit price in micro-lamports.
                blockhashSlotsToExpiry:
                  type: integer
                  minimum: 0
                  description: Optional transaction expiry window in slots.
                positiveSlippage:
                  type: object
                  additionalProperties: true
                  description: Optional positive slippage collection settings.
                visibility:
                  type: string
                  enum:
                    - public
                    - private
                  description: >-
                    `public` (default) proxies Jupiter/Metis as-is. `private`
                    routes the output through a scheduled private transfer.
                  example: public
                destination:
                  type: string
                  description: >-
                    Final private-transfer recipient (wallet pubkey). Required
                    when `visibility = "private"`.
                minDelayMs:
                  type: string
                  pattern: ^\d+$
                  description: >-
                    Earliest (ms) the queued transfer may settle. Required when
                    `visibility = "private"`.
                  example: '0'
                maxDelayMs:
                  type: string
                  pattern: ^\d+$
                  description: >-
                    Latest (ms) the queued transfer may settle. Required when
                    `visibility = "private"`. Must be `>= minDelayMs` and `<=
                    600000` (10 minutes).
                  example: '60000'
                split:
                  type: integer
                  minimum: 1
                  maximum: 14
                  description: >-
                    Number of queue entries to split the transfer across.
                    Required when `visibility = "private"`. Must be between 1
                    and 14.
                clientRefId:
                  type: string
                  pattern: ^\d+$
                  description: >-
                    Optional u64 client correlation id attached to each queued
                    split.
                validator:
                  type: string
                  description: >-
                    Optional validator pubkey for the transfer-queue PDA.
                    Defaults to the well-known MagicBlock validator
                    (`MAS1Dt9qreoRMQ14YQuhg8UTZMMzDdKhmkZMECCzk57`).
              required:
                - userPublicKey
                - quoteResponse
            examples:
              public:
                summary: Public swap (default behaviour, upstream proxy)
                value:
                  userPublicKey: 3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE
                  quoteResponse:
                    inputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                    inAmount: '1000000'
                    outputMint: Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
                    outAmount: '999519'
                    otherAmountThreshold: '994522'
                    swapMode: ExactIn
                    slippageBps: 50
                    priceImpactPct: '0'
                    routePlan: []
              private:
                summary: Private swap with scheduled transfer
                value:
                  userPublicKey: 3rXKwQ1kpjBd5tdcco32qsvqUh1BnZjcYnS5kYrP7AYE
                  quoteResponse:
                    inputMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                    inAmount: '1000000'
                    outputMint: Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
                    outAmount: '999519'
                    otherAmountThreshold: '994522'
                    swapMode: ExactIn
                    slippageBps: 50
                    priceImpactPct: '0'
                    routePlan: []
                  visibility: private
                  destination: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
                  minDelayMs: '0'
                  maxDelayMs: '60000'
                  split: 1
      responses:
        '200':
          description: Swap transaction
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
                properties:
                  swapTransaction:
                    type: string
                    description: Base64-encoded unsigned transaction.
                  lastValidBlockHeight:
                    type: integer
                    minimum: 0
                  prioritizationFeeLamports:
                    type: integer
                    minimum: 0
                  privateTransfer:
                    type: object
                    description: >-
                      Present only when `visibility = "private"`. Diagnostic
                      metadata about the appended `schedule_private_transfer`
                      instruction.
                    properties:
                      stashAta:
                        type: string
                      hydraCrankPda:
                        type: string
                      shuttleId:
                        type: integer
                        minimum: 0
                    required:
                      - stashAta
                      - hydraCrankPda
                      - shuttleId
                required:
                  - swapTransaction
              examples:
                public:
                  summary: Response for visibility=public
                  value:
                    swapTransaction: AQABA...base64...
                    lastValidBlockHeight: 318120000
                private:
                  summary: Response for visibility=private (with diagnostic block)
                  value:
                    swapTransaction: >-
                      AQABA...base64 with appended ATA-create +
                      schedule_private_transfer...
                    lastValidBlockHeight: 318120000
                    privateTransfer:
                      stashAta: 9mZP3xKHvVqXd3xtk72nSeEwJjmsgqmXvUDfwNA9BM4K
                      hydraCrankPda: HyDraCrNkPdA11111111111111111111111111111111
                      shuttleId: 2147483647
        '400':
          description: Invalid request (missing or conflicting private-transfer fields)
        '500':
          description: Configuration error (e.g. missing `METIS_SWAP_API_URL`)
        '502':
          description: Upstream error

````