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

# Create a checkout session

> Bills a payer a FIXED amount. `destAmount` is the amount you receive, and the payer covers whatever the route costs on top. Use this when you are selling something at a known price.

Creation is idempotent on `orderId`: replaying the same `orderId` while a session is still open returns the EXISTING session with `200` instead of creating a second one, so a retried request cannot double-charge. A new session is `201`. Multi-destination Checkout is deprecated; existing requests remain supported during migration to one fixed Checkout destination.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/payments/checkout
openapi: 3.1.0
info:
  title: Hypermid API
  description: >-
    Price and execute cross-chain swaps, read reference data and payer balances,
    and quote the fiat on-ramp. Quotes return an executable `transactionRequest`
    your frontend submits directly, so Hypermid never custodies the funds.


    Payments — `checkout`, `deposit`, and `withdrawal` sessions — and
    payment-link management are available through these merchant REST endpoints
    and the [`@hypermid/sdk`](https://docs.hypermid.io/sdk/payments) package.
    Payer-facing routes are intentionally omitted.
  version: 0.2.0
  contact: {}
servers:
  - url: https://server.hypermid.io
    description: Production — live keys (sk_live_…)
  - url: https://server.hypermid.io
    description: Sandbox — test keys (sk_test_…), testnets only
security: []
tags:
  - name: payments
    description: >-
      Create and read payment sessions, manage webhooks, and configure payout
      addresses with a secret partner key.
  - name: payment links
    description: >-
      Create, read, version, and revoke reusable checkout payment links with a
      secret partner key.
  - name: quote
    description: >-
      Route pricing for the orchestration product. Returns an executable
      `transactionRequest` your frontend submits directly, so Hypermid never
      custodies the funds.
  - name: status
    description: >-
      Resolve the state of a submitted swap or transfer. Two endpoints with
      different audiences — see each one's description before choosing.
  - name: catalog
    description: >-
      Reference data an integration needs to render a picker: supported chains
      and tokens, prices, routable connections, and fee configuration. A sandbox
      key sees only testnets here.
  - name: balances
    description: Read a payer wallet's token balances across supported chains.
  - name: onramp
    description: >-
      The fiat rail — card and bank payment for crypto, quoted and settled
      through our onramp partner. Requires per-partner onramp credentials on
      your account.
  - name: webhooks
    description: >-
      Events Hypermid sends TO you when a session completes. These are requests
      we make to your server, not endpoints you call.
paths:
  /v1/payments/checkout:
    post:
      tags:
        - payments
      summary: Create a checkout session
      description: >-
        Bills a payer a FIXED amount. `destAmount` is the amount you receive,
        and the payer covers whatever the route costs on top. Use this when you
        are selling something at a known price.


        Creation is idempotent on `orderId`: replaying the same `orderId` while
        a session is still open returns the EXISTING session with `200` instead
        of creating a second one, so a retried request cannot double-charge. A
        new session is `201`. Multi-destination Checkout is deprecated; existing
        requests remain supported during migration to one fixed Checkout
        destination.
      operationId: PaymentController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCheckoutDto'
      responses:
        '200':
          description: >-
            Idempotent replay: the existing non-terminal session for the same
            partner and orderId.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiEnvelope'
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: '#/components/schemas/PaymentCreateResultDto'
        '201':
          description: New or revived payment session created.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiEnvelope'
                  - type: object
                    required:
                      - data
                    properties:
                      data:
                        $ref: '#/components/schemas/PaymentCreateResultDto'
        '400':
          description: Invalid request (`BAD_REQUEST` or `INVALID_PARAMS`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentErrorResponseDto'
        '401':
          description: Missing, invalid, or non-secret partner key (`UNAUTHORIZED`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentErrorResponseDto'
        '403':
          description: >-
            Key or operation forbidden (`FORBIDDEN` or
            `RECIPIENT_NOT_ALLOWLISTED`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentErrorResponseDto'
        '422':
          description: >-
            Valid request cannot be fulfilled (`AMOUNT_OUT_OF_BOUNDS`,
            `PAYOUT_TOKEN_NOT_ALLOWED`, `INSUFFICIENT_LIQUIDITY`, or
            `OVER_DELIVERY_CAP`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentErrorResponseDto'
        '500':
          description: Unexpected server error (`INTERNAL_ERROR`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentErrorResponseDto'
        '502':
          description: Quote/provider failed (`NO_QUOTE_AVAILABLE` or `UPSTREAM_ERROR`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentErrorResponseDto'
      security:
        - bearer: []
components:
  schemas:
    CreateCheckoutDto:
      type: object
      properties:
        chain:
          type: number
          example: 8453
          description: Destination chain id — where the recipient is paid.
        token:
          type: string
          example: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
          description: Destination token address on `chain`.
        amount:
          type: string
          example: '10000000'
          description: >-
            Amount in BASE UNITS, as a string (10 USDC at 6 decimals is
            "10000000"). A string because these exceed IEEE-754 safe range at 18
            decimals. Omit for an OPEN amount — the payer names it — which is
            the normal shape for `deposit` and legal for `withdrawal`; a
            `checkout` almost always fixes it.
        recipient:
          type: string
          example: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
          description: Address that receives the funds on the destination chain.
        destinations:
          description: >-
            Alternative destinations offered to the payer. Mutually exclusive
            with top-level chain/token/recipient/amount/minAmount/maxAmount. One
            entry takes the legacy single-session path; two or more require
            payer selection.
          type: array
          items:
            $ref: '#/components/schemas/CreateDestinationCandidateDto'
        orderId:
          type: string
          example: order_1029
          description: >-
            Your identifier for this payment, and the IDEMPOTENCY key. Creating
            twice with the same orderId returns the existing non-terminal
            session with a 200 instead of a 201, rather than charging the payer
            twice. Send one, and send the same one on retry.
        metadata:
          type: object
          additionalProperties: true
          description: >-
            Arbitrary JSON echoed back on reads and webhooks. Never shown to the
            payer.
        successUrl:
          type: string
          description: Where to send the payer after a completed payment.
        cancelUrl:
          type: string
          description: Where to send the payer if they abandon the payment.
        minAmount:
          type: string
          description: >-
            Lower bound for an OPEN-amount session, base units. Ignored when
            `amount` is fixed.
        maxAmount:
          type: string
          description: >-
            Upper bound for an OPEN-amount session, base units. Ignored when
            `amount` is fixed.
        expiresIn:
          type: number
          example: 1800
          description: >-
            Session lifetime in seconds. Defaults to the server's configured
            TTL.
      required:
        - orderId
    ApiEnvelope:
      type: object
      properties:
        traceId:
          type: string
          description: W3C trace id of the request — correlate with logs/traces in SigNoz.
          example: 4bf92f3577b34da6a3ce929d0e0e4736
        code:
          type: string
          enum:
            - OK
            - BAD_REQUEST
            - UNAUTHORIZED
            - FORBIDDEN
            - NOT_FOUND
            - CONFLICT
            - RATE_LIMITED
            - PAYLOAD_TOO_LARGE
            - UNSUPPORTED_CHAIN
            - INTERNAL_ERROR
            - UPSTREAM_TIMEOUT
            - UPSTREAM_ERROR
            - SERVICE_UNAVAILABLE
            - KILL_SWITCH_ACTIVE
            - CIRCUIT_BREAKER_OPEN
            - NO_QUOTE_AVAILABLE
            - QUOTE_STALE
            - SIMULATION_REVERTED
            - INVALID_PARAMS
            - AMOUNT_OUT_OF_BOUNDS
            - PAYOUT_TOKEN_NOT_ALLOWED
            - RECIPIENT_NOT_ALLOWLISTED
            - PAYMENT_EXPIRED
            - PAYMENT_NOT_FOUND
            - NOT_CONFIGURED
            - INSUFFICIENT_LIQUIDITY
            - ROUTE_TEMPORARILY_UNAVAILABLE
            - UNSUPPORTED_ROUTE
            - OVER_DELIVERY_CAP
          description: >-
            Domain error code. `OK` on success; non-OK values come with a
            non-null `error`.
          example: OK
        error:
          type:
            - string
            - 'null'
          description: Human-readable error message. `null` on success.
          example: null
        data:
          type:
            - object
            - 'null'
          description: Endpoint-specific payload. `null` on error.
      required:
        - traceId
        - code
        - error
        - data
    PaymentCreateResultDto:
      type: object
      properties:
        id:
          type: string
          example: co_01JABC123
          description: >-
            Hypermid session id. Store it — it is the id every webhook and
            status read uses.
        url:
          type: string
          example: https://pay.hypermid.io/pay/co_01JABC123
          description: >-
            Hosted payment page. REDIRECT the payer here. It is deliberately not
            framable (`X-Frame-Options: DENY`) as anti-clickjacking — to embed,
            use `embedUrl`.
        embedUrl:
          type: string
          example: https://pay.hypermid.io/embed?paymentId=co_01JABC123
          description: >-
            The same session on the EMBEDDABLE surface, served with no framing
            headers. This is the one to put in an iframe and the one
            `createParentBridge` expects.
        status:
          type: string
          example: created
          description: >-
            Session state at creation. See the session lifecycle for the full
            set.
        mode:
          type: string
          enum:
            - checkout
            - deposit
            - withdrawal
          example: checkout
          description: >-
            Which product this session is. Echoed back so a generic handler need
            not remember which endpoint it called.
        expiresAt:
          type: string
          format: date-time
          description: >-
            When this session stops accepting payment (ISO 8601). After this the
            payer must start a new session.
        created:
          type: boolean
          description: >-
            True for a new or revived session; false for an idempotent replay of
            an existing one. A false here with a 200 means your retry was
            deduplicated rather than charging twice.
      required:
        - id
        - url
        - embedUrl
        - status
        - mode
        - expiresAt
        - created
    PaymentErrorResponseDto:
      type: object
      properties:
        traceId:
          type: string
          example: 4bf92f3577b34da6a3ce929d0e0e4736
          description: >-
            Correlation id for this request. Quote it in any support message —
            it is how we find your call in our logs.
        code:
          type: string
          enum:
            - OK
            - BAD_REQUEST
            - UNAUTHORIZED
            - FORBIDDEN
            - NOT_FOUND
            - CONFLICT
            - RATE_LIMITED
            - PAYLOAD_TOO_LARGE
            - UNSUPPORTED_CHAIN
            - INTERNAL_ERROR
            - UPSTREAM_TIMEOUT
            - UPSTREAM_ERROR
            - SERVICE_UNAVAILABLE
            - KILL_SWITCH_ACTIVE
            - CIRCUIT_BREAKER_OPEN
            - NO_QUOTE_AVAILABLE
            - QUOTE_STALE
            - SIMULATION_REVERTED
            - INVALID_PARAMS
            - AMOUNT_OUT_OF_BOUNDS
            - PAYOUT_TOKEN_NOT_ALLOWED
            - RECIPIENT_NOT_ALLOWLISTED
            - PAYMENT_EXPIRED
            - PAYMENT_NOT_FOUND
            - NOT_CONFIGURED
            - INSUFFICIENT_LIQUIDITY
            - ROUTE_TEMPORARILY_UNAVAILABLE
            - UNSUPPORTED_ROUTE
            - OVER_DELIVERY_CAP
          example: INVALID_PARAMS
          description: >-
            Stable machine-readable error code. Branch on this, not on `error`,
            whose wording may change.
        error:
          type: string
          example: orderId is required
          description: >-
            Human-readable explanation. For logs and developers — not intended
            to be shown to a payer verbatim.
        data:
          type:
            - object
            - 'null'
          example: null
          description: >-
            Always null on an error. Present so success and error envelopes have
            the same shape.
      required:
        - traceId
        - code
        - error
        - data
    CreateDestinationCandidateDto:
      type: object
      properties:
        chain:
          type: string
          example: '9270000000000000'
          description: >-
            Destination chain id as a decimal string; never parse it through a
            JavaScript number.
        token:
          type: string
          description: Destination token identifier on `chain`.
        recipient:
          type: string
          description: Chain-specific address that receives this candidate's funds.
        amount:
          type: string
          description: >-
            Destination-token base units. Required and positive for checkout;
            omit for an open deposit.
        minAmount:
          type: string
          description: Open-deposit lower bound in this candidate token's base units.
        maxAmount:
          type: string
          description: Open-deposit upper bound in this candidate token's base units.
      required:
        - chain
        - token
        - recipient
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: API key
      type: http
      description: >-
        Secret partner API key (`sk_live_…` or `sk_test_…`). Required to create
        or manage payment sessions. Server-side only — it can move money, so it
        must never reach a browser bundle. The key's prefix also selects the
        environment: `sk_test_` is confined to testnets.

````