Skip to content
Last updated

El endpoint de timbrado de CFDI 4.0 permite a los clientes de QRwey! generar y timbrar facturas de ingreso directamente a través del API, sin necesidad de generar un código QR previo.

Este flujo es ideal cuando el sistema del cliente controla completamente los datos de la transacción y del receptor.


Endpoint

POST /v1/qrs/invoices

Host (DEV):

https://api-dev.qrwey.com

Host (PROD):

https://api.qrwey.com

Headers requeridos

Authorization: Bearer {{access_token}}
Content-Type: application/json

Request body

Campos principales

CampoDescripción
sale_idIdentificador de la venta, generado por el cliente
seriesSerie del comprobante (opcional)
dateFecha de emisión en formato ISO 8601 (requerido)
expedition_zip_codeCódigo postal del lugar de expedición (requerido)
amountTotal de la operación (requerido)
subtotalSubtotal antes de impuestos (requerido)
currencyMoneda (ej. MXN) (requerido)
exchange_rateTasa de cambio, necesario si currency es diferente a MXN
sat_payment_formForma de pago SAT (ej. 04 Tarjeta de crédito)
sat_payment_methodMétodo de pago SAT (PUE o PPD)
type_of_receiptTipo de comprobante: I para factura de ingreso (requerido)
export_codeCódigo de exportación SAT (ej. 01 No aplica) (requerido)

Conceptos (items)

Cada elemento representa un concepto del CFDI:

CampoDescripción
skuIdentificador interno del producto
descriptionDescripción del concepto (requerido)
amountImporte del concepto (requerido)
quantityCantidad (requerido)
discountDescuento aplicado
sat_unit_keyClave de unidad SAT, ej. LTR (requerido)
unit_pricePrecio unitario (requerido)
sat_product_service_keyClave producto/servicio SAT (requerido)
sat_tax_object_keyObjeto de impuesto SAT, ej. 02 (requerido)
taxesImpuestos aplicables al concepto

Impuestos del concepto (taxes)

CampoDescripción
typeTipo de impuesto: Traslado o Retencion (requerido)
taxClave del impuesto SAT, ej. 002 IVA (requerido)
factorTipo de factor: Tasa, Cuota o Exento (requerido)
rateTasa o cuota del impuesto, ej. 0.160000 (requerido)
taxable_baseBase imponible (requerido)
amountMonto del impuesto (requerido)

Emisor (issuer)

CampoDescripción
rfcRFC del emisor (requerido)
business_nameRazón social del emisor (opcional, ver lógica de resolución)
tax_regime_codeClave del régimen fiscal SAT (opcional, ver lógica de resolución)
sat_credentialsCredenciales del CSD en formato base64 (opcional)

Lógica de resolución del emisor

El campo rfc es el único requerido en el objeto issuer. El sistema resuelve el emisor con la siguiente lógica:

  1. Si se proporciona business_name y tax_regime_code: el sistema auto-crea o actualiza los registros de InvoiceData, Merchant y CSD (si sat_credentials también está presente). Esto permite al cliente registrar un emisor al vuelo durante el timbrado.

  2. Si solo se proporciona rfc: el sistema busca un emisor activo existente registrado con ese RFC en la cuenta del customer.

⚠️ Si usas la opción 2 y no existe un emisor activo con ese RFC, la operación fallará con error 404.

Credenciales SAT (sat_credentials)

CampoDescripción
base64CerCertificado CSD codificado en base64
base64KeyLlave privada CSD codificada en base64
passwordContraseña de la llave privada

Receptor (recipient)

CampoDescripción
rfcRFC del receptor (requerido)
business_nameRazón social del receptor (requerido)
zip_codeCódigo postal del domicilio fiscal (requerido)
tax_regime_codeClave del régimen fiscal SAT (requerido)
cfdi_use_codeClave de uso del CFDI SAT, ej. G03 (requerido)
emailCorreo electrónico del receptor (opcional)

CampoDescripción
tipo_relacionTipo de relación entre CFDIs, ej. 04 Sustitución
cfdisLista de UUIDs de los CFDIs relacionados

Información global (global_info) - Opcional

Para comprobantes globales de operaciones con público en general:

CampoDescripción
periodicityPeriodicidad SAT, ej. 04 Mensual
monthsMes SAT, ej. 12 Diciembre
yearAnio a cuatro dígitos

Ejemplo de request (DEV)

curl -X POST "https://api-dev.qrwey.com/v1/qrs/invoices" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "Content-Type: application/json" \
  -d '{
    "sale_id": "fcd68791-6a27-412f-a50f-8d47b7bc34d2",
    "series": "A",
    "date": "2026-03-19T14:30:00",
    "expedition_zip_code": "06600",
    "amount": 1160.00,
    "subtotal": 1000.00,
    "currency": "MXN",
    "exchange_rate": 1.0,
    "sat_payment_form": "04",
    "sat_payment_method": "PUE",
    "type_of_receipt": "I",
    "export_code": "01",
    "items": [
      {
        "sku": "GAS87",
        "description": "Gasolina Magna",
        "amount": 1000.00,
        "quantity": 49.210,
        "discount": 0.00,
        "sat_unit_key": "LTR",
        "unit_price": 20.321,
        "sat_product_service_key": "15101515",
        "sat_tax_object_key": "02",
        "taxes": [
          {
            "type": "Traslado",
            "tax": "002",
            "factor": "Tasa",
            "rate": "0.160000",
            "taxable_base": 1000.00,
            "amount": 160.00
          }
        ]
      }
    ],
    "issuer": {
      "rfc": "FUNK671228PH6",
      "business_name": "KARLA FUENTE NOLASCO",
      "tax_regime_code": "601"
    },
    "recipient": {
      "rfc": "EKU9003173C9",
      "business_name": "ESCUELA KEMPER URGATE",
      "zip_code": "42501",
      "tax_regime_code": "601",
      "cfdi_use_code": "G03",
      "email": "receptor@ejemplo.com"
    },
    "related_cfdis": null,
    "global_info": null
  }'

Respuesta

{
  "invoiceStatus": "GENERATED",
  "folioUuid": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
  "sourceTaxId": "FUNK671228PH6",
  "sourceLegalName": "KARLA FUENTE NOLASCO",
  "targetTaxId": "EKU9003173C9",
  "targetLegalName": "ESCUELA KEMPER URGATE",
  "subtotal": 1000.00,
  "iva": 160.00,
  "total": 1160.00,
  "invoiceDate": "2026-03-19T14:30:00Z",
  "invoiceError": null,
  "base64Xml": "PD94bWwgdmVyc2lvbj0iMS4wIiBlb..."
}

Campos de la respuesta

CampoDescripción
invoiceStatusEstado del timbrado: GENERATED, ERROR
folioUuidUUID fiscal asignado por el SAT
sourceTaxIdRFC del emisor
sourceLegalNameRazón social del emisor
targetTaxIdRFC del receptor
targetLegalNameRazón social del receptor
subtotalSubtotal del CFDI
ivaIVA calculado
totalTotal del CFDI
invoiceDateFecha de timbrado
invoiceErrorDescripción del error (solo cuando invoiceStatus = ERROR, de lo contrario es null)
base64XmlXML timbrado codificado en base64 (solo cuando invoiceStatus = GENERATED)

Errores comunes

CódigoMotivo
400Campos requeridos faltantes, datos del CFDI invalidos
401Token inválido o expirado
404Emisor no encontrado o no tiene llaves CSD configuradas
409La venta ya fue facturada anteriormente (duplicado por sale_id)
422Error de reglas de negocio del SAT (RFC inválido, régimen incorrecto, etc.)

Consulta: Manejo de errores


Buenas prácticas

  • Verifica que el emisor tenga llaves CSD configuradas antes de timbrar
  • Usa sale_id como referencia interna para correlacionar con tu sistema
  • Valida que los campos del receptor (RFC, razón social, código postal, régimen fiscal) sean correctos segun la Constancia de Situación Fiscal
  • Para emisores recurrentes, registra el emisor previamente y usa solo el rfc en el request
  • Guarda el folioUuid y las URLs del XML/PDF para tu registro contable

¿Qué sigue?