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

# Charge a payment instrument against an invoice

> Charges a payment instrument for all or part of the remaining balance. The returned allocation is `pending`: the invoice balance does not move until the processor reports a capture, so `amountPaid` and `status` in this response still reflect the pre-charge state. Idempotent by idempotency key per invoice — a replay returns the existing allocation without charging again.



## OpenAPI

````yaml /openapi.json post /invoices/{id}/payments
openapi: 3.0.0
info:
  title: PayGood Merchant API
  description: Server-to-server integration surface for merchant API keys.
  version: '1.0'
  contact: {}
servers:
  - url: https://api-sandbox.paygood.co
    description: Sandbox
  - url: https://api.paygood.co
    description: Production
security: []
paths:
  /invoices/{id}/payments:
    post:
      tags:
        - invoices
      summary: Charge a payment instrument against an invoice
      description: >-
        Charges a payment instrument for all or part of the remaining balance.
        The returned allocation is `pending`: the invoice balance does not move
        until the processor reports a capture, so `amountPaid` and `status` in
        this response still reflect the pre-charge state. Idempotent by
        idempotency key per invoice — a replay returns the existing allocation
        without charging again.
      operationId: InvoicesController_charge
      parameters:
        - name: id
          required: true
          in: path
          description: Invoice TypeID (`inv_...`) to charge.
          schema:
            example: inv_01hxy8m1nqk9g3x3y3p0azq2va
            type: string
      requestBody:
        required: true
        description: >-
          Charge payload with idempotency key, merchant scope, payment
          instrument, and optional partial amount.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChargeInvoiceDto'
            examples:
              chargeFullBalance:
                summary: Charge the full remaining balance
                value:
                  idempotencyKey: idem-inv-charge-01
                  merchantId: mer_01hxy8m1nqk9g3x3y3p0azq2bg
                  paymentInstrumentId: pi_01hxy8m1nqk9g3x3y3p0azq2p1
              chargePartialAmount:
                summary: Charge a partial amount
                value:
                  idempotencyKey: idem-inv-charge-02
                  merchantId: mer_01hxy8m1nqk9g3x3y3p0azq2bg
                  paymentInstrumentId: pi_01hxy8m1nqk9g3x3y3p0azq2p1
                  amount: 20000
      responses:
        '201':
          description: >-
            Charge accepted. Returns the invoice plus the newly created
            `pending` allocation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoicePaymentResultDto'
        '400':
          description: >-
            Validation failed, invoice is not `issued` or `partially_paid`,
            amount exceeds the remaining balance, or the payment instrument is
            inactive or belongs to another customer.
        '401':
          description: Missing or invalid authentication credentials.
        '403':
          description: >-
            Authenticated principal lacks `invoices.update` capability or
            merchant scope.
        '404':
          description: >-
            Invoice was not found for the provided merchant scope, or the
            payment instrument does not exist.
      security:
        - bearer: []
components:
  schemas:
    ChargeInvoiceDto:
      type: object
      properties:
        idempotencyKey:
          type: string
          minLength: 1
          description: Idempotency key for safe retries of the charge per invoice.
        merchantId:
          type: string
          description: Merchant TypeID (`mer_...`) used for authorization scope.
        paymentInstrumentId:
          type: string
          description: >-
            Payment instrument TypeID (`pi_...`) to charge. Must belong to the
            invoice's customer and be active.
        amount:
          description: >-
            Minor-unit amount to charge. Defaults to the full remaining balance.
            Must not exceed it.
          type: integer
          exclusiveMinimum: true
          maximum: 9007199254740991
          minimum: 0
      required:
        - idempotencyKey
        - merchantId
        - paymentInstrumentId
    InvoicePaymentResultDto:
      type: object
      properties:
        invoice:
          type: object
          properties:
            invoiceId:
              type: string
            invoiceNumber:
              type: string
              minLength: 1
            invoiceUrlSlug:
              type: string
              minLength: 1
              description: >-
                Secret pay-link token. Anyone holding this value can view and
                pay the invoice anonymously, so treat it like a credential: safe
                to send to the customer, never safe to log or expose publicly.
                Unguessable and unrelated to `invoiceId`, so it can be rotated
                without changing the invoice.
            idempotencyKey:
              type: string
              minLength: 1
            merchantId:
              type: string
            customerId:
              type: string
            currentRevisionNumber:
              type: integer
              exclusiveMinimum: true
              maximum: 9007199254740991
              minimum: 0
            status:
              type: string
              enum:
                - draft
                - issued
                - partially_paid
                - paid
                - void
            currency:
              description: Supported currency code (USD, CAD)
              type: string
              minLength: 3
              maxLength: 3
            lineItems:
              type: array
              items:
                oneOf:
                  - type: object
                    properties:
                      kind:
                        type: string
                        enum:
                          - product_charge
                      productId:
                        type: string
                      priceId:
                        type: string
                      description:
                        type: string
                        minLength: 1
                        maxLength: 500
                      quantity:
                        type: integer
                        exclusiveMinimum: true
                        maximum: 9007199254740991
                        minimum: 0
                      unitAmount:
                        type: integer
                        minimum: 0
                        maximum: 9007199254740991
                      lineTotal:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                    required:
                      - kind
                      - productId
                      - description
                      - quantity
                      - unitAmount
                      - lineTotal
                    additionalProperties: false
                  - type: object
                    properties:
                      kind:
                        type: string
                        enum:
                          - manual_adjustment
                      description:
                        type: string
                        minLength: 1
                        maxLength: 500
                      amount:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                      quantity:
                        type: integer
                        exclusiveMinimum: true
                        maximum: 9007199254740991
                        minimum: 0
                      lineTotal:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                    required:
                      - kind
                      - description
                      - amount
                      - quantity
                      - lineTotal
                    additionalProperties: false
            productTotal:
              type: object
              properties:
                amount:
                  type: integer
                  exclusiveMinimum: true
                  maximum: 9007199254740991
                  minimum: 0
                currency:
                  description: Supported currency code (USD, CAD)
                  type: string
                  minLength: 3
                  maxLength: 3
              required:
                - amount
                - currency
            total:
              type: object
              properties:
                amount:
                  type: integer
                  exclusiveMinimum: true
                  maximum: 9007199254740991
                  minimum: 0
                currency:
                  description: Supported currency code (USD, CAD)
                  type: string
                  minLength: 3
                  maxLength: 3
              required:
                - amount
                - currency
            amountPaid:
              type: object
              properties:
                amount:
                  type: integer
                  exclusiveMinimum: true
                  maximum: 9007199254740991
                  minimum: 0
                currency:
                  description: Supported currency code (USD, CAD)
                  type: string
                  minLength: 3
                  maxLength: 3
              required:
                - amount
                - currency
              description: >-
                Sum of applied payment allocations, both processed and
                out-of-band.
            amountRemaining:
              type: object
              properties:
                amount:
                  type: integer
                  exclusiveMinimum: true
                  maximum: 9007199254740991
                  minimum: 0
                currency:
                  description: Supported currency code (USD, CAD)
                  type: string
                  minLength: 3
                  maxLength: 3
              required:
                - amount
                - currency
              description: >-
                Computed as `total` minus `amountPaid`. Zero when the invoice is
                fully paid.
            dueDate:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            paidAt:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            notes:
              type: string
            metadata:
              type: object
              additionalProperties: {}
            createdAt:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            updatedAt:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          required:
            - invoiceId
            - invoiceNumber
            - invoiceUrlSlug
            - idempotencyKey
            - merchantId
            - customerId
            - currentRevisionNumber
            - status
            - currency
            - lineItems
            - productTotal
            - total
            - amountPaid
            - amountRemaining
            - createdAt
            - updatedAt
        allocation:
          type: object
          properties:
            allocationId:
              type: string
            invoiceId:
              type: string
            kind:
              type: string
              enum:
                - payment
                - out_of_band
            status:
              type: string
              enum:
                - pending
                - applied
                - canceled
                - reversed
            amount:
              type: object
              properties:
                amount:
                  type: integer
                  exclusiveMinimum: true
                  maximum: 9007199254740991
                  minimum: 0
                currency:
                  description: Supported currency code (USD, CAD)
                  type: string
                  minLength: 3
                  maxLength: 3
              required:
                - amount
                - currency
            paymentId:
              description: Present only for `payment` allocations.
              type: string
            method:
              description: Present only for `out_of_band` allocations.
              type: string
              enum:
                - cash
                - check
                - bank_transfer
                - wire
                - zelle
                - venmo
                - cash_app
                - paypal
                - other
            reference:
              type: string
            recordedBy:
              description: >-
                Who recorded an out-of-band payment, snapshotted at write time.
                Deliberately omits the raw principal id.
              type: object
              properties:
                principalType:
                  type: string
                  enum:
                    - member
                    - operator
                    - api_key
                display:
                  type: string
              required:
                - principalType
            effectiveAt:
              description: >-
                When the money arrived, per the processor for `payment` rows and
                per the merchant for `out_of_band` rows. Null while a payment
                allocation is still pending.
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            createdAt:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            appliedAt:
              description: When PayGood credited the amount to the invoice balance.
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            canceledAt:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
            reversedAt:
              type: string
              format: date-time
              pattern: >-
                ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z))$
          required:
            - allocationId
            - invoiceId
            - kind
            - status
            - amount
            - createdAt
      required:
        - invoice
        - allocation
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: merchant_<prefix>_<secret>
      type: http
      description: >-
        Merchant API key bearer token. Legacy wire prefixes `api_key_` and
        `api_` are also accepted.

````