[MX] Payment Invoice (Complemento de Pago)

What is a Payment Invoice?

A Complemento de Pago is a CFDI that records the actual receipt of payment for a previously issued invoice. It is required by SAT when the original invoice was issued with payment_method = PPD (Pago en Parcialidades o Diferido) — meaning payment was deferred or split.

You do not issue a Complemento de Pago for invoices paid at the time of issuance (PUE — Pago en Una Sola Exhibición).

FieldValue
invoice_typepayment
document_typepayment invoice
e_invoicetrue
currencyMXN

Two Modes

Brinta supports two modes. You don't declare the mode explicitly — Brinta detects it automatically based on the fields present in your payload.

Mode A — You calculate everything

You send all tax totals, payment amounts, and balance tracking. Brinta stamps the document without recalculating anything.

Use when: your system already tracks invoice balances and can produce the exact tax breakdown per payment event.

What you need to send: root-level amounts[], root-level taxes[], and the full nested relations[].relations[] structure.

Mode B — Brinta calculates

You only send the original invoice ID and how much was paid. Brinta fetches the original invoice and calculates everything.

Use when: the original invoice was issued through Brinta and you don't want to manage balance tracking yourself.

What you need to send: original_invoice_id + paid_amount at root level. No relations needed.


Mode A — Field by Field

Root Level

fiscal_status

SAT field c_ObjetoImp. Indicates whether the payment is subject to tax.

ValueMeaningWhen to use
01Not subject to taxThe payment is not taxable (e.g. exempt operations).
02Taxable objectStandard value for Complemento de Pago. Use this in almost all cases.
03Taxable object, not obligated to break down taxSpecial cases only — consult your tax advisor.

payment_method.type

The form of payment used. SAT uses this to classify the payment in the CFDI.

  • bank transfer — wire transfer / SPEI
  • cash — physical cash
  • credit card / debit card — card payments
  • digital wallet — e-wallet

amounts[]

Document-level payment totals. These represent the aggregate across all payment events in this CFDI.

nametypeWhen to use
total payment amountpaymentAlways. The total amount received across all payments in this document.

The amount here must equal the sum of all relations[].amounts[] entries with type: "payment". Example: if you have two payment events of $3,000 and $1,680, root amounts[].amount must be $4,680.

taxes[]

Document-level tax totals. These are the aggregate taxes across all payment events.

Each tax entry falls into one of two categories — you'll typically send one of each:

Field combinationWhat it represents
withholding_type: "withholding" — no rate or taxable_amountThe total withheld tax amount for the document.
rate + taxable_amount — no withholding_typeThe transferred (traslado) tax with its base and rate.

Fields:

FieldWhat to send
amountThe tax amount in currency.
nameTax name. Use total VAT at document level.
typeTax type. Use VAT for IVA.
rateTax rate. Use 0.16 for standard 16% IVA.
rate_typeAlways percentage for IVA.
taxable_amountThe base amount the rate applies to. This is the subtotal before tax, not the total paid.
withholding_typeUse withholding if this entry is a retention. Omit for transferred taxes.

How to calculate taxable_amount: if the amount paid includes 16% IVA, divide by 1.16. Example: paid $4,640 → taxable_amount = $4,640 / 1.16 = $4,000. The tax amount is then $4,000 × 0.16 = $640.

Understanding the three levels of taxes[]

There are three places where you send taxes[] in a Complemento de Pago. Each has a different scope:

LevelScopename to use
Root taxes[]Aggregate totals for the entire document — sum of all payment events.total VAT
relations[].taxes[]Taxes for one specific payment event.VAT
relations[].relations[].taxes[]Taxes on the amount being applied to one specific original invoice.VAT

All three levels follow the same field structure. The difference is purely the scope of what they represent.


relations[] — Payment Events

Each entry in relations[] represents one payment event — for example, one bank transfer. If the buyer made two separate transfers, you'd have two entries.

relations[].invoice_type and relations[].document_type

Always payment and payment for the payment event level.

relations[].currency and relations[].exchange_rate

The currency and exchange rate of this specific payment. Use MXN and 1 for peso payments.

relations[].payment_method

Same structure as root payment_method, but for this specific payment event. Adds bank account details.

payment_method.type

Same values as root. Must match the actual payment form used in this event.

payment_method.bank_account_beneficiary

The bank account that received the payment (your account or your client's payable account).

Only required when payment_method.type is bank transfer. Omit entirely for cash, credit card, debit card, or digital wallet.

FieldWhat to send
bank_nameName of the receiving bank (e.g. Banco de Mexico, BBVA).
account_numberAccount number or CLABE.
account_number_altOptional alias or secondary identifier (e.g. CLABE alias).
address.countryCountry of the bank. Use MX for Mexican banks.
beneficiary.companyThe legal entity that owns this account. Include RFC in tax_registrations.

payment_method.bank_account_sender

The bank account that sent the payment (the buyer's account).

Only required when payment_method.type is bank transfer. Omit entirely for other payment types.

FieldWhat to send
bank_nameName of the sending bank.
account_numberSender's account number.
address.countryCountry of the sender's bank. Can be foreign (e.g. CO, US).
sender.companyThe legal entity that owns the sending account. Include tax ID in tax_registrations.

relations[].amounts[]

The amounts for this specific payment event — not the document total.

nametypeWhen to use
total payment amountpaymentAlways. The amount paid in this specific event.

relations[].taxes[]

The taxes for this specific payment event.

Same structure as root taxes[], but scoped to this event. Use VAT (not total VAT) as the name at this level.


relations[].relations[] — Original Invoices Being Paid

Each entry here represents one original CFDI being settled by this payment event. If one payment covers two invoices, you'd have two entries.

invoice_key

The folio fiscal UUID of the original CFDI being paid. This is the SAT-stamped UUID, not the Brinta invoice ID.

  • Format: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
  • Where to find it: in the response of the original invoice creation, field invoice_key.

invoice_serie and invoice_number

The series and number of the original invoice. Must match exactly what was stamped on the CFDI.

payment_method.installment

SAT field NumParcialidad. The installment number being paid.

  • Use 1 for the first payment against this invoice.
  • Use 2 for the second, and so on.
  • If paying in full in one shot, use 1.

amounts[]

Balance tracking for the original invoice. You must send all three entries:

nametypeWhat to send
previous balancebalanceThe outstanding balance before this payment. For the first payment, this equals the original invoice total.
paid amountpaymentThe amount being paid in this event against this specific invoice.
remaining unpaid balancebalanceThe balance after this payment. If paying in full, send 0.

Example: original invoice was $4,680. First payment covers it in full.

  • previous balance4680
  • paid amount4680
  • remaining unpaid balance0

taxes[]

The tax breakdown of the amount being paid on this original invoice.

Send two entries — one for the transferred tax (traslado) and one for the withheld tax (retención):

EntryFields to include
Transferred (traslado)taxable_amount, amount, name, rate, rate_type, type
Withheld (retención)taxable_amount, amount, name, rate, rate_type, type, withholding_type: "withholding"

Full Example Payload

{
  "supplier_company_id": "{{company_id}}",
  "invoice_number": "111122234",
  "invoice_serie": "FE",
  "invoice_type": "payment",
  "document_type": "payment invoice",
  "invoice_date": "2026-03-10",
  "currency": "MXN",
  "exchange_rate": 1,
  "e_invoice": true,
  "fiscal_status": "02",
  "payment_method": {
    "type": "bank transfer"
  },
  "buyer": {
    "company": {
      "name": "MARIA OLIVIA MARTINEZ SAGAZ",
      "legal_name": "MARIA OLIVIA MARTINEZ SAGAZ",
      "type": "person",
      "address": { "postal_code": "80290", "country": "MX" },
      "tax_registrations": [
        {
          "type": "RFC",
          "number": "MASO451221PM4",
          "level": "country",
          "location": "MX",
          "status": "Regimen de Actividades Profesionales"
        }
      ]
    }
  },
  "amounts": [
    {
      "amount": 6240,
      "name": "total payment amount",
      "type": "payment"
      // Total received across all payment events in this document
    }
  ],
  "taxes": [
    {
      "amount": 640,
      "name": "total VAT",
      "type": "VAT",
      "withholding_type": "withholding"
      // Aggregate withheld IVA across the whole document
    },
    {
      "taxable_amount": 4000,
      "amount": 640,
      "name": "total VAT",
      "rate": 0.16,
      "rate_type": "percentage",
      "type": "VAT"
      // Aggregate transferred IVA — taxable_amount is the subtotal before tax
    }
  ],
  "relations": [
    {
      // One entry per payment event (e.g. one bank transfer)
      "invoice_type": "payment",
      "document_type": "payment",
      "currency": "MXN",
      "exchange_rate": 1,
      "payment_method": {
        "type": "bank transfer",
        "bank_account_beneficiary": {
          "bank_name": "Banco de Mexico",
          "account_number": "3495593033",
          "account_number_alt": "alias_123",
          "address": { "country": "MX" },
          "beneficiary": {
            "company": {
              "name": "Bank Account Beneficiary",
              "type": "business",
              "address": { "country": "MX" },
              "tax_registrations": [
                { "type": "RFC", "level": "country", "location": "MX", "number": "HJO12345676" }
              ]
            }
          }
        },
        "bank_account_sender": {
          "bank_name": "Test Bank",
          "account_number": "123456",
          "address": { "country": "MX" },
          "sender": {
            "company": {
              "name": "Bank Account Sender Company",
              "type": "business",
              "address": { "country": "MX" },
              "tax_registrations": [
                { "type": "RFC", "level": "country", "location": "MX", "number": "EJE123456789" }
              ]
            }
          }
        }
      },
      "amounts": [
        {
          "amount": 4680,
          "name": "total payment amount",
          "type": "payment"
          // Amount paid in this specific payment event
        }
      ],
      "taxes": [
        {
          "taxable_amount": 3000,
          "amount": 480,
          "name": "VAT",
          "rate": 0.16,
          "rate_type": "percentage",
          "type": "VAT"
          // Transferred IVA for this payment event
        },
        {
          "amount": 480,
          "name": "VAT",
          "type": "VAT",
          "withholding_type": "withholding"
          // Withheld IVA for this payment event
        }
      ],
      "relations": [
        {
          // One entry per original invoice being paid in this event
          "invoice_type": "debit",
          "document_type": "invoice",
          "currency": "MXN",
          "exchange_rate": 1,
          "invoice_key": "DD17F8F7-470C-53D6-BCE0-43CD5F12713E",
          "invoice_serie": "FE",
          "invoice_number": "123456112",
          "payment_method": {
            "installment": 1
            // 1 = first payment against this invoice, 2 = second, etc.
          },
          "amounts": [
            { "amount": 4680, "name": "previous balance", "type": "balance" },
            // Balance before this payment — equals original invoice total for first payment
            { "amount": 4680, "name": "paid amount", "type": "payment" },
            // Amount being applied to this invoice in this event
            { "amount": 0, "name": "remaining unpaid balance", "type": "balance" }
            // Balance after this payment — 0 means fully paid
          ],
          "taxes": [
            {
              "taxable_amount": 3000,
              "amount": 480,
              "name": "VAT",
              "rate": 0.16,
              "rate_type": "percentage",
              "type": "VAT"
              // Transferred IVA on the amount being paid for this invoice
            },
            {
              "taxable_amount": 3000,
              "amount": 480,
              "name": "VAT",
              "rate": 0.16,
              "rate_type": "percentage",
              "type": "VAT",
              "withholding_type": "withholding"
              // Withheld IVA on the amount being paid for this invoice
            }
          ]
        }
      ]
    }
  ]
}

Common Mistakes

MistakeWhat happensFix
Sending invoice_key as the Brinta IDSAT rejects the documentUse the UUID from the original CFDI response, field invoice_key
installment starts at 0SAT validation errorAlways start at 1
remaining unpaid balance missingBrinta validation errorAlways send all three amounts[] entries in relations[].relations[]
taxable_amount equals total paidIncorrect tax basetaxable_amount is the subtotal before tax. Formula: paid_amount / 1.16 for standard 16% IVA
Root taxes[] uses VAT instead of total VATIncorrect document structureRoot level uses total VAT, event and invoice levels use VAT
Using PUE invoice as the originalComplemento de Pago not requiredOnly issue Complemento de Pago for PPD original invoices