# Timbrar un recibo de nómina

`POST https://api.fiscalisto.com/v1/payroll_receipts`

Nómina ordinaria (Nómina 1.2): Fiscalisto calcula sueldo, ISR con subsidio al empleo e IMSS del empleado y el periodo, como la app. Queda como factura tipo N (GET /v1/invoices/{id}). El emisor necesita employer_registration.

## Parámetros

| Nombre | Dónde | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `Idempotency-Key` | encabezado | sí | Uno nuevo por comprobante (8 a 255 caracteres; su id de pedido sirve). Si la respuesta se pierde, repita la solicitud con el mismo valor: contesta lo mismo y nunca se timbra dos veces. |

## Cuerpo

| Campo | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `employee` | string | sí | El empleado (emp_…). |
| `period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `period.start` | string | sí | Primer día del periodo (FechaInicialPago), AAAA-MM-DD. |
| `period.end` | string | sí | Último día del periodo (FechaFinalPago), AAAA-MM-DD. |
| `period.payment_date` | string |  | Fecha de pago (FechaPago), AAAA-MM-DD. Por omisión el último día del periodo. |
| `days` | number |  | Días pagados (NumDiasPagados). Por omisión, todos los del periodo que le tocan. (de -∞ a 31) |
| `send_email` | boolean |  | true para mandar el PDF y el XML por correo al timbrar, con el diseño de Fiscalisto. Por omisión no se envía. |
| `metadata` | objeto |  | Sus propios datos: hasta 50 llaves de 40 caracteres con valores de texto de hasta 500. No van al CFDI; vuelven en el objeto y en los webhooks. |

Ejemplo:

```json
{
  "employee": "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
  "period": {
    "start": "2026-10-10",
    "end": "2026-10-16"
  },
  "send_email": true,
  "metadata": {
    "corrida": "2026-42"
  }
}
```

## Con el SDK de TypeScript

```ts
import { Fiscalisto } from "fiscalisto";

// La llave viene de FISCALISTO_API_KEY.
const fiscalisto = new Fiscalisto();

const invoice = await fiscalisto.payrollReceipts.create({
  employee: "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
  period: { start: "2026-10-10", end: "2026-10-16" },
  send_email: true,
  metadata: { corrida: "2026-42" },
}, { idempotencyKey: "pedido-A-1042" });
```

## Con el SDK de Python

```python
from fiscalisto import Fiscalisto

# La llave viene de FISCALISTO_API_KEY.
fiscalisto = Fiscalisto()

invoice = fiscalisto.payroll_receipts.create({
    "employee": "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
    "period": {"start": "2026-10-10", "end": "2026-10-16"},
    "send_email": True,
    "metadata": {"corrida": "2026-42"},
}, idempotency_key="pedido-A-1042")
```

## Con el SDK de PHP

```php
<?php

use Fiscalisto\Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
$fiscalisto = new Fiscalisto();

$invoice = $fiscalisto->payrollReceipts->create([
    'employee' => 'emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV',
    'period' => [
        'start' => '2026-10-10',
        'end' => '2026-10-16',
    ],
    'send_email' => true,
    'metadata' => ['corrida' => '2026-42'],
], ['idempotency_key' => 'pedido-A-1042']);
```

## Con el SDK de .NET

```csharp
using Fiscalisto;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var invoice = await fiscalisto.PayrollReceipts.CreateAsync(new CreatePayrollReceiptParams
{
    Employee = "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
    Period = new() { Start = "2026-10-10", End = "2026-10-16" },
    SendEmail = true,
    Metadata = new() { ["corrida"] = "2026-42" },
}, new RequestOptions { IdempotencyKey = "pedido-A-1042" });
```

## Con el SDK de Go

```go
package main

import (
	"context"
	"fmt"
	"log"

	fiscalisto "fiscalisto.com/go"
)

func main() {
	// La llave viene de FISCALISTO_API_KEY.
	client, err := fiscalisto.NewClient("")
	if err != nil {
		log.Fatal(err)
	}
	ctx := context.Background()

	invoice, err := client.PayrollReceipts.Create(ctx, &fiscalisto.CreatePayrollReceiptParams{
		Employee: "emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV",
		Period: fiscalisto.CreatePayrollReceiptParamsPeriod{
			Start: "2026-10-10",
			End:   "2026-10-16",
		},
		SendEmail: fiscalisto.Bool(true),
		Metadata:  map[string]string{"corrida": "2026-42"},
	}, fiscalisto.WithIdempotencyKey("pedido-A-1042"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(invoice.ID)
}
```

## Con el SDK de Java

```java
import com.fiscalisto.FiscalistoClient;
import com.fiscalisto.RequestOptions;
import com.fiscalisto.model.CreatePayrollReceiptParams;
import com.fiscalisto.model.CreatePayrollReceiptParamsPeriod;
import java.util.Map;

// La llave viene de FISCALISTO_API_KEY.
var fiscalisto = new FiscalistoClient();

var invoice = fiscalisto.payrollReceipts().create(new CreatePayrollReceiptParams()
        .setEmployee("emp_OufpKqnrvx9p3RxmD1RIDgEHzKYPYnYBlV")
        .setPeriod(new CreatePayrollReceiptParamsPeriod()
                .setStart("2026-10-10")
                .setEnd("2026-10-16"))
        .setSendEmail(true)
        .setMetadata(Map.of("corrida", "2026-42")), RequestOptions.idempotencyKey("pedido-A-1042"));
System.out.println(invoice.getId());
```

## Respuesta 201

Correcto. Repetir la solicitud con la misma Idempotency-Key contesta lo mismo, con el mismo status y el encabezado idempotent-replayed: true.

Un objeto `Invoice`:

| Campo | Tipo | Siempre viene | Descripción |
| --- | --- | --- | --- |
| `id` | string | sí | Identificador del objeto, con su prefijo (iss_, inv_, ret_, cus_, prd_, emp_, bat_, brn_, whs_, stm_, adj_, evt_, whe_). |
| `livemode` | boolean | sí | true en producción (llaves fk_live_), false en pruebas (fk_test_). Lo de pruebas no vale ante el SAT. |
| `object` | `"invoice"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `issuer` | string | sí | El emisor (iss_…). |
| `branch` | string o null | sí | La sucursal (brn_…) desde donde se timbró, o null (el domicilio fiscal del emisor). Sus pagos y notas de crédito la siguen. |
| `type` | `I`, `E`, `P`, `T`, `N` | sí | Tipo de comprobante (TipoDeComprobante): I ingreso, E egreso, P pago, T traslado, N nómina. |
| `status` | `processing`, `pending`, `valid`, `rejected`, `canceled` | sí | processing: el PAC no ha contestado (se resuelve sola; escuche invoice.stamped). valid: timbrada. pending: timbrada con una cancelación en espera del cliente. rejected: el SAT o el PAC no la aceptaron (ver error). canceled: cancelada. |
| `uuid` | string o null | sí | Folio fiscal que asigna el SAT (UUID del Timbre Fiscal Digital), en mayúsculas. |
| `series` | string o null | sí | Serie (Serie), hasta 25 caracteres. Cada serie lleva sus propios folios. |
| `folio` | string o null | sí | Folio (Folio). Fiscalisto asigna el siguiente de la serie; mande uno solo si debe ser ese. |
| `date` | string o null | sí | Fecha de emisión (Fecha), hora de la Ciudad de México. |
| `customer` | objeto | sí | Cliente (Receptor): el id de uno de su catálogo (cus_…) o sus datos en un objeto. |
| `customer.tax_id` | string o null | sí | RFC (Rfc), 12 caracteres una persona moral y 13 una física. |
| `customer.legal_name` | string o null | sí | Nombre o razón social tal como está en la constancia de situación fiscal, sin el régimen de capital (sin «S.A. de C.V.»). |
| `customer.tax_system` | string |  | Régimen fiscal (RegimenFiscal), clave de c_RegimenFiscal: 601, 612, 626… |
| `customer.zip` | string |  | Código postal del domicilio fiscal del cliente (DomicilioFiscalReceptor), 5 dígitos. |
| `customer.foreign` | objeto |  | Si es extranjero: su país de residencia (ResidenciaFiscal, c_Pais) y su número de registro tributario (NumRegIdTrib), con el RFC genérico XEXX010101000. |
| `use` | string o null | sí | Uso del CFDI (UsoCFDI), clave de c_UsoCFDI. Por omisión G03, o S01 con régimen 616. |
| `payment_form` | string o null | sí | Forma de pago (FormaPago), clave de c_FormaPago: 01 efectivo, 03 transferencia, 04 tarjeta de crédito, 28 débito, 99 por definir… Obligatoria con PUE; con PPD es 99. |
| `payment_method` | string o null | sí | Método de pago (MetodoPago): PUE (una sola exhibición, por omisión) o PPD (en parcialidades o diferido, se cobra con complementos de pago). |
| `currency` | string | sí | Moneda, clave ISO 4217 de c_Moneda (MXN, USD, EUR…). Por omisión MXN. |
| `exchange_rate` | number o null | sí | Tipo de cambio a pesos (TipoCambio). Obligatorio si la moneda no es MXN; use el del DOF del día anterior. |
| `items` | arreglo de objeto | sí | Conceptos (Conceptos), al menos uno. |
| `subtotal` | number o null | sí | Suma de los importes antes de impuestos y descuentos (SubTotal). |
| `discount` | number o null | sí | Descuento (Descuento). |
| `taxes` | objeto o null | sí | Impuestos del comprobante, por tipo. |
| `taxes.iva` | number o null | sí | IVA trasladado. |
| `taxes.ieps` | number o null | sí | IEPS trasladado. |
| `taxes.iva_withheld` | number o null | sí | IVA retenido. |
| `taxes.isr_withheld` | number o null | sí | ISR retenido. |
| `taxes.local_transferred` | number o null | sí | Impuestos locales trasladados. |
| `taxes.local_withheld` | number o null | sí | Impuestos locales retenidos. |
| `total` | number o null | sí | Total en la moneda del comprobante (Total). |
| `payment_status` | `paid`, `partial`, `unpaid` o null | sí | Si ya se cobró (Cuentas por cobrar): paid, partial (complementos de pago o notas de crédito por una parte) o unpaid. Una PUE está paid, salvo con paid_later hasta POST /v1/invoices/{id}/mark_paid. null si no es de ingreso o no está vigente. |
| `amount_due` | number o null | sí | Lo que falta por cobrar, en su moneda, o null. |
| `amount_paid` | number o null | sí | Lo cobrado: complementos de pago y notas de crédito vigentes, o todo si es PUE pagada. null si no aplica. |
| `related` | objeto o null | sí | CFDI relacionados (CfdiRelacionados): tipo de relación de c_TipoRelacion y los UUID. |
| `payment` | objeto o null |  | Solo en un complemento de pago (type P). |
| `payment.date` | string o null | sí | Fecha del pago (FechaPago). |
| `payment.payment_form` | string o null | sí | Forma de pago (FormaPago), clave de c_FormaPago: 01 efectivo, 03 transferencia, 04 tarjeta de crédito, 28 débito, 99 por definir… Obligatoria con PUE; con PPD es 99. |
| `payment.currency` | string | sí | Moneda del pago (MonedaP). |
| `payment.exchange_rate` | number o null | sí | Tipo de cambio a pesos (TipoCambio). Obligatorio si la moneda no es MXN; use el del DOF del día anterior. |
| `payment.amount` | number | sí | Monto del pago (Monto). |
| `payment.operation_number` | string o null | sí | Número de operación del pago (NumOperacion), como el rastreo SPEI. |
| `payment.documents` | arreglo de objeto | sí | Las facturas que paga (DoctoRelacionado). |
| `payment.documents[].uuid` | string | sí | Folio fiscal que asigna el SAT (UUID del Timbre Fiscal Digital), en mayúsculas. |
| `payment.documents[].series` | string o null | sí | Serie de la factura pagada. |
| `payment.documents[].folio` | string o null | sí | Folio de la factura pagada. |
| `payment.documents[].currency` | string | sí | Moneda de la factura pagada (MonedaDR). |
| `payment.documents[].partiality` | integer | sí | Número de parcialidad (NumParcialidad). (de -9007199254740991 a 9007199254740991) |
| `payment.documents[].previous_balance` | number | sí | Saldo anterior de la factura (ImpSaldoAnt). |
| `payment.documents[].amount` | number | sí | Lo que se paga de esa factura (ImpPagado), en la moneda de la factura. |
| `payment.documents[].remaining` | number | sí | Saldo insoluto después de este pago (ImpSaldoInsoluto). |
| `payroll` | objeto |  | Solo en un recibo de nómina (type N). |
| `payroll.periodicity` | string | sí | Periodicidad del pago (PeriodicidadPago): 02 semanal, 03 catorcenal, 04 quincenal (por omisión), 05 mensual. |
| `payroll.period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `payroll.period.start` | string | sí | Primer día del periodo (FechaInicialPago), AAAA-MM-DD. |
| `payroll.period.end` | string | sí | Último día del periodo (FechaFinalPago), AAAA-MM-DD. |
| `payroll.period.payment_date` | string | sí | Fecha de pago (FechaPago), AAAA-MM-DD. Por omisión el último día del periodo. |
| `payroll.days` | number | sí | Días pagados (NumDiasPagados). Por omisión, todos los del periodo que le tocan. |
| `payroll.employer` | objeto | sí | El patrón (Emisor del complemento): registro patronal y CURP si es persona física. |
| `payroll.employer.employer_registration` | string o null | sí | Registro patronal ante el IMSS (RegistroPatronal), 11 caracteres. Necesario para timbrar nómina. |
| `payroll.employer.curp` | string o null | sí | CURP, 18 caracteres. |
| `payroll.employee` | objeto | sí | El empleado (emp_…). |
| `payroll.employee.id` | string o null | sí | Identificador del objeto, con su prefijo (iss_, inv_, ret_, cus_, prd_, emp_, bat_, brn_, whs_, stm_, adj_, evt_, whe_). |
| `payroll.employee.number` | string | sí | Número de empleado (NumEmpleado). |
| `payroll.employee.curp` | string | sí | CURP, 18 caracteres. |
| `payroll.employee.social_security_number` | string o null | sí | Número de seguridad social (NumSeguridadSocial), 11 dígitos. |
| `payroll.employee.start_date` | string | sí | Fecha de inicio de la relación laboral (FechaInicioRelLaboral), AAAA-MM-DD. |
| `payroll.employee.contract_type` | string | sí | Tipo de contrato (TipoContrato), c_TipoContrato. Por omisión 01, por tiempo indeterminado. |
| `payroll.employee.unionized` | boolean | sí | true si es sindicalizado (Sindicalizado). |
| `payroll.employee.workday_type` | string | sí | Tipo de jornada (TipoJornada), c_TipoJornada. Por omisión 01, diurna. |
| `payroll.employee.regime_type` | string | sí | Tipo de régimen (TipoRegimen): 02 sueldos y salarios. |
| `payroll.employee.department` | string o null |  | Departamento (Departamento). |
| `payroll.employee.position` | string o null |  | Puesto (Puesto). |
| `payroll.employee.risk_class` | string o null | sí | Clase de riesgo del puesto ante el IMSS (RiesgoPuesto), 1 a 5. Por omisión 1. |
| `payroll.employee.contribution_base_salary` | number o null | sí | Salario base de cotización (SalarioBaseCotApor). |
| `payroll.employee.integrated_daily_salary` | number o null | sí | Salario diario integrado (SalarioDiarioIntegrado): no menor al salario diario. |
| `payroll.employee.state` | string | sí | Entidad federativa donde trabaja (ClaveEntFed): JAL, CMX, NLE… |
| `payroll.perceptions` | arreglo de objeto | sí | Percepciones (Percepcion): sueldo y demás, gravado y exento. |
| `payroll.perceptions[].type` | string | sí | Tipo de percepción (TipoPercepcion), c_TipoPercepcion: 001 sueldos… |
| `payroll.perceptions[].key` | string | sí | Clave del patrón (Clave). |
| `payroll.perceptions[].concept` | string | sí | Concepto (Concepto). |
| `payroll.perceptions[].taxed` | number | sí | Importe gravado (ImporteGravado). |
| `payroll.perceptions[].exempt` | number | sí | Importe exento (ImporteExento). |
| `payroll.deductions` | arreglo de objeto | sí | Deducciones (Deduccion): ISR, cuotas IMSS y demás. |
| `payroll.deductions[].type` | string | sí | Tipo de deducción (TipoDeduccion), c_TipoDeduccion: 001 IMSS, 002 ISR… |
| `payroll.deductions[].key` | string | sí | Clave del patrón (Clave). |
| `payroll.deductions[].concept` | string | sí | Concepto (Concepto). |
| `payroll.deductions[].amount` | number | sí | Importe (Importe). |
| `payroll.other_payments` | arreglo de objeto | sí | Otros pagos (OtroPago): subsidio para el empleo. |
| `payroll.other_payments[].type` | string | sí | Tipo de otro pago (TipoOtroPago), c_TipoOtroPago: 002 subsidio para el empleo. |
| `payroll.other_payments[].key` | string | sí | Clave del patrón (Clave). |
| `payroll.other_payments[].concept` | string | sí | Concepto (Concepto). |
| `payroll.other_payments[].amount` | number | sí | Importe pagado (Importe). |
| `payroll.other_payments[].subsidy_caused` | number |  | Subsidio causado (SubsidioCausado). |
| `payroll.other_payments[].subsidy_applied` | number |  | Del subsidio causado, el ISR que evitó (no va en el XML). |
| `global` | objeto |  | Solo en una factura global. |
| `cancellation` | objeto o null | sí | La cancelación, si se pidió: estado, motivo, sustituto y cuándo. |
| `cancellation.status` | string o null | sí | pending (espera la respuesta del cliente), accepted (cancelada), rejected (el cliente la rechazó) o lapsed (venció; puede pedirla otra vez). |
| `cancellation.motive` | string o null | sí | Motivo de cancelación (c_MotivoCancelacion): 01 con errores con relación (lleva substitution), 02 con errores sin relación (por omisión), 03 no se llevó a cabo, 04 solo en una factura global, cuando una venta incluida se facturó a nombre del cliente. |
| `cancellation.substitution` | string o null | sí | El comprobante que sustituye a este (su id o su UUID), con el motivo 01. |
| `cancellation.canceled_at` | string (date-time) o null | sí | Cuándo se canceló. |
| `email` | objeto o null | sí | El envío por correo: a quién, con copia a quién y cuándo (null si no se ha enviado). |
| `email.to` | string o null | sí | A quién (correos separados por comas). |
| `email.cc` | string o null | sí | Con copia (correos separados por comas). |
| `email.sent_at` | string (date-time) o null | sí | Cuándo se envió. |
| `error` | objeto o null | sí | Por qué el SAT o el PAC no lo aceptaron: mensaje, código del SAT y texto original. |
| `error.message` | string | sí | Qué pasó y cómo corregirlo, para una persona. |
| `error.sat_code` | string o null | sí | Código del SAT o del PAC (CFDI40xxx). |
| `error.raw` | string | sí | El texto original del PAC. |
| `recurring_invoice` | string o null | sí | La factura recurrente (rin_…) que la timbró sola, o null si se timbró con una llamada. |
| `created_at` | string (date-time) o null | sí | Cuándo se creó, ISO 8601 con la hora de la Ciudad de México (-06:00). |
| `metadata` | objeto | sí | Sus propios datos: hasta 50 llaves de 40 caracteres con valores de texto de hasta 500. No van al CFDI; vuelven en el objeto y en los webhooks. |
| `warnings` | arreglo de string |  | Avisos que no impidieron timbrar (por ejemplo, el XML se guardará después). |
| `email_error` | string |  | Por qué no se pudo mandar el correo; el comprobante sí se timbró. |
| `substitutes` | objeto |  | La factura que esta sustituyó y si quedó cancelada. |
| `substitutes.invoice` | string | sí | La factura sustituida (inv_…). |
| `substitutes.canceled` | boolean | sí | true si la sustituida ya quedó cancelada. |
| `substitutes.cancel_error` | string |  | Por qué no se pudo cancelar la sustituida (cancélela con POST /v1/invoices/{id}/cancel). |
| `advance_application` | objeto |  | La aplicación del anticipo: método, nota de aplicación y su estado. |
| `advance_application.advance` | string o null | sí | El anticipo, como factura (inv_…). |
| `advance_application.advance_uuid` | string | sí | El folio fiscal del anticipo. |
| `advance_application.method` | `egreso`, `remanente` | sí | egreso (la factura completa y después una nota de crédito por el anticipo, opción A) o remanente (la factura solo por lo que falta, opción B). |
| `advance_application.status` | `done`, `credit_note_pending` | sí | done (listo) o credit_note_pending (falta timbrar la nota de aplicación: repita la solicitud con la misma Idempotency-Key). |
| `advance_application.credit_note` | string o null | sí | La nota de aplicación del anticipo (inv_…), con method egreso. |
| `advance_application.credit_note_error` | string |  | Por qué no se timbró la nota de aplicación (repita con la misma Idempotency-Key). |

```json
{
  "id": "inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg",
  "object": "invoice",
  "livemode": false,
  "issuer": "iss_OufpKqnrvx9p",
  "branch": null,
  "type": "I",
  "status": "valid",
  "uuid": "5F1E8C2A-3B7D-4C9E-A1B2-C3D4E5F60718",
  "series": null,
  "folio": "1",
  "date": "2026-10-24T10:15:42",
  "customer": {
    "tax_id": "ICV060329BY0",
    "legal_name": "INMOBILIARIA CVA",
    "tax_system": "601",
    "zip": "33826"
  },
  "use": "I04",
  "payment_form": "03",
  "payment_method": "PUE",
  "currency": "MXN",
  "exchange_rate": null,
  "items": [
    {
      "description": "Mensualidad",
      "product_key": "86121700",
      "unit_key": "E48",
      "unit_name": "Unidad de servicio",
      "sku": "MEN-1",
      "quantity": 2,
      "unit_price": 2500,
      "taxability": "02",
      "iva": "0.16"
    }
  ],
  "subtotal": 5000,
  "discount": 0,
  "taxes": {
    "iva": 800,
    "ieps": 0,
    "iva_withheld": 0,
    "isr_withheld": 0,
    "local_transferred": 0,
    "local_withheld": 0
  },
  "total": 5800,
  "payment_status": "paid",
  "amount_due": 0,
  "amount_paid": 5800,
  "related": null,
  "cancellation": null,
  "email": null,
  "error": null,
  "recurring_invoice": null,
  "created_at": "2026-10-24T10:15:42-06:00",
  "metadata": {}
}
```

## Respuesta 202

El PAC no contestó a tiempo: el comprobante queda en processing y se timbra solo en unos momentos. Escuche el evento *.stamped o consúltelo con GET; repetir la solicitud con la misma Idempotency-Key contesta su estado sin timbrar otra vez.

Un objeto `Invoice`:

| Campo | Tipo | Siempre viene | Descripción |
| --- | --- | --- | --- |
| `id` | string | sí | Identificador del objeto, con su prefijo (iss_, inv_, ret_, cus_, prd_, emp_, bat_, brn_, whs_, stm_, adj_, evt_, whe_). |
| `livemode` | boolean | sí | true en producción (llaves fk_live_), false en pruebas (fk_test_). Lo de pruebas no vale ante el SAT. |
| `object` | `"invoice"` | sí | Qué tipo de objeto es («invoice», «customer»…). |
| `issuer` | string | sí | El emisor (iss_…). |
| `branch` | string o null | sí | La sucursal (brn_…) desde donde se timbró, o null (el domicilio fiscal del emisor). Sus pagos y notas de crédito la siguen. |
| `type` | `I`, `E`, `P`, `T`, `N` | sí | Tipo de comprobante (TipoDeComprobante): I ingreso, E egreso, P pago, T traslado, N nómina. |
| `status` | `processing`, `pending`, `valid`, `rejected`, `canceled` | sí | processing: el PAC no ha contestado (se resuelve sola; escuche invoice.stamped). valid: timbrada. pending: timbrada con una cancelación en espera del cliente. rejected: el SAT o el PAC no la aceptaron (ver error). canceled: cancelada. |
| `uuid` | string o null | sí | Folio fiscal que asigna el SAT (UUID del Timbre Fiscal Digital), en mayúsculas. |
| `series` | string o null | sí | Serie (Serie), hasta 25 caracteres. Cada serie lleva sus propios folios. |
| `folio` | string o null | sí | Folio (Folio). Fiscalisto asigna el siguiente de la serie; mande uno solo si debe ser ese. |
| `date` | string o null | sí | Fecha de emisión (Fecha), hora de la Ciudad de México. |
| `customer` | objeto | sí | Cliente (Receptor): el id de uno de su catálogo (cus_…) o sus datos en un objeto. |
| `customer.tax_id` | string o null | sí | RFC (Rfc), 12 caracteres una persona moral y 13 una física. |
| `customer.legal_name` | string o null | sí | Nombre o razón social tal como está en la constancia de situación fiscal, sin el régimen de capital (sin «S.A. de C.V.»). |
| `customer.tax_system` | string |  | Régimen fiscal (RegimenFiscal), clave de c_RegimenFiscal: 601, 612, 626… |
| `customer.zip` | string |  | Código postal del domicilio fiscal del cliente (DomicilioFiscalReceptor), 5 dígitos. |
| `customer.foreign` | objeto |  | Si es extranjero: su país de residencia (ResidenciaFiscal, c_Pais) y su número de registro tributario (NumRegIdTrib), con el RFC genérico XEXX010101000. |
| `use` | string o null | sí | Uso del CFDI (UsoCFDI), clave de c_UsoCFDI. Por omisión G03, o S01 con régimen 616. |
| `payment_form` | string o null | sí | Forma de pago (FormaPago), clave de c_FormaPago: 01 efectivo, 03 transferencia, 04 tarjeta de crédito, 28 débito, 99 por definir… Obligatoria con PUE; con PPD es 99. |
| `payment_method` | string o null | sí | Método de pago (MetodoPago): PUE (una sola exhibición, por omisión) o PPD (en parcialidades o diferido, se cobra con complementos de pago). |
| `currency` | string | sí | Moneda, clave ISO 4217 de c_Moneda (MXN, USD, EUR…). Por omisión MXN. |
| `exchange_rate` | number o null | sí | Tipo de cambio a pesos (TipoCambio). Obligatorio si la moneda no es MXN; use el del DOF del día anterior. |
| `items` | arreglo de objeto | sí | Conceptos (Conceptos), al menos uno. |
| `subtotal` | number o null | sí | Suma de los importes antes de impuestos y descuentos (SubTotal). |
| `discount` | number o null | sí | Descuento (Descuento). |
| `taxes` | objeto o null | sí | Impuestos del comprobante, por tipo. |
| `taxes.iva` | number o null | sí | IVA trasladado. |
| `taxes.ieps` | number o null | sí | IEPS trasladado. |
| `taxes.iva_withheld` | number o null | sí | IVA retenido. |
| `taxes.isr_withheld` | number o null | sí | ISR retenido. |
| `taxes.local_transferred` | number o null | sí | Impuestos locales trasladados. |
| `taxes.local_withheld` | number o null | sí | Impuestos locales retenidos. |
| `total` | number o null | sí | Total en la moneda del comprobante (Total). |
| `payment_status` | `paid`, `partial`, `unpaid` o null | sí | Si ya se cobró (Cuentas por cobrar): paid, partial (complementos de pago o notas de crédito por una parte) o unpaid. Una PUE está paid, salvo con paid_later hasta POST /v1/invoices/{id}/mark_paid. null si no es de ingreso o no está vigente. |
| `amount_due` | number o null | sí | Lo que falta por cobrar, en su moneda, o null. |
| `amount_paid` | number o null | sí | Lo cobrado: complementos de pago y notas de crédito vigentes, o todo si es PUE pagada. null si no aplica. |
| `related` | objeto o null | sí | CFDI relacionados (CfdiRelacionados): tipo de relación de c_TipoRelacion y los UUID. |
| `payment` | objeto o null |  | Solo en un complemento de pago (type P). |
| `payment.date` | string o null | sí | Fecha del pago (FechaPago). |
| `payment.payment_form` | string o null | sí | Forma de pago (FormaPago), clave de c_FormaPago: 01 efectivo, 03 transferencia, 04 tarjeta de crédito, 28 débito, 99 por definir… Obligatoria con PUE; con PPD es 99. |
| `payment.currency` | string | sí | Moneda del pago (MonedaP). |
| `payment.exchange_rate` | number o null | sí | Tipo de cambio a pesos (TipoCambio). Obligatorio si la moneda no es MXN; use el del DOF del día anterior. |
| `payment.amount` | number | sí | Monto del pago (Monto). |
| `payment.operation_number` | string o null | sí | Número de operación del pago (NumOperacion), como el rastreo SPEI. |
| `payment.documents` | arreglo de objeto | sí | Las facturas que paga (DoctoRelacionado). |
| `payment.documents[].uuid` | string | sí | Folio fiscal que asigna el SAT (UUID del Timbre Fiscal Digital), en mayúsculas. |
| `payment.documents[].series` | string o null | sí | Serie de la factura pagada. |
| `payment.documents[].folio` | string o null | sí | Folio de la factura pagada. |
| `payment.documents[].currency` | string | sí | Moneda de la factura pagada (MonedaDR). |
| `payment.documents[].partiality` | integer | sí | Número de parcialidad (NumParcialidad). (de -9007199254740991 a 9007199254740991) |
| `payment.documents[].previous_balance` | number | sí | Saldo anterior de la factura (ImpSaldoAnt). |
| `payment.documents[].amount` | number | sí | Lo que se paga de esa factura (ImpPagado), en la moneda de la factura. |
| `payment.documents[].remaining` | number | sí | Saldo insoluto después de este pago (ImpSaldoInsoluto). |
| `payroll` | objeto |  | Solo en un recibo de nómina (type N). |
| `payroll.periodicity` | string | sí | Periodicidad del pago (PeriodicidadPago): 02 semanal, 03 catorcenal, 04 quincenal (por omisión), 05 mensual. |
| `payroll.period` | objeto | sí | Periodo (Periodo): mes inicial, mes final y año. |
| `payroll.period.start` | string | sí | Primer día del periodo (FechaInicialPago), AAAA-MM-DD. |
| `payroll.period.end` | string | sí | Último día del periodo (FechaFinalPago), AAAA-MM-DD. |
| `payroll.period.payment_date` | string | sí | Fecha de pago (FechaPago), AAAA-MM-DD. Por omisión el último día del periodo. |
| `payroll.days` | number | sí | Días pagados (NumDiasPagados). Por omisión, todos los del periodo que le tocan. |
| `payroll.employer` | objeto | sí | El patrón (Emisor del complemento): registro patronal y CURP si es persona física. |
| `payroll.employer.employer_registration` | string o null | sí | Registro patronal ante el IMSS (RegistroPatronal), 11 caracteres. Necesario para timbrar nómina. |
| `payroll.employer.curp` | string o null | sí | CURP, 18 caracteres. |
| `payroll.employee` | objeto | sí | El empleado (emp_…). |
| `payroll.employee.id` | string o null | sí | Identificador del objeto, con su prefijo (iss_, inv_, ret_, cus_, prd_, emp_, bat_, brn_, whs_, stm_, adj_, evt_, whe_). |
| `payroll.employee.number` | string | sí | Número de empleado (NumEmpleado). |
| `payroll.employee.curp` | string | sí | CURP, 18 caracteres. |
| `payroll.employee.social_security_number` | string o null | sí | Número de seguridad social (NumSeguridadSocial), 11 dígitos. |
| `payroll.employee.start_date` | string | sí | Fecha de inicio de la relación laboral (FechaInicioRelLaboral), AAAA-MM-DD. |
| `payroll.employee.contract_type` | string | sí | Tipo de contrato (TipoContrato), c_TipoContrato. Por omisión 01, por tiempo indeterminado. |
| `payroll.employee.unionized` | boolean | sí | true si es sindicalizado (Sindicalizado). |
| `payroll.employee.workday_type` | string | sí | Tipo de jornada (TipoJornada), c_TipoJornada. Por omisión 01, diurna. |
| `payroll.employee.regime_type` | string | sí | Tipo de régimen (TipoRegimen): 02 sueldos y salarios. |
| `payroll.employee.department` | string o null |  | Departamento (Departamento). |
| `payroll.employee.position` | string o null |  | Puesto (Puesto). |
| `payroll.employee.risk_class` | string o null | sí | Clase de riesgo del puesto ante el IMSS (RiesgoPuesto), 1 a 5. Por omisión 1. |
| `payroll.employee.contribution_base_salary` | number o null | sí | Salario base de cotización (SalarioBaseCotApor). |
| `payroll.employee.integrated_daily_salary` | number o null | sí | Salario diario integrado (SalarioDiarioIntegrado): no menor al salario diario. |
| `payroll.employee.state` | string | sí | Entidad federativa donde trabaja (ClaveEntFed): JAL, CMX, NLE… |
| `payroll.perceptions` | arreglo de objeto | sí | Percepciones (Percepcion): sueldo y demás, gravado y exento. |
| `payroll.perceptions[].type` | string | sí | Tipo de percepción (TipoPercepcion), c_TipoPercepcion: 001 sueldos… |
| `payroll.perceptions[].key` | string | sí | Clave del patrón (Clave). |
| `payroll.perceptions[].concept` | string | sí | Concepto (Concepto). |
| `payroll.perceptions[].taxed` | number | sí | Importe gravado (ImporteGravado). |
| `payroll.perceptions[].exempt` | number | sí | Importe exento (ImporteExento). |
| `payroll.deductions` | arreglo de objeto | sí | Deducciones (Deduccion): ISR, cuotas IMSS y demás. |
| `payroll.deductions[].type` | string | sí | Tipo de deducción (TipoDeduccion), c_TipoDeduccion: 001 IMSS, 002 ISR… |
| `payroll.deductions[].key` | string | sí | Clave del patrón (Clave). |
| `payroll.deductions[].concept` | string | sí | Concepto (Concepto). |
| `payroll.deductions[].amount` | number | sí | Importe (Importe). |
| `payroll.other_payments` | arreglo de objeto | sí | Otros pagos (OtroPago): subsidio para el empleo. |
| `payroll.other_payments[].type` | string | sí | Tipo de otro pago (TipoOtroPago), c_TipoOtroPago: 002 subsidio para el empleo. |
| `payroll.other_payments[].key` | string | sí | Clave del patrón (Clave). |
| `payroll.other_payments[].concept` | string | sí | Concepto (Concepto). |
| `payroll.other_payments[].amount` | number | sí | Importe pagado (Importe). |
| `payroll.other_payments[].subsidy_caused` | number |  | Subsidio causado (SubsidioCausado). |
| `payroll.other_payments[].subsidy_applied` | number |  | Del subsidio causado, el ISR que evitó (no va en el XML). |
| `global` | objeto |  | Solo en una factura global. |
| `cancellation` | objeto o null | sí | La cancelación, si se pidió: estado, motivo, sustituto y cuándo. |
| `cancellation.status` | string o null | sí | pending (espera la respuesta del cliente), accepted (cancelada), rejected (el cliente la rechazó) o lapsed (venció; puede pedirla otra vez). |
| `cancellation.motive` | string o null | sí | Motivo de cancelación (c_MotivoCancelacion): 01 con errores con relación (lleva substitution), 02 con errores sin relación (por omisión), 03 no se llevó a cabo, 04 solo en una factura global, cuando una venta incluida se facturó a nombre del cliente. |
| `cancellation.substitution` | string o null | sí | El comprobante que sustituye a este (su id o su UUID), con el motivo 01. |
| `cancellation.canceled_at` | string (date-time) o null | sí | Cuándo se canceló. |
| `email` | objeto o null | sí | El envío por correo: a quién, con copia a quién y cuándo (null si no se ha enviado). |
| `email.to` | string o null | sí | A quién (correos separados por comas). |
| `email.cc` | string o null | sí | Con copia (correos separados por comas). |
| `email.sent_at` | string (date-time) o null | sí | Cuándo se envió. |
| `error` | objeto o null | sí | Por qué el SAT o el PAC no lo aceptaron: mensaje, código del SAT y texto original. |
| `error.message` | string | sí | Qué pasó y cómo corregirlo, para una persona. |
| `error.sat_code` | string o null | sí | Código del SAT o del PAC (CFDI40xxx). |
| `error.raw` | string | sí | El texto original del PAC. |
| `recurring_invoice` | string o null | sí | La factura recurrente (rin_…) que la timbró sola, o null si se timbró con una llamada. |
| `created_at` | string (date-time) o null | sí | Cuándo se creó, ISO 8601 con la hora de la Ciudad de México (-06:00). |
| `metadata` | objeto | sí | Sus propios datos: hasta 50 llaves de 40 caracteres con valores de texto de hasta 500. No van al CFDI; vuelven en el objeto y en los webhooks. |
| `warnings` | arreglo de string |  | Avisos que no impidieron timbrar (por ejemplo, el XML se guardará después). |
| `email_error` | string |  | Por qué no se pudo mandar el correo; el comprobante sí se timbró. |
| `substitutes` | objeto |  | La factura que esta sustituyó y si quedó cancelada. |
| `substitutes.invoice` | string | sí | La factura sustituida (inv_…). |
| `substitutes.canceled` | boolean | sí | true si la sustituida ya quedó cancelada. |
| `substitutes.cancel_error` | string |  | Por qué no se pudo cancelar la sustituida (cancélela con POST /v1/invoices/{id}/cancel). |
| `advance_application` | objeto |  | La aplicación del anticipo: método, nota de aplicación y su estado. |
| `advance_application.advance` | string o null | sí | El anticipo, como factura (inv_…). |
| `advance_application.advance_uuid` | string | sí | El folio fiscal del anticipo. |
| `advance_application.method` | `egreso`, `remanente` | sí | egreso (la factura completa y después una nota de crédito por el anticipo, opción A) o remanente (la factura solo por lo que falta, opción B). |
| `advance_application.status` | `done`, `credit_note_pending` | sí | done (listo) o credit_note_pending (falta timbrar la nota de aplicación: repita la solicitud con la misma Idempotency-Key). |
| `advance_application.credit_note` | string o null | sí | La nota de aplicación del anticipo (inv_…), con method egreso. |
| `advance_application.credit_note_error` | string |  | Por qué no se timbró la nota de aplicación (repita con la misma Idempotency-Key). |

```json
{
  "id": "inv_OufpKqnrvx9p0Nfbydl9jG4UNGeTYcvdrg",
  "object": "invoice",
  "livemode": false,
  "issuer": "iss_OufpKqnrvx9p",
  "branch": null,
  "type": "I",
  "status": "valid",
  "uuid": "5F1E8C2A-3B7D-4C9E-A1B2-C3D4E5F60718",
  "series": null,
  "folio": "1",
  "date": "2026-10-24T10:15:42",
  "customer": {
    "tax_id": "ICV060329BY0",
    "legal_name": "INMOBILIARIA CVA",
    "tax_system": "601",
    "zip": "33826"
  },
  "use": "I04",
  "payment_form": "03",
  "payment_method": "PUE",
  "currency": "MXN",
  "exchange_rate": null,
  "items": [
    {
      "description": "Mensualidad",
      "product_key": "86121700",
      "unit_key": "E48",
      "unit_name": "Unidad de servicio",
      "sku": "MEN-1",
      "quantity": 2,
      "unit_price": 2500,
      "taxability": "02",
      "iva": "0.16"
    }
  ],
  "subtotal": 5000,
  "discount": 0,
  "taxes": {
    "iva": 800,
    "ieps": 0,
    "iva_withheld": 0,
    "isr_withheld": 0,
    "local_transferred": 0,
    "local_withheld": 0
  },
  "total": 5800,
  "payment_status": "paid",
  "amount_due": 0,
  "amount_paid": 5800,
  "related": null,
  "cancellation": null,
  "email": null,
  "error": null,
  "recurring_invoice": null,
  "created_at": "2026-10-24T10:15:42-06:00",
  "metadata": {}
}
```

## Errores

Puede responder 400, 401, 402, 403, 404, 409, 422, 429, 500 con el cuerpo de error de siempre; cada código está en https://fiscalisto.com/docs/api/errores.md.
