Saltar al contenido

API de complemento de pago, el REP desde tu sistema

Cuando tu cliente paga una factura PPD, envías el recibo electrónico de pago (Pagos 2.0) en JSON y recibes el CFDI timbrado, ultrarrápido y válido ante el SAT, con su XML y su PDF. Es el mismo endpoint y la misma llave que usas para facturar; cada REP timbrado usa 1 folio.

Lo que resuelve la API del REP

Todo lo que lleva un complemento de pago 2.0, desde tu sistema de cobranza o tu ERP.

El mismo endpoint

El REP se timbra con POST /invoice/create, igual que una factura: TipoDeComprobante "P" y el complemento en Complemento.Pagos20.

Parcialidades y varias facturas

Cada Pago lleva sus DoctoRelacionado con NumParcialidad, ImpSaldoAnt, ImpPagado e ImpSaldoInsoluto. Un REP puede saldar varias facturas y registrar varios pagos.

Impuestos del pago

ImpuestosDR por documento, ImpuestosP por pago y los Totales del complemento: IVA al 16%, al 8% y al 0%, exento y retenciones.

Sin campos que el SAT no admite

En un REP, la API quita FormaPago y MetodoPago del comprobante antes de timbrar.

Relacionado con la factura

Al timbrar, el REP queda relacionado con las facturas de tu cuenta que salda. GET /invoice/relations te muestra esa relación.

Envío a tu cliente

Con enviar_mail en el JSON, el REP se envía por correo a tu cliente en cuanto se timbra.

El pago de una factura PPD, de la petición a la respuesta

Tu cliente pagó por transferencia una factura de $1,000.00 más IVA. El JSON va en el campo json de POST /invoice/create, con tu llave en el header X-Api-Key.

Endpoints
POST /invoice/create
JSON con TipoDeComprobante P y Complemento.Pagos20. Armamos el XML, lo sellamos con tu CSD y lo timbramos.
GET /invoice/relations
Con el UUID de una factura en el header Uuid, devuelve sus CFDI relacionados, entre ellos sus REP.
POST /invoice/stampxml
Si tu sistema ya genera y sella el XML del REP, lo envías en Base64.
  • El comprobante va en ceros: SubTotal y Total 0, Moneda XXX y UsoCFDI CP01.
  • FormaPago y MetodoPago no van en el REP; si los mandas, la API los quita.
  • Folio "AUTO" toma el siguiente folio de tu serie de pagos.
  • IdDocumento es el UUID de la factura que se paga.
Producción
https://app.facturadigital.com.mx/api/v5
Sandbox
https://sandbox-app.facturadigital.com.mx/api/v5
timbrar-rep.shDatos de muestra
# FD_API=https://sandbox-app.facturadigital.com.mx/api/v5
curl -X POST "$FD_API/invoice/create" \
  -H "X-Api-Key: $FD_API_KEY" \
  --data-urlencode "json@recibo-de-pago.json"
recibo-de-pago.jsonDatos de muestra
{
  "Version": "4.0",
  "Serie": "P",
  "Folio": "AUTO",
  "Fecha": "AUTO",
  "SubTotal": "0",
  "Moneda": "XXX",
  "Total": "0",
  "TipoDeComprobante": "P",
  "Exportacion": "01",
  "LugarExpedicion": "64000",
  "Emisor": { "RegimenFiscal": "601" },
  "Receptor": {
    "Rfc": "XIA190128J61",
    "Nombre": "XENON INDUSTRIAL ARTICLES",
    "DomicilioFiscalReceptor": "76343",
    "RegimenFiscalReceptor": "601",
    "UsoCFDI": "CP01"
  },
  "Conceptos": [{
    "ClaveProdServ": "84111506",
    "Cantidad": "1",
    "ClaveUnidad": "ACT",
    "Descripcion": "Pago",
    "ValorUnitario": "0",
    "Importe": "0",
    "ObjetoImp": "01"
  }],
  "Complemento": {
    "Pagos20": {
      "Totales": {
        "TotalTrasladosBaseIVA16": "1000.00",
        "TotalTrasladosImpuestoIVA16": "160.00",
        "MontoTotalPagos": "1160.00"
      },
      "Pago": [{
        "FechaPago": "2026-09-22T12:00:00",
        "FormaDePagoP": "03",
        "MonedaP": "MXN",
        "TipoCambioP": "1",
        "Monto": "1160.00",
        "DoctoRelacionado": [{
          "IdDocumento": "0B7C2E51-8A4D-4E0F-A1C3-7D9E6F2B5A10",
          "Serie": "F",
          "Folio": "2231",
          "MonedaDR": "MXN",
          "EquivalenciaDR": "1",
          "NumParcialidad": "1",
          "ImpSaldoAnt": "1160.00",
          "ImpPagado": "1160.00",
          "ImpSaldoInsoluto": "0.00",
          "ObjetoImpDR": "02",
          "ImpuestosDR": {
            "TrasladosDR": [{
              "BaseDR": "1000.00",
              "ImpuestoDR": "002",
              "TipoFactorDR": "Tasa",
              "TasaOCuotaDR": "0.160000",
              "ImporteDR": "160.00"
            }]
          }
        }],
        "ImpuestosP": {
          "TrasladosP": [{
            "BaseP": "1000.00",
            "ImpuestoP": "002",
            "TipoFactorP": "Tasa",
            "TasaOCuotaP": "0.160000",
            "ImporteP": "160.00"
          }]
        }
      }]
    }
  },
  "enviar_mail": {
    "destinatarios": "cliente@facturadigital.com.mx"
  }
}
respuesta-200.jsonDatos de muestra
{
  "message": "The document was generated successfully",
  "code": 200,
  "cfdi": {
    "UUID": "6FA90F39-2D7A-4F1C-9B3E-5C1D8A0E7B42",
    "FechaTimbrado": "2026-09-22T12:04:31",
    "XmlBase64": "PD94bWwgdmVyc2lvbj0iMS4wIi...",
    "PDF": "https://app.facturadigital.com.mx/docs/pdf/6FA90F39-...",
    "XML": "https://app.facturadigital.com.mx/docs/xml/...",
    "Serie": "P",
    "Folio": "318",
    ...
  }
}

Intégralo en 4 pasos

De la factura PPD al REP timbrado.

  1. 01

    Timbra la factura en PPD

    La factura original lleva MetodoPago PPD y FormaPago 99. Guarda su UUID: será el IdDocumento del REP.

  2. 02

    Configura la serie de pagos

    Para usar Folio "AUTO", da de alta una serie para el tipo de comprobante P en Configuración → Series y Folios.

  3. 03

    Arma el REP con cada pago

    Por cada pago: fecha, forma de pago, monto y los documentos que salda, con su parcialidad, saldo anterior, importe pagado y saldo insoluto.

  4. 04

    Timbra y envíalo

    Llama a POST /invoice/create y guarda UUID, Serie y Folio de la respuesta. Con enviar_mail, el REP le llega a tu cliente.

Errores frecuentes y cómo resolverlos

Los errores responden con HTTP 400 y un code en el cuerpo. Si el REP no se timbra, no se usa folio.

702El REP no cumple el esquema del SAT: falta un atributo obligatorio o un valor no tiene el formato del catálogo.Revisa errors: cada error trae el elemento, el campo y el mensaje en español.
400Folio "AUTO" sin serie para pagos: «No folio range found for Serie='P' and TipoDeComprobante='P'».Da de alta la serie de pagos en Configuración → Series y Folios, o manda tu propio folio.
400No llegó el campo json: «Invalid or non received json in headers or body.»Manda el JSON en el campo json del body (application/x-www-form-urlencoded).
HTTP 400Se rechazó el timbrado porque el código postal del receptor no coincide con el SAT: «El campo Codigo Postal (DomicilioFiscalReceptor) no coincide con los registros del SAT».Usa el código postal que aparece en la Constancia de Situación Fiscal de tu cliente.
601 · 602Tu cuenta no tiene folios disponibles (601) o no tiene un CSD activo (602).Consulta tu saldo con GET /account/balance y sube tu CSD en Configuración → Certificados.
501La llave X-Api-Key no es válida o es de otro ambiente; el mensaje termina con [Environment: …].Usa la llave del ambiente al que llamas: sandbox y producción tienen llaves distintas.
5037 · 50345037: no se pudo conectar para timbrar. 5034: no hubo respuesta al timbrar.Con 5037 puedes reintentar. Con 5034 el REP pudo haberse timbrado: búscalo en el SAT con la Serie y el Folio de la respuesta antes de reintentar.

Sigue con

Carta Porte 3.1

Timbra CFDI de ingreso y traslado con el complemento Carta Porte y las reglas del SAT revisadas antes de timbrar.

Complementos de pago en la web

Qué es el REP, cuándo se emite y cómo se registra un pago desde la app.

Sandbox

Ambiente de pruebas gratis con la misma API v5 que producción.

Webhooks

Que tu sistema se entere de lo que pasa en tu cuenta sin consultar la API.

API v5

Autenticación, endpoints y las tres formas de timbrar: JSON, XML en Base64 o archivo XML.

Preguntas sobre la API del REP

¿Algo que no está aquí? Escríbenos o revisa la referencia completa.

¿Qué endpoint uso para timbrar un complemento de pago?

POST /invoice/create, el mismo que para una factura. Mandas TipoDeComprobante "P" y el complemento en Complemento.Pagos20; la respuesta es la misma: UUID, XML en Base64 y ligas al PDF y al XML.

¿El REP usa folio?

Sí. Cada CFDI timbrado usa 1 folio, también el REP. La API está incluida: pagas folios, no la API, y los folios no caducan.

¿Puedo saldar varias facturas en un solo REP?

Sí. Cada Pago acepta varios DoctoRelacionado y el complemento acepta varios Pago. Los importes de todo el complemento van en Pagos20.Totales.

¿La API calcula los saldos y los Totales?

No. Los mandas tú: ImpSaldoAnt, ImpPagado e ImpSaldoInsoluto por documento, y los Totales del complemento. La API arma el XML, quita FormaPago y MetodoPago, lo valida contra el esquema del SAT y lo timbra.

¿Cómo sé qué REP tiene una factura?

Con GET /invoice/relations y el UUID de la factura en el header Uuid. En padres vienen los CFDI que la relacionan, incluidos los REP timbrados en tu cuenta.

¿Puedo enviar el REP a mi cliente por correo?

Sí. Agrega enviar_mail al JSON con destinatarios (y, si quieres, bcc y mensaje) y el REP se envía en cuanto se timbra. En el sandbox los correos no les llegan a tus clientes: se desvían a un buzón de pruebas.

Mi sistema ya genera el XML del REP. ¿Puedo timbrarlo tal cual?

Sí. Envíalo sellado a /invoice/stampxml (Base64) o a /invoice/stampxmlfile (archivo). Estos dos endpoints no agregan el documento a tus listados de la API.

Timbra tu primer REP en el sandbox

Es gratis y usa la misma API v5 que producción. Cuando funcione, cambias la URL base y la llave.