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

# Pay an invoice at checkout

> Creates a charge on an open invoice using the method the payer picked (`pix`, `boleto`, `card` or `crypto`). The response carries what the payer needs to finish, such as the Pix QR code. Confirmation comes later: poll the payment status or wait for the `payment.confirmed` webhook.




## OpenAPI

````yaml /api-reference/openapi.en.json post /pay/{slug}/invoices/{invoiceID}/charge
openapi: 3.1.0
info:
  title: Infi API
  version: 0.0.1
  description: >
    The Infi REST API: catalog, customers, usage metering, subscriptions,

    invoices, payments and checkout.


    **Authentication.** Send your secret key as `Authorization: Bearer
    sk_test_…`

    (sandbox) or `sk_live_…` (production). The key prefix selects the
    environment.

    Checkout routes (`/pay/*`) and `/public/*` take no key: they run in the

    payer's browser.


    **Idempotency.** Every request that changes data requires an

    `Idempotency-Key` header. A retry with the same key returns the original

    response instead of running again.


    **Amounts.** Money and quantities travel as decimal strings (`"150.00"`,

    `"0.0001"`), never as floating-point numbers.


    **Errors.** The body carries `error_code` (stable, branch on it), `message`

    (for humans) and `tracer_id` (send it to support). Rate-limit and
    idempotency

    errors are nested under `error`, with `code` and `request_id`.
servers:
  - url: https://api-sandbox.beinfi.com
    description: Sandbox
  - url: https://api.beinfi.com
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Catalog
  - name: Customers
  - name: Metering
  - name: Subscriptions
  - name: Invoices
  - name: Payments
  - name: Checkout
  - name: Coupons
  - name: Billing
  - name: Account
  - name: Webhooks
  - name: Test account
  - name: Rail
  - name: Storefronts
paths:
  /pay/{slug}/invoices/{invoiceID}/charge:
    post:
      tags:
        - Checkout
      summary: Pay an invoice at checkout
      description: >
        Creates a charge on an open invoice using the method the payer picked
        (`pix`, `boleto`, `card` or `crypto`). The response carries what the
        payer needs to finish, such as the Pix QR code. Confirmation comes
        later: poll the payment status or wait for the `payment.confirmed`
        webhook.
      operationId: chargeCheckoutInvoice
      parameters:
        - name: slug
          in: path
          required: true
          schema:
            type: string
          description: Your account's public identifier, as in checkout URLs.
        - name: invoiceID
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Invoice ID.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckoutChargeRequest'
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Payment'
          description: The created charge.
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConflictError'
          description: >
            The invoice is not open (`invoice_not_open`), a charge is already in
            progress on it (`charge_in_progress`), the previous charge is
            already being processed and cannot be switched to another method
            (`charge_already_processing` — wait for it to finish), or the
            account's card setup is incomplete (`client_key_missing`).
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
          description: >
            Something the caller can fix. Besides `validation_failed`:
            `customer_tax_id_required` (Pix and boleto need the payer's
            CPF/CNPJ) and `amount_below_minimum` (in BRL, a charge under R$ 5.00
            may be refused; the minimum that applies to this charge is in
            `errors[]`, under `amount`; a deep coupon discount can cause this).
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: >-
            The charge could not be created right now, or the previous attempt
            could not be released to switch methods. Nothing was charged; retry.
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security: []
components:
  schemas:
    CheckoutChargeRequest:
      type: object
      required:
        - method
      properties:
        method:
          type: string
          enum:
            - pix
            - boleto
            - card
            - crypto
          description: Payment method.
        card:
          $ref: '#/components/schemas/CheckoutCardInput'
          description: >-
            Card details. Required when `method` is `card` on an embedded
            checkout.
        saveInstrument:
          type: boolean
          description: >-
            The payer chose to save the card for future automatic charges.
            Requires `consentTextVersion`; without it, returns 422.
        consentTextVersion:
          type: string
          description: >-
            The version of the authorization text the payer saw: echo
            `CheckoutSession.mandate.version`. Required with `saveInstrument`.
        surface:
          type: string
          enum:
            - hosted
            - embed
          default: hosted
          description: >-
            Which Infi checkout the payer is on. It sets where the browser
            returns after a bank verification. Use `embed` from an embedded
            (iframe) checkout; without it, `hosted` applies and the payer leaves
            the iframe for the full page.
      description: The method the payer picked. A missing or unknown `method` returns 422.
    Payment:
      type: object
      properties:
        id:
          type: string
          format: uuid
        invoiceId:
          type: string
          format: uuid
        provider:
          type: string
          description: The processor the charge ran through. In sandbox, `sandbox`.
        providerId:
          type:
            - string
            - 'null'
          description: The charge's reference at the processor, useful for support.
        method:
          type: string
          enum:
            - pix
            - boleto
            - card
            - crypto
        amount:
          type: string
          description: Amount charged, as a decimal string.
        currency:
          type: string
        status:
          type: string
          enum:
            - pending
            - confirmed
            - failed
            - refunded
            - charged_back
          description: >-
            `pending` awaits payment; `confirmed` was paid; `failed` was not
            paid (see `failureCode`); `refunded` was fully refunded;
            `charged_back` was disputed by the buyer with their bank.
        refundedAmount:
          type: string
          description: >-
            Total refunded so far, as a decimal string. Absent when nothing was
            refunded. A partial refund keeps `status` at `confirmed`; only
            refunding the full amount sets `refunded`. Use this field, not
            `status`, to know how much went back.
        failureCode:
          type:
            - string
            - 'null'
          enum:
            - insufficient_funds
            - do_not_honor
            - card_declined
            - authentication_required
            - card_expired
            - card_stolen
            - card_invalid
            - mandate_revoked
            - mandate_refused
            - brand_changed
            - provider_error
            - provider_timeout
            - superseded
            - null
          description: >-
            Why the charge failed. `superseded` is not a decline: the buyer
            switched payment method to pay the same invoice. Null when the
            payment did not fail or when no reason was recorded. New codes may
            appear; treat an unknown value as a generic failure.
        failedAt:
          type:
            - string
            - 'null'
          format: date-time
          description: When the charge moved to `failed`.
        createdAt:
          type: string
          format: date-time
        payer:
          type:
            - object
            - 'null'
          properties:
            id:
              type: string
              format: uuid
            name:
              type:
                - string
                - 'null'
            email:
              type:
                - string
                - 'null'
          description: >-
            Who paid. On a one-off invoice, `id` is the customer ID; on a
            subscription invoice, it is the ID of the customer's enrollment in
            the product. Present only on `GET /billing/payments` and `GET
            /billing/payments/{paymentID}`, and null when the invoice does not
            identify the customer.
        invoiceUrl:
          type: string
          description: Hosted payment page. Present only on the charge-creation response.
        chargeToken:
          type: string
          description: >-
            Single-use token for the crypto payment widget. Present only on a
            crypto charge response.
        network:
          type: string
          enum:
            - main
            - test
          description: 'Crypto widget environment for this charge: `main` (real) or `test`.'
        settlementAsset:
          type: string
          enum:
            - USDC
          description: Asset the crypto charge settles in.
        settlementNetwork:
          type: string
          enum:
            - base
            - solana
          description: Network the crypto charge settles on.
        pixPayload:
          type: string
          description: >-
            Pix copy-and-paste code. Render the QR from it. Still available on
            later reads of the payment.
        pixQrImage:
          type: string
          description: >-
            The Pix QR as a base64 PNG (no `data:` prefix), if you would rather
            not render it yourself.
        providerPixPayload:
          type: string
          description: >-
            Sandbox only: the Pix code the test processor generated, for
            inspection. Not payable. In sandbox, `pixPayload` carries the test
            confirmation link.
        sandboxConfirmUrl:
          type: string
          description: >-
            Sandbox only: a page that marks this charge as paid without real
            money. Branch on whether this field is present, not on the shape of
            `pixPayload`. You do not need it to render: `pixPayload` is a QR in
            both environments.
        pixExpiresAt:
          type:
            - string
            - 'null'
          format: date-time
          description: When the Pix code expires (Pix charges only).
        clientSecret:
          type: string
          description: >-
            Temporary secret to confirm a card charge in the browser. Present
            only on the charge-creation response.
        publishableKey:
          type: string
          description: >-
            Public key paired with `clientSecret`. Present only on the
            charge-creation response.
        nextAction:
          $ref: '#/components/schemas/PaymentNextAction'
          description: >-
            Data to complete a card charge in the browser. Present only on the
            charge-creation response.
        switchable:
          type: boolean
          description: >-
            Whether this charge can still be dropped so the same invoice is paid
            another way: `true` while `pending`, `false` once paid or failed.
            Present only on the charge-creation response; treat a missing value
            as `false`.
      description: >-
        One charge attempt against an invoice. An invoice can have several
        payments.
    ConflictError:
      type: object
      required:
        - message
        - error_code
        - tracer_id
        - resource
        - metadata
      properties:
        message:
          type: string
          description: Human-readable explanation.
        error_code:
          $ref: '#/components/schemas/ErrorCode'
          description: Stable error code. Branch on this field.
        tracer_id:
          type: string
          description: Request identifier. Send it to support.
        resource:
          type: string
          description: The kind of resource in conflict. Empty string when not applicable.
        metadata:
          type:
            - object
            - 'null'
          additionalProperties:
            type: string
          description: Conflict details, as key-value pairs. `null` when there are none.
      description: 'Body of a 409 error: the resource''s state does not allow the operation.'
    ValidationError:
      type: object
      required:
        - message
        - error_code
        - tracer_id
        - errors
      properties:
        message:
          type: string
        error_code:
          $ref: '#/components/schemas/ErrorCode'
        tracer_id:
          type: string
        errors:
          type: array
          items:
            type: object
            required:
              - field
              - value
              - constraint
              - description
            properties:
              field:
                type: string
              value:
                type: string
              constraint:
                type: string
              description:
                type: string
          description: >-
            Per-field detail (`field`, `description`). Always present on a
            `422`; may be empty.
      description: >-
        Body of a `422`. Same shape as `Error`, plus `errors[]` with per-field
        detail. That is where the sentence telling you what to fix lives (for
        example, "product has no published version").
    Error:
      type: object
      required:
        - message
        - error_code
        - tracer_id
      properties:
        message:
          type: string
          description: Human-readable sentence.
        error_code:
          $ref: '#/components/schemas/ErrorCode'
          description: Stable error code. Branch on it.
        tracer_id:
          type: string
          description: Request id. Include it when contacting support.
      description: >-
        The standard error body. It is flat (no `error` wrapper) and the trace
        id is `tracer_id`.
    CheckoutCardInput:
      type: object
      required:
        - number
        - holderName
        - expiryMonth
        - expiryYear
        - ccv
        - holderEmail
        - holderCpfCnpj
        - holderPostalCode
        - holderAddressNumber
      properties:
        number:
          type: string
        holderName:
          type: string
        expiryMonth:
          type: string
          example: '12'
        expiryYear:
          type: string
          example: '2030'
        ccv:
          type: string
          description: Card security code.
        holderEmail:
          type: string
          format: email
        holderCpfCnpj:
          type: string
          description: Cardholder CPF or CNPJ.
        holderPostalCode:
          type: string
          description: Cardholder postal code.
        holderAddressNumber:
          type: string
          description: Cardholder street number.
        holderPhone:
          type: string
      description: >-
        Card and holder details for a card charge on an embedded checkout. Sent
        over a secure connection; the card number and security code are never
        stored by Infi. All fields are required.
    PaymentNextAction:
      oneOf:
        - $ref: '#/components/schemas/CardSessionAction'
        - $ref: '#/components/schemas/CardPaymentAction'
      discriminator:
        propertyName: type
        mapping:
          adyen_session:
            $ref: '#/components/schemas/CardSessionAction'
          stripe_payment_intent:
            $ref: '#/components/schemas/CardPaymentAction'
      description: >-
        Temporary data for the browser to complete the charge. Branch on `type`.
        Use it only in the same session; do not reuse it or accept these values
        back from the browser.
    NotFoundError:
      type: object
      required:
        - message
        - error_code
        - tracer_id
        - resource
      properties:
        message:
          type: string
        error_code:
          $ref: '#/components/schemas/ErrorCode'
        tracer_id:
          type: string
        resource:
          type: string
    ErrorCode:
      type: string
      examples:
        - internal_error
        - validation_failed
        - bad_request
        - unauthorized
        - forbidden
        - not_found
        - conflict
        - rate_limited
      description: >-
        Stable error code. The list is open: besides the generic codes, each
        area defines its own (`coupon_expired`, `insufficient_balance`,
        `version_not_draft`, `idempotency_key_reused`…). Handle a code you do
        not recognize by its HTTP status and show `message`; do not fail parsing
        the response.
    RequestError:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            message:
              type: string
            request_id:
              type: string
    CardSessionAction:
      type: object
      additionalProperties: false
      required:
        - type
        - session
        - clientKey
        - environment
        - countryCode
        - locale
        - amount
      properties:
        type:
          type: string
          const: adyen_session
        session:
          type: object
          additionalProperties: false
          required:
            - id
            - sessionData
          properties:
            id:
              type: string
            sessionData:
              type: string
          description: Checkout session to open in the browser. Do not store or log it.
        clientKey:
          type: string
          description: Public key, safe for the browser.
        environment:
          type: string
          enum:
            - live
            - live-us
            - live-au
            - live-nea
            - live-in
          description: Environment the form must load in.
        countryCode:
          type: string
          const: BR
        locale:
          type: string
          const: pt-BR
        amount:
          $ref: '#/components/schemas/ClientActionAmount'
          description: Charge amount.
      description: Payment session for the in-browser card form.
    CardPaymentAction:
      type: object
      additionalProperties: false
      required:
        - type
        - clientSecret
        - publishableKey
      properties:
        type:
          type: string
          const: stripe_payment_intent
        clientSecret:
          type: string
          description: Temporary secret to confirm the charge in the browser.
        publishableKey:
          type: string
          description: Public key, safe for the browser.
      description: Data to confirm the card charge in the browser.
    ClientActionAmount:
      type: object
      additionalProperties: false
      required:
        - value
        - currency
      properties:
        value:
          type: integer
          format: int64
          minimum: 0
          description: Amount in the currency's minor unit (cents, for BRL).
        currency:
          type: string
          example: BRL
  responses:
    BadRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Malformed request.
    NotFound:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/NotFoundError'
      description: Resource not found.
    RateLimited:
      headers:
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RequestError'
      description: Rate limit exceeded. `Retry-After` gives the wait in seconds.
    ServiceUnavailable:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      description: Temporarily unavailable. Retry shortly.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your account's secret key: `Authorization: Bearer sk_test_…` or
        `sk_live_…`. Server-side only.

````