Invoices

How to interpret invoice data returned by the API and compute income correctly from it.

Invoices in BDI come from CFDIs (Comprobantes Fiscales Digitales) reported to the SAT. The same record can mean very different things depending on its type and on which side of the transaction the subject sits. This page explains how to read them and how to compute monthly income.

Invoices are retrieved from GET /invoices/{identifier} — an 18-char CURP for an individual, or a 12-char RFC for a business. For a business, both invoices it issued and invoices it received are returned.

To improve invoice coverage for individuals, clients that already hold the user's RFC can pass it as the optional rfc field when creating a verification (POST /verifications). When provided, the API uses the client-supplied RFC directly and skips the internal CURP → RFC conversion.


Invoice types

Each invoice has a type field. The type determines whether the amount counts as income, and for which party.

CodeCounts as income?For whom
nominaYesThe rfc_receiver (the employee being paid)
ingresoYesThe rfc_issuer (the party selling goods/services)
egresoNo, it is a correctionReduces a previously issued ingreso from the same RFC
pagoNo, it is a collection complementDocuments the actual payment of a previously issued ingreso

Perspective: rfc_issuer vs rfc_receiver

The same invoice means different things depending on which side of the transaction the subject is on. When querying by CURP or RFC, always check which field the subject appears in:

  • A nomina where the subject is rfc_receiver means the subject received a salary.
  • An ingreso where the subject is rfc_issuer means the subject received an income.
  • An ingreso where the subject is rfc_receiver means the subject bought goods or services.

Computing monthly income

Monthly income for an identifier is the sum of two components:

  1. Salary income: sum of amount for nomina invoices where rfc_receiver is the subject.
  2. Self-employment income: sum of amount for ingreso invoices issued by the subject, minus the sum of amount for egreso invoices issued against those ingresos by the same RFC.
monthly_income =
    Σ nomina.amount  (subject as receiver)
  + Σ ingreso.amount (subject as issuer)
  − Σ egreso.amount  (subject as issuer)

This formula applies to both individuals and businesses. For businesses, salary income is typically zero — they receive income through ingreso invoices, not nomina.


pago invoices: how to read them

pago invoices are SAT's "Recibo Electrónico de Pago" — a complement issued when a customer pays an invoice that was originally issued under deferred or installment payment terms (PPD). The pago CFDI itself does not represent new revenue; it documents a payment against a previously-issued invoice.

Because of this, per SAT spec the top-level amount, subtotal, total_taxes_transferred, and total_taxes_retained on a pago CFDI are zero or near zero. The actual payment value (amount paid, payment date, payment method) lives in a separate node called "Complemento de Pagos," which is not exposed in the default /invoices response.

To retrieve payment details, pass include_payment_info=true on the request. Each invoice will include a payment_info[] array of payment records, and each entry contains a nested payment_relations[] array linking that specific payment to the ingreso invoices it was applied to.

Use this when:

  • Validating whether PPD invoices have been paid.
  • Measuring payment behavior (timeliness, partial payments).
  • Reconciling invoiced revenue against cash collected in a given period.

Common pitfalls

  • Summing pago as income → double-counting. pago documents a payment, not new revenue.
  • Treating egreso as a generic expense → understates income. egreso is a correction to a previously issued ingreso, not an arbitrary debit.
  • Ignoring perspective: a nomina where the subject is rfc_issuer is not received salary — the subject paid it.
  • Treating self-issued CFDIs (subject on both sides) as non-income → they are income.
  • Expecting incomes / deductions on ingreso or pago invoices → those fields are nómina-specific.
  • Aggregating across mixed currencies without normalizing (currency field).

Field reference

The same invoice object is returned for individuals and businesses. Nómina-specific fields are only populated for nomina invoices.

Field NameTypeDescriptionExampleNotes
typestringInvoice type."nomina"See Invoice Types below.
amountnumberTotal amount.42487.53
currencystringCurrency code."MXN"Usually MXN.
folio_fiscalstringFiscal identifier of invoice."7A9F33E4-892C-4B8D-A9E1-2F6F0001"May be null.
issue_datestring (date)Official issue date."2025-04-01"YYYY-MM-DD.
rfc_issuerstringIssuer's RFC."CYA010101AAA"Who issued the invoice.
issuer_namestringIssuer's name."Construcciones Yamile S.A. de C.V."Name of individual or company issuing the invoice.
rfc_receiverstringReceiver's RFC."OICE940722GHW"Who received the invoice.
receiver_namestringReceiver's name."José Carlos Aguilar Rincón"Name of individual or company receiving the invoice.
payment_methodstringSAT payment method code."PPD"Populated for ingreso and egreso.
payment_typestringSAT payment form code."99"Populated for ingreso and egreso.
line_itemsarray[object]Product or service lines.See belowPopulated for ingreso and egreso.
invoice_relationsarray[object]Related invoice references.See belowPopulated for ingreso and egreso.
invoice_statusstringInvoice status.""May be an empty string.
zip_code_receiverstringReceiver postal code.""May be an empty string.
payment_infoarray[object] or nullPayment details associated with the invoice.See Invoice Types and Payment Info belowOnly present when include_payment_info=true.
payroll_typestringPayroll type, SAT TipoNomina.OrdinariaPopulated for nomina
payment_periodicitystringPayment periodicity, SAT PeriodicidadPagoQuincenalPopulated for nomina
job_riskstringJob risk class, SAT RiesgoPuesto.Clase IPopulated for nomina
job_rolestringJob role (puesto) reported in the payroll receipt.AUXILIAR ADMINISTRATIVOPopulated for nomina
job_departmentstringJob department (departamento) reported in the payroll receipt.ADMINISTRACIONPopulated for nomina


incomes and deductions

For nomina invoices, the response includes incomes and deductions arrays with the line-item breakdown (Percepciones and Deducciones in SAT terminology). For other types, both arrays are empty.

Field NameTypeDescriptionNotes
incomesarray[object]Income breakdown.Populated for nomina.
deductionsarray[object]Deduction breakdown.Populated for nomina.

Each item has amount, currency, and a free-form detail label (e.g., Sueldo, Aguinaldo, ISR, IMSS). Items can also include key and type SAT codes that identify and group the concept.


line_items

For ingreso and egreso invoices, the response can include a line_items array with the products or services included in the invoice.

Field NameTypeDescriptionNotes
detailstringProduct or service description.
quantitynumberNumber of units included.
unitstringUnit of measure.
unit_pricenumberPer-unit cost.
amountnumberTotal amount for the line item.
product_service_keystringSAT product/service identifier.ClaveProdServ.

Use line_items to understand what was billed or corrected, but use the top-level amount when computing income totals.


invoice_relations

For ingreso and egreso invoices, the response can include an invoice_relations array with references to related fiscal documents.

Field NameTypeDescription
relation_typestringSAT relationship code (TipoRelacion).
related_fiscal_codestringFolio fiscal of the related invoice.


Job risk (nomina)

The SAT defines occupational risk as follows:

Job riskDescription
Clase IRiesgo ordinario de vida
Clase IIRiesgo bajo
Clase IIIRiesgo medio
Clase IVRiesgo alto
Clase VRiesgo máximo

Did this page help you?