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

# Create a checkout session

> Resolve the amount, apply the merchant's payment policy, and return the transfer target when payment is required.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/create_checkout
openapi: 3.1.0
info:
  title: Ringup API
  version: v1
  description: >-
    Take a card payment on a phone call. Every endpoint is authenticated with a
    Bearer API key; the key prefix (`rk_test_` / `rk_live_`) selects the
    environment.
servers:
  - url: https://api.ringup.dev
security: []
paths:
  /v1/create_checkout:
    post:
      summary: Create a checkout session
      description: >-
        Resolve the amount, apply the merchant's payment policy, and return the
        transfer target when payment is required.
      operationId: createCheckout
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCheckoutRequest'
            example:
              merchant_number: '+14155550100'
              caller_phone: '+14155550142'
              order_id: 8QK4M2XJ
              platform_call_id: call_7c2a91e4
              return_to: https://example.com/calls/7c2a91e4
              success_message: You're all set. Your order will be ready in about ten minutes.
              failure_message: That card did not go through. I can text you a link instead.
              metadata:
                ticket: '4821'
      responses:
        '201':
          description: Success.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateCheckoutResponse'
              example:
                checkout_session_id: cs_test_453b5401286d0f80
                merchant_id: mch_4f2c9a1b7e3d
                agent_message: Payment is ready. Transferring the caller now.
                payment_required: required
                amount_cents: 1650
                currency: USD
                amount_source: order
                transfer_to: >-
                  sip:eyJjIjoiKzE0MTU1NTUwMTQyIiwiYSI6MTY1MCwibSI6Im1jaF80ZjJjOWExYjdlM2QifQ.Xr7QpN2vK9sLd4TfA1mYc8BhE3wZ@transfer.ringup.dev
                transfer_to_number: '+16283364058'
                expires_at: '2026-07-21T18:34:12.000Z'
                cards:
                  - instrument_id: ins_9d21c7
                    brand: VISA
                    last_four: '5858'
                    expiry: 07/2028
                default_card_id: ins_9d21c7
                metadata:
                  ticket: '4821'
        '400':
          description: |-
            `invalid_json` The request body is not valid JSON.

            `missing_required_fields` A required parameter is missing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
              examples:
                invalid_json:
                  summary: The request body is not valid JSON.
                  value:
                    error:
                      type: invalid_request_error
                      code: invalid_json
                      audience: developer
                      message: The request body is not valid JSON.
                      advice_code: do_not_try_again
                      agent_message: null
                      display_message: null
                      agent_action: null
                      doc_url: >-
                        https://docs.ringup.dev/api-reference/error-codes#invalid_json
                      request_id: req_8f3c1d2ab4e9
                missing_required_fields:
                  summary: A required parameter is missing.
                  value:
                    error:
                      type: invalid_request_error
                      code: missing_required_fields
                      audience: developer
                      message: A required parameter is missing.
                      param: caller_phone
                      advice_code: do_not_try_again
                      agent_message: null
                      display_message: null
                      agent_action: null
                      doc_url: >-
                        https://docs.ringup.dev/api-reference/error-codes#missing_required_fields
                      request_id: req_8f3c1d2ab4e9
        '401':
          description: >-
            `invalid_key` The API key is missing, malformed, revoked, or does
            not match the mode of the resource.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
              examples:
                invalid_key:
                  summary: >-
                    The API key is missing, malformed, revoked, or does not
                    match the mode of the resource.
                  value:
                    error:
                      type: authentication_error
                      code: invalid_key
                      audience: developer
                      message: >-
                        The API key is missing, malformed, revoked, or does not
                        match the mode of the resource.
                      advice_code: do_not_try_again
                      agent_message: null
                      display_message: null
                      agent_action: null
                      doc_url: >-
                        https://docs.ringup.dev/api-reference/error-codes#invalid_key
                      request_id: req_8f3c1d2ab4e9
        '404':
          description: >-
            `merchant_not_found` No merchant with that id belongs to your
            account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
              examples:
                merchant_not_found:
                  summary: No merchant with that id belongs to your account.
                  value:
                    error:
                      type: invalid_request_error
                      code: merchant_not_found
                      audience: developer
                      message: No merchant with that id belongs to your account.
                      advice_code: do_not_try_again
                      agent_message: null
                      display_message: null
                      agent_action: null
                      doc_url: >-
                        https://docs.ringup.dev/api-reference/error-codes#merchant_not_found
                      request_id: req_8f3c1d2ab4e9
        '422':
          description: >-
            `order_lookup_unsupported` This processor cannot resolve an order
            total by reference.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
              examples:
                order_lookup_unsupported:
                  summary: This processor cannot resolve an order total by reference.
                  value:
                    error:
                      type: invalid_request_error
                      code: order_lookup_unsupported
                      audience: developer
                      message: >-
                        This processor cannot resolve an order total by
                        reference.
                      advice_code: do_not_try_again
                      agent_message: null
                      display_message: null
                      agent_action: null
                      doc_url: >-
                        https://docs.ringup.dev/api-reference/error-codes#order_lookup_unsupported
                      request_id: req_8f3c1d2ab4e9
        '424':
          description: >-
            `order_lookup_failed` The processor could not be reached to resolve
            the order total.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
              examples:
                order_lookup_failed:
                  summary: >-
                    The processor could not be reached to resolve the order
                    total.
                  value:
                    error:
                      type: processor_error
                      code: order_lookup_failed
                      audience: caller
                      message: >-
                        The processor could not be reached to resolve the order
                        total.
                      advice_code: try_again_later
                      agent_message: >-
                        I'm having trouble taking payment right now. Let me get
                        someone to help you.
                      display_message: >-
                        I'm having trouble taking payment right now. Let me get
                        someone to help you.
                      agent_action: null
                      doc_url: >-
                        https://docs.ringup.dev/api-reference/error-codes#order_lookup_failed
                      request_id: req_8f3c1d2ab4e9
      security:
        - bearerAuth: []
components:
  schemas:
    CreateCheckoutRequest:
      additionalProperties: false
      properties:
        amount_cents:
          description: >-
            Required only when there is no `order_id`. Never trusted over an
            order.
          type: number
        caller_phone:
          type: string
        currency:
          type: string
        failure_message:
          description: Spoken after a failed one.
          type: string
        merchant_id:
          description: >-
            The merchant, when the caller knows it (a developer integrating over
            REST).
          type: string
        merchant_number:
          description: >-
            The merchant's own dialed number, when the caller knows the CALL but
            not the merchant (the transfer tool). Resolved to a merchant within
            the authed vendor; an unregistered number is an inaudible `none`,
            not an error (R13c-ii).
          type: string
        metadata:
          additionalProperties:
            type: string
          description: >-
            Your own key/value pairs. Opaque to Ringup: stored, echoed, never
            interpreted.
          type: object
        order_id:
          description: The merchant's POS order. THE amount authority when present.
          type: string
        platform_call_id:
          description: >-
            The voice platform's id for this call. Functional, not metadata: we
            call the platform with it to verify caller attestation. Recommended.
          type: string
        return_to:
          description: Where to send the caller back after payment.
          type: string
        success_message:
          description: Spoken after a successful payment.
          type: string
      required:
        - caller_phone
      type: object
    CreateCheckoutResponse:
      additionalProperties: false
      properties:
        agent_message:
          description: >-
            The one line a voice agent should say for this outcome, so the
            transfer tool never invents copy: "no payment is needed",
            "transferring you now", or "payment is unavailable" all come from
            here (R13c-ii). Errors carry the same field under
            `error.agent_message`.
          type: string
        amount_cents:
          description: >-
            What we RESOLVED. Under the order model the total is derived, so we
            must return it.
          type: number
        amount_source:
          description: Where the total came from, so a derived amount is visibly derived.
          enum:
            - order
            - request
          type: string
        cards:
          description: >-
            Cards chargeable AT THIS MERCHANT, newest first. Handle-aware, not
            merely silo-aware: a Clover card enrolled at merchant A has no
            charge handle at merchant B, and offering it would fail at charge
            after the caller had already agreed to it. Empty means text a link.
          items:
            $ref: '#/components/schemas/SavedCard'
          type: array
        checkout_session_id:
          type: string
        currency:
          type: string
        default_card_id:
          type:
            - string
            - 'null'
        expires_at:
          type: string
        merchant_id:
          description: >-
            The merchant this resolved to, echoed back. Useful when the caller
            passed a `merchant_number` and wants to know which merchant it
            matched; empty string when no merchant resolved (an inaudible
            `none`, R13c-ii).
          type: string
        metadata:
          anyOf:
            - additionalProperties:
                type: string
              type: object
            - type: 'null'
        payment_required:
          $ref: '#/components/schemas/PaymentRequired'
        transfer_to:
          description: >-
            Null unless payment is required. Nothing to transfer to means do not
            transfer.
          type:
            - string
            - 'null'
        transfer_to_number:
          description: >-
            The same hand-off as a plain phone number, for platforms that can
            only transfer calls to a number. The call arrives without the token
            and the payment line resolves the session by the caller's number.
            Prefer `transfer_to` when the platform can dial a SIP URI.
          type:
            - string
            - 'null'
      type: object
    ApiErrorBody:
      additionalProperties: false
      description: >-
        THE error object. Identical on every endpoint: provisioning, identify,
        checkout, cards, charge. A failed charge (which arrives as a 200 with
        `status: "failed"`) carries the SAME fields under `failure`, so a
        developer writes one parser and it works everywhere.
      properties:
        error:
          additionalProperties: false
          properties:
            advice_code:
              $ref: '#/components/schemas/AdviceCode'
              description: try_again_later | confirm_card_data | do_not_try_again
            agent_action:
              anyOf:
                - $ref: '#/components/schemas/AgentAction'
                - type: 'null'
              description: 'Null on every `developer`-audience error: see agent_message.'
            agent_message:
              description: >-
                Speak verbatim WHEN NON-NULL. Null on every `developer`-audience
                error.
              type:
                - string
                - 'null'
            audience:
              $ref: '#/components/schemas/Audience'
              description: >-
                Who this error is for. Drives whether there is anything to speak
                at all.
            charge:
              description: Present when the error concerns a specific charge.
              type: string
            code:
              $ref: '#/components/schemas/ErrorCode'
            decline_code:
              type: string
            display_message:
              description: >-
                The same fact written for a screen. Null on `developer`-audience
                errors.
              type:
                - string
                - 'null'
            doc_url:
              type: string
            message:
              type: string
            param:
              type: string
            processor_code:
              type: string
            request_id:
              type: string
            request_log_url:
              description: >-
                Deep link to this request in the dashboard. Present once the
                dashboard log view exists.
              type: string
            type:
              $ref: '#/components/schemas/ErrorType'
          type: object
      type: object
    SavedCard:
      additionalProperties: false
      properties:
        brand:
          type: string
        expiry:
          type: string
        instrument_id:
          description: The value `charge` requires.
          type: string
        last_four:
          type: string
      type: object
    PaymentRequired:
      enum:
        - required
        - optional
        - none
      type: string
    AdviceCode:
      description: >-
        `advice_code` is our guidance to the developer on what to do with this
        decline programmatically. It is distinct from `agent_action`, which
        drives the conversation. A decline can be "do not retry this card"
        (advice) while still being "offer a different card" (agent action).
      enum:
        - try_again_later
        - do_not_try_again
        - confirm_card_data
      type: string
    AgentAction:
      description: >-
        What the agent should DO next. Keeps conversational branching
        deterministic too.
      enum:
        - retry_card
        - offer_different_card
        - send_link
        - end_call
        - escalate
      type: string
    Audience:
      description: >-
        Who an error is for.


        `caller` errors are things the person on the phone is living through, so
        they carry copy your agent can speak. `developer` errors are your
        integration's own bugs, and carry NO speakable copy at all: the fields
        are null rather than a neutral filler, because a filler sentence invites
        an agent to raise payment when nothing about payment has failed.
      enum:
        - developer
        - caller
      type: string
    ErrorCode:
      enum:
        - invalid_json
        - missing_required_fields
        - invalid_value
        - invalid_key
        - vendor_not_provisioned
        - merchant_not_found
        - merchant_not_connected
        - invalid_processor
        - invalid_credentials
        - invalid_payment_policy
        - invalid_payment_policy_amount_cents
        - session_not_found
        - session_expired
        - session_create_failed
        - session_missing_consumer
        - missing_checkout_session_id
        - order_lookup_failed
        - order_lookup_unsupported
        - instrument_not_found
        - instrument_not_authorized
        - missing_instrument_fields
        - processor_mismatch
        - needs_enrollment
        - charge_details_mismatch
        - card_save_failed
        - card_declined
        - processor_unavailable
        - merchant_credentials_invalid
        - invalid_vault
        - key_not_found
        - invalid_environment
        - invalid_url
        - invalid_events
        - invalid_ttl
        - invalid_state_key
        - not_found
        - not_configured
        - rate_limit
        - internal_error
      type: string
    ErrorType:
      enum:
        - invalid_request_error
        - authentication_error
        - permission_error
        - card_error
        - processor_error
        - idempotency_error
        - rate_limit_error
        - api_error
      type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: rk_live_…

````