API Reference

API Reference

La API de FiscaFacil te permite generar facturas electronicas (CFDI 4.0), gestionar clientes, productos y calcular nomina de forma programatica.

Base URL
https://api.fiscafacil.mx
Formato de Respuesta
{ success, data | error }
Respuesta exitosa
{
  "success": true,
  "data": { ... }
}
Respuesta de error
{
  "success": false,
  "error": {
    "code": "CFDI_001",
    "message": "Datos invalidos",
    "details": { ... }
  }
}
Autenticacion

Los endpoints protegidos aceptan dos tipos de auth: Session cookie (para el dashboard) o API Key (para agentes e integraciones). Los API keys usan el header Authorization: Bearer ff_...

Header x-empresa-id

Los endpoints de clientes, productos y CFDI requieren el header x-empresa-id para indicar sobre cual empresa operar.

Sandbox Mode

Las empresas se crean en sandbox por defecto. En sandbox, el endpoint de timbrado valida todo internamente (CSD, XML, cadena original, sello RSA-SHA256) pero no llama al PAC. Retorna un UUID con prefijo SANDBOX- y status TIMBRADO_SANDBOX. No consume timbres. Para timbrar de verdad, cambia la empresa a sandbox: false.

Response Mode Header

Toda respuesta autenticada incluye el header X-FiscaFacil-Mode: sandbox | live y un campo "mode": "sandbox" en el JSON body. Usa esto para validar programaticamente en que modo estas operando: assert(response.mode === 'sandbox').

Para AI Agents

GET /llms.txt — indice de docs para LLMs. GET /llms-full.txt — toda la doc en un solo archivo Markdown. GET /api/docs — spec JSON para consumo programatico.

Autenticacion

Registro de Usuario

POST/api/auth/register
Publico

Crea una cuenta nueva. Requerido antes de poder crear API keys.

ParametroTipoDescripcion
namerequiredstringNombre completo (min 2 chars)
emailrequiredstringEmail unico
passwordrequiredstringMin 8 chars, 1 mayuscula, 1 numero, 1 especial
Request
curl -X POST https://api.fiscafacil.mx/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Juan Perez",
    "email": "juan@empresa.com",
    "password": "MiPassword123!"
  }'
Response 201
{
  "success": true,
  "data": {
    "id": "clx...",
    "email": "juan@empresa.com",
    "name": "Juan Perez"
  }
}

Login (Session)

POST/api/auth/callback/credentials
Publico

Inicia sesion via NextAuth. Retorna una cookie de sesion necesaria para crear API keys.

Request
curl -X POST https://api.fiscafacil.mx/auth/callback/credentials \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "email": "juan@empresa.com",
    "password": "MiPassword123!"
  }'

Crear API Key

POST/api/api-keys
Session, API Key, o Email+Password

Genera un API key para acceso programatico. Acepta 3 metodos de autenticacion: sesion (dashboard), API key existente (rotacion), o email+password (primera vez via API). El key completo solo se muestra una vez — guardalo de forma segura.

ParametroTipoDescripcion
namerequiredstringNombre descriptivo del key
expiresInDaysnumberDias hasta expiracion (omitir = sin expiracion)
emailstringEmail de tu cuenta (solo para auth via credenciales)
passwordstringPassword de tu cuenta (solo para auth via credenciales)
Request
# Opcion 1: con email+password (primera vez, sin sesion)
curl -X POST https://api.fiscafacil.mx/api-keys \
  -H "Content-Type: application/json" \
  -d '{
    "email": "tu@email.com",
    "password": "TuPassword123!",
    "name": "Mi Agent",
    "expiresInDays": 90
  }'
Response 201
{
  "success": true,
  "data": {
    "id": "clx...",
    "name": "Mi Agent",
    "key": "ff_a1b2c3d4e5f67890abcdef...",
    "keyPrefix": "ff_a1b2c3d4",
    "expiresAt": "2026-06-24T00:00:00.000Z"
  }
}

Guarda el campo key — no se puede recuperar despues.

Listar API Keys

GET/api/api-keys
Session (cookie)

Lista todos los API keys del usuario. Solo muestra el prefijo, nunca el key completo.

Response 200
{
  "success": true,
  "data": [
    {
      "id": "clx...",
      "name": "Mi Agent",
      "keyPrefix": "ff_a1b2c3d4",
      "active": true,
      "lastUsedAt": "2026-03-26T...",
      "expiresAt": "2026-06-24T...",
      "createdAt": "2026-03-26T..."
    }
  ]
}

Revocar API Key

DELETE/api/api-keys
Session (cookie)
ParametroTipoDescripcion
idrequiredstringID del API key a revocar
Response 200
{ "success": true, "data": { "revoked": true } }

Empresas

Crear Empresa

POST/api/empresas
Session o API Key

Crea una empresa. El usuario que la crea es automaticamente asignado como PROPIETARIO.

ParametroTipoDescripcion
rfcrequiredstringRFC de la empresa (12-13 chars)
razonSocialrequiredstringRazon social o nombre
regimenFiscalrequiredstringClave del regimen fiscal SAT (ej: 601)
codigoPostalrequiredstringCP del domicilio fiscal
nombreComercialstringNombre comercial
sandboxbooleanDefault: true. Sandbox valida todo pero no llama al PAC.
Request
curl -X POST https://api.fiscafacil.mx/empresas \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rfc": "EKU9003173C9",
    "razonSocial": "ESCUELA KEMPER URGATE",
    "regimenFiscal": "601",
    "codigoPostal": "06600"
  }'
Response 201
{
  "success": true,
  "data": {
    "id": "clx...",
    "rfc": "EKU9003173C9",
    "razonSocial": "ESCUELA KEMPER URGATE",
    "regimenFiscal": "601",
    "codigoPostal": "06600",
    "seriePredeterminada": "A",
    "folioActual": 1
  }
}

Listar Empresas

GET/api/empresas
Session o API Key

Lista las empresas a las que el usuario tiene acceso, con su rol en cada una.

Response 200
{
  "success": true,
  "data": [
    {
      "id": "clx...",
      "rfc": "EKU9003173C9",
      "razonSocial": "ESCUELA KEMPER URGATE",
      "csdConfigured": true,
      "csdVigenciaFin": "2027-05-15T...",
      "role": "PROPIETARIO"
    }
  ]
}

Subir CSD

POST/api/empresas/{empresaId}/certificados
Session o API Key + x-empresa-id

Sube el Certificado de Sello Digital (CSD) para habilitar timbrado en produccion. Valida que el .cer y .key correspondan, que la contrasena sea correcta y que el certificado no este expirado. En sandbox no es necesario subir CSD.

ParametroTipoDescripcion
cerBase64requiredstringArchivo .cer codificado en base64
keyBase64requiredstringArchivo .key codificado en base64
passwordrequiredstringContrasena del CSD (la que se creo al generarlo en el SAT)
Request
# Codifica tus archivos en base64
CER_B64=$(base64 -w 0 certificado.cer)   # Linux
KEY_B64=$(base64 -w 0 llave.key)          # macOS: base64 -i

curl -X POST https://api.fiscafacil.mx/empresas/clx_EMPRESA_ID/certificados \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d "{
    \"cerBase64\": \"$CER_B64\",
    \"keyBase64\": \"$KEY_B64\",
    \"password\": \"12345678a\"
  }"
Response 201
{
  "success": true,
  "data": {
    "noCertificado": "30001000000500003456",
    "vigenciaFin": "2027-05-15T00:00:00.000Z",
    "empresaId": "clx..."
  }
}

Errores posibles

CodigoCausa
CSD_001Falta cerBase64, keyBase64 o password
CSD_002El .cer y .key no coinciden, o la contrasena es incorrecta
CSD_003El certificado esta expirado — renovar en sat.gob.mx

Subir FIEL (e.firma)

POST/api/empresas/{empresaId}/fiel
Session o API Key + x-empresa-id

Sube la FIEL (e.firma) para habilitar descarga de CFDIs del SAT. La FIEL es un certificado distinto del CSD — se obtiene directamente del SAT con tu cita presencial y se usa para tramites oficiales como Descarga Masiva de CFDI.

FIEL vs CSD: el CSD se usa para emitir facturas (firmar XML). La FIEL se usa para tramites fiscales (descargar CFDIs, consultar declaraciones, etc). Son certificados diferentes, con contrasenas distintas, aunque ambos vienen como pares .cer + .key.
ParametroTipoDescripcion
cerBase64requiredstringArchivo .cer de la FIEL en base64
keyBase64requiredstringArchivo .key de la FIEL en base64
passwordrequiredstringContrasena de la llave privada de la FIEL
Request
CER_B64=$(base64 -w 0 fiel.cer)
KEY_B64=$(base64 -w 0 fiel.key)

curl -X POST https://api.fiscafacil.mx/empresas/clx_EMPRESA_ID/fiel \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d "{
    \"cerBase64\": \"$CER_B64\",
    \"keyBase64\": \"$KEY_B64\",
    \"password\": \"contrasena_fiel\"
  }"
Response 201
{
  "success": true,
  "data": {
    "noCertificado": "00001000000500003456",
    "vigenciaFin": "2028-05-15T00:00:00.000Z",
    "empresaId": "clx..."
  }
}

Errores posibles

CodigoCausa
FIEL_001Falta cerBase64, keyBase64 o password
FIEL_002El .cer y .key no coinciden, o la contrasena es incorrecta
FIEL_003La FIEL esta expirada — renovar en sat.gob.mx

Estado de FIEL

GET/api/empresas/{empresaId}/fiel
Session o API Key + x-empresa-id

Verifica si la empresa tiene FIEL configurada, su numero de certificado y fecha de vigencia. Util para mostrar el estado en dashboards antes de intentar una descarga.

Response 200 — FIEL configurada
{
  "success": true,
  "data": {
    "configured": true,
    "expired": false,
    "noCertificado": "00001000000500003456",
    "vigenciaFin": "2028-05-15T00:00:00.000Z"
  }
}
Response 200 — Sin FIEL
{
  "success": true,
  "data": {
    "configured": false,
    "expired": false,
    "noCertificado": null,
    "vigenciaFin": null
  }
}

Clientes

Todos los endpoints de clientes requieren el header x-empresa-id.

Listar Clientes

GET/api/clientes?page=1&pageSize=20&q=busqueda
Session o API Key + x-empresa-id

Lista paginada con busqueda por RFC o razon social. Max 100 items por pagina.

Response 200
{
  "success": true,
  "data": {
    "items": [
      { "id": "clx...", "rfc": "XAXX010101000", "razonSocial": "PUBLICO EN GENERAL", ... }
    ],
    "total": 50,
    "page": 1,
    "pageSize": 20,
    "totalPages": 3
  }
}

Crear Cliente

POST/api/clientes
Session o API Key + x-empresa-id
ParametroTipoDescripcion
rfcrequiredstringRFC del cliente (unico por empresa)
razonSocialrequiredstringRazon social
regimenFiscalrequiredstringClave regimen fiscal SAT
codigoPostalrequiredstringCodigo postal fiscal
usoCfdistringUso del CFDI (default: G03)
emailstringEmail para envio de facturas
Request
curl -X POST https://api.fiscafacil.mx/clientes \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{ "rfc": "CACX7605101P8", "razonSocial": "CARLOS CASTRO", "regimenFiscal": "612", "codigoPostal": "44100" }'

Productos

Requiere header x-empresa-id.

Listar Productos

GET/api/productos?page=1&pageSize=20&q=busqueda
Session o API Key + x-empresa-id

Crear Producto

POST/api/productos
Session o API Key + x-empresa-id
ParametroTipoDescripcion
claveProdServrequiredstringClave SAT del producto/servicio
claveUnidadrequiredstringClave SAT de unidad (E48=servicio, H87=pieza)
descripcionrequiredstringDescripcion del producto
precioUnitariorequirednumberPrecio unitario en MXN
ivaRatenumberTasa de IVA (default: 0.16)
Request
curl -X POST https://api.fiscafacil.mx/productos \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{ "claveProdServ": "84111506", "claveUnidad": "E48", "descripcion": "Servicio de consultoria fiscal", "precioUnitario": 5000.00 }'

CFDI Timbrado

Timbrar CFDI 4.0

POST/api/cfdi/timbrar
Session o API Key + x-empresa-id

Pipeline completo: construye XML CFDI 4.0, sella con CSD de la empresa, y envia al PAC para timbrado. Requiere CSD configurado.

ParametroTipoDescripcion
tipoComprobante"I"|"E"|"T"|"P"I=Ingreso (default), E=Egreso, T=Traslado, P=Pago
formaPagostring01=Efectivo, 03=Transferencia, 04=Tarjeta credito
metodoPago"PUE"|"PPD"PUE=Una exhibicion, PPD=Parcialidades
monedastringDefault: MXN
clienteIdstringID del cliente (omitir = PUBLICO EN GENERAL)
conceptosrequiredarrayLista de conceptos (ver schema abajo)
Concepto Schema:
ParametroTipoDescripcion
claveProdServrequiredstringClave SAT del producto/servicio
claveUnidadrequiredstringClave SAT de unidad
descripcionrequiredstringDescripcion
cantidadrequirednumberCantidad (> 0)
precioUnitariorequirednumberPrecio unitario
descuentonumberDescuento (default: 0)
objetoImpuesto"01"|"02"|"03"02=Objeto IVA (default). Si 02 y no envias impuestos, IVA 16% se calcula auto.
Request
curl -X POST https://api.fiscafacil.mx/cfdi/timbrar \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "tipoComprobante": "I",
    "formaPago": "03",
    "metodoPago": "PUE",
    "conceptos": [{
      "claveProdServ": "84111506",
      "claveUnidad": "E48",
      "descripcion": "Servicio de consultoria fiscal",
      "cantidad": 1,
      "precioUnitario": 10000.00,
      "objetoImpuesto": "02"
    }]
  }'
Response 201
{
  "success": true,
  "data": {
    "cfdiId": "clx...",
    "uuid": "ABC12345-6789-...",
    "fechaTimbrado": "2026-03-26T12:30:00Z",
    "xmlUrl": "cfdis/EKU9003173C9/ABC12345-6789-....xml",
    "xmlUploaded": true,
    "serie": "A",
    "folio": "1",
    "total": 11600.00
  }
}

Nomina

Calculo Gross-to-Net

POST/api/nomina/calcular
Publico (sin auth)

Motor de calculo de nomina mexicana. Retorna desglose completo de ISR (Art. 96 LISR), subsidio al empleo, cuotas IMSS y neto a pagar.

ParametroTipoDescripcion
salarioDiariorequirednumberSalario diario en MXN
salarioDiarioIntegradorequirednumberSDI (salario + prestaciones integradas)
diasPagadosrequirednumberDias del periodo (7, 15, 30)
periodicidadrequired"semanal"|"quincenal"|"mensual"Periodicidad de pago
riesgoPuestorequired"1"-"5"1=Clase I ... 5=Clase V
percepcionesarrayPercepciones adicionales [{tipo, concepto, importe, gravado, exento}]
deduccionesarrayDeducciones adicionales [{tipo, concepto, importe}]
Request
curl -X POST https://api.fiscafacil.mx/nomina/calcular \
  -H "Content-Type: application/json" \
  -d '{
    "salarioDiario": 500,
    "salarioDiarioIntegrado": 570,
    "diasPagados": 15,
    "periodicidad": "quincenal",
    "riesgoPuesto": "1"
  }'
Response 200
{
  "success": true,
  "data": {
    "percepciones": {
      "sueldoBase": 7500.00,
      "totalGravado": 7500.00,
      "totalExento": 0,
      "totalPercepciones": 7500.00
    },
    "deducciones": {
      "isrBruto": 844.29,
      "subsidioAlEmpleo": 0,
      "isrRetenido": 844.29,
      "imssEmpleado": 149.00,
      "totalDeducciones": 993.29
    },
    "otrosPagos": {
      "subsidioEntregado": 0,
      "totalOtrosPagos": 0
    },
    "netoAPagar": 6506.71,
    "desglose": {
      "baseGravableISR": 7500.00,
      "rangoISR": "21.36%",
      "cuotaFija": 692.96,
      "excedenteLimInf": 708.57,
      "isrMarginal": 151.33,
      "imssDesglose": {
        "enfermedadYMaternidad": 81.38,
        "invalidezYVida": 53.44,
        "cesantiaYVejez": 96.19,
        "total": 149.00
      }
    }
  }
}

Listar CFDIs

GET/api/cfdi
Session o API Key + x-empresa-id

Lista todas las facturas de la empresa (emitidas y recibidas) con paginacion y filtros. Los CFDIs recibidos aparecen aqui despues de sincronizar con el SAT.

ParametroTipoDescripcion
pagenumberPagina (default: 1)
limitnumberResultados por pagina (max: 100, default: 50)
statusstringFiltrar por status: TIMBRADO, CANCELADO
tipostringFiltrar por tipo de comprobante: I, E, T, P, N
desdedateFecha inicio (ISO 8601)
hastadateFecha fin (ISO 8601)
searchstringBuscar por UUID, folio, o nombre del cliente
Request
# Listar facturas recibidas de enero 2026
curl "https://api.fiscafacil.mx/cfdi?desde=2026-01-01&hasta=2026-01-31&limit=100&page=1" \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID"
Response 200
{
  "success": true,
  "data": {
    "cfdis": [
      {
        "id": "clx_cfdi_123...",
        "uuid": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB",
        "tipo": "RECIBIDA",
        "origen": "SAT_DESCARGA",
        "tipoComprobante": "I",
        "serie": "A",
        "folio": "12345",
        "fecha": "2026-01-15T10:30:00.000Z",
        "total": "11600.00",
        "status": "TIMBRADO",
        "emisorRfc": "AAA010101AAA",
        "emisorNombre": "Proveedor SA de CV",
        "receptorRfc": "BBB020202BBB",
        "receptorNombre": "Mi Restaurante SA de CV",
        "xmlUrl": "cfdis/BBB020202BBB/recibidos/A1B2C3D4-....xml"
      }
    ],
    "total": 204,
    "page": 1,
    "limit": 100
  }
}
Tip: Si xmlUrl es null, el CFDI solo tiene metadata (fue encontrado en el SAT pero el XML no se pudo descargar aun). Puedes intentar descargar el XML con POST /api/cfdi/descargar-por-uuid.

Facturas Recibidas (SAT)

Descarga y consulta las facturas que recibes de tus proveedores, directamente del portal del SAT. Ideal para restaurantes que necesitan ver los insumos, productos y montos de lo que compran.

Resultados instantaneos. Conectamos directamente al portal del SAT con tu FIEL. Las consultas son sincronas — sin esperas de horas. Un mes completo con 200+ facturas se sincroniza en menos de 30 segundos.
Requisitos previos:
  • FIEL (e.firma) configurada en la empresa (POST /api/empresas/:id/fiel)
  • FIEL vigente (no vencida)
  • Permiso cfdi:descargar (rol CONTADOR o superior)

Sincronizar por mes

POST/api/cfdi/sync-recibidos
Session o API Key + x-empresa-id

Lanza un job en background que descarga todas las facturas recibidas de un mes completo del portal del SAT. Cada CFDI se parsea, se guarda en la base de datos, y el XML se sube a S3. Si un UUID ya existe, se omite (dedupe automatico).

ParametroTipoDescripcion
yearrequirednumberAno (ej: 2026)
monthrequirednumberMes (1-12)
Request
# Sincronizar todas las facturas recibidas de marzo 2026
curl -X POST https://api.fiscafacil.mx/cfdi/sync-recibidos \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{ "year": 2026, "month": 3 }'
Response 200 — Job creado
{
  "success": true,
  "data": {
    "jobId": "repeat:sync-portal:abc123",
    "status": "started",
    "year": 2026,
    "month": 3
  }
}
Tiempos tipicos:
  • Query al SAT: 2-5 segundos
  • Descarga 100 XMLs: 30-60 segundos
  • Descarga 200 XMLs: 60-120 segundos
  • Parseo + guardado en BD: 5-15 segundos

Descargar CFDI por UUID

POST/api/cfdi/descargar-por-uuid
Session o API Key + x-empresa-id

Descarga un CFDI especifico del portal del SAT por su UUID. La respuesta es sincrona — retorna el CFDI completo con todos sus conceptos en 5-10 segundos. Incluye xmlDownloadUrl — una URL firmada que permite descargar el XML directamente (valida por 1 hora).

Dedupe automatico: si ya tienes este UUID en la base de datos con XML descargado, retorna el CFDI existente con source: "cache" sin tocar al SAT.

Eventual consistency: si el SAT entrega solo metadata (sin XML), el CFDI se guarda con xmlDownloadStatus: "METADATA_ONLY" y se reintenta automaticamente en background (hasta 8 veces en ~5 dias). Cuando el XML este disponible, se dispara el webhook cfdi.xml_disponible.

ParametroTipoDescripcion
uuidrequiredstringUUID del CFDI (formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX). Tambien acepta URL completa del SAT.
Request
curl -X POST https://api.fiscafacil.mx/cfdi/descargar-por-uuid \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{ "uuid": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB" }'
Response 200 — CFDI descargado del SAT
{
  "success": true,
  "data": {
    "source": "sat_portal",
    "xmlBytes": 8542,
    "cfdi": {
      "id": "clx_cfdi_xyz...",
      "uuid": "A1B2C3D4-E5F6-7890-ABCD-1234567890AB",
      "serie": "A",
      "folio": "12345",
      "fecha": "2026-03-15T10:30:00.000Z",
      "total": 11600.00,
      "subtotal": 10000.00,
      "moneda": "MXN",
      "tipoComprobante": "I",
      "formaPago": "03",
      "metodoPago": "PUE",
      "emisorRfc": "AAA010101AAA",
      "emisorNombre": "Distribuidora de Alimentos SA",
      "emisorRegimen": "601",
      "receptorRfc": "BBB020202BBB",
      "receptorNombre": "Mi Restaurante SA de CV",
      "receptorUsoCfdi": "G03",
      "status": "TIMBRADO",
      "xmlDownloadStatus": "COMPLETE",
      "xmlDownloadUrl": "https://s3.../cfdis/BBB.../A1B2C3D4-....xml?X-Amz-Signature=...",
      "pdfDownloadUrl": null,
      "downloadExpiresIn": 3600,
      "xmlRetryCount": 0,
      "xmlNextRetryAt": null,
      "conceptos": [
        {
          "claveProdServ": "50112000",
          "claveUnidad": "KGM",
          "descripcion": "Carne de res corte New York",
          "cantidad": 20,
          "precioUnitario": 350.00,
          "importe": 7000.00,
          "descuento": 0
        },
        {
          "claveProdServ": "50101500",
          "claveUnidad": "KGM",
          "descripcion": "Verduras mixtas frescas",
          "cantidad": 15,
          "precioUnitario": 200.00,
          "importe": 3000.00,
          "descuento": 0
        }
      ]
    }
  }
}

xmlDownloadUrl es una URL firmada de S3 valida por 1 hora. El POS puede abrirla directamente para descargar el archivo XML. Genera una nueva llamando al endpoint de nuevo.

Response 200 — Ya existia en cache
{
  "success": true,
  "data": {
    "source": "cache",
    "cfdi": {
      "uuid": "A1B2C3D4-...",
      "xmlDownloadStatus": "COMPLETE",
      "xmlDownloadUrl": "https://s3.../cfdis/...?X-Amz-Signature=...",
      "downloadExpiresIn": 3600,
      ...
    }
  }
}
Response 200 — Solo metadata (XML no disponible aun)
{
  "success": true,
  "data": {
    "source": "sat_metadata_only",
    "warning": "Se encontro el CFDI en el SAT pero no se pudo descargar el XML. Reintentaremos automaticamente en background; recibiras un webhook cfdi.xml_disponible cuando este listo.",
    "cfdi": {
      "uuid": "A1B2C3D4-...",
      "emisorRfc": "AAA010101AAA",
      "emisorNombre": "Proveedor SA de CV",
      "total": 11600.00,
      "xmlDownloadStatus": "METADATA_ONLY",
      "xmlDownloadUrl": null,
      "xmlRetryCount": 0,
      "xmlNextRetryAt": "2026-04-27T15:30:00.000Z",
      "conceptos": []
    },
    "retryStatus": {
      "retryCount": 0,
      "nextRetryAt": "2026-04-27T15:30:00.000Z"
    }
  }
}

Campos clave para integracion POS

CampoTipoDescripcion
xmlDownloadUrlstring | nullURL firmada para descargar el XML (1h). null si METADATA_ONLY.
pdfDownloadUrlstring | nullURL firmada para descargar el PDF (si existe).
downloadExpiresInnumber | nullSegundos de validez de la URL (3600 = 1 hora).
xmlDownloadStatusstringCOMPLETE | METADATA_ONLY | PERMANENT_METADATA_ONLY
xmlRetryCountnumberIntentos de descarga realizados (max 8).
xmlNextRetryAtstring | nullProximo reintento (ISO 8601). null si COMPLETE.

Errores posibles

CodigoHTTPCausa
UUID_NOT_FOUND404No se encontro el CFDI en el SAT (verifica que sea recibida)
MISSING_FIEL400La empresa no tiene FIEL configurada
FIEL_EXPIRED400La FIEL esta vencida
FIEL_RFC_MISMATCH400El RFC de la FIEL no coincide con la empresa
RECEPTOR_MISMATCH403El CFDI tiene como receptor otro RFC (no tienes acceso)
SCOPE_001403API key no tiene acceso a la empresa
SCOPE_002403API key no tiene permiso para cfdi:descargar
RATE_001429Rate limit excedido (ver header Retry-After)

Estado de sincronizacion

GET/api/cfdi/sync-recibidos
Session o API Key + x-empresa-id

Consulta el estado actual de sincronizacion de facturas recibidas. Util para saber si hay un sync en curso y cuantas facturas recibidas tiene la empresa.

Request
curl "https://api.fiscafacil.mx/cfdi/sync-recibidos" \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID"
Response 200
{
  "success": true,
  "data": {
    "syncStatus": "IDLE",
    "lastSyncAt": "2026-04-10T15:30:00.000Z",
    "totalRecibidos": 635
  }
}

Crear Periodo de Nomina

POST/api/nomina/periodos
Session o API Key + x-empresa-id

Crea un periodo de nomina (quincenal, semanal, mensual). El periodo inicia en status ABIERTO.

ParametroTipoDescripcion
fechaIniciorequireddatetimeInicio del periodo (ISO 8601)
fechaFinrequireddatetimeFin del periodo
fechaPagorequireddatetimeFecha de pago (debe ser >= fechaFin)
periodicidadrequiredstringSEMANAL, CATORCENAL, QUINCENAL, MENSUAL
diasPagadosrequirednumberDias del periodo (7, 14, 15, 30)
Request
curl -X POST https://api.fiscafacil.mx/nomina/periodos \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{ "fechaInicio": "2026-04-16T00:00:00Z", "fechaFin": "2026-04-30T00:00:00Z", "fechaPago": "2026-04-30T00:00:00Z", "periodicidad": "QUINCENAL", "diasPagados": 15 }'
Response 201
{
  "mode": "sandbox",
  "success": true,
  "data": {
    "id": "cm_periodo_abc123",
    "status": "ABIERTO",
    "fechaPago": "2026-04-30T00:00:00.000Z",
    "diasPagados": 15,
    "periodicidad": "QUINCENAL"
  }
}

Calcular Nomina del Periodo

POST/api/nomina/periodos/{id}
Session o API Key + x-empresa-id

Calcula ISR (Art. 96 LISR 2026), IMSS (cuotas obreras), y subsidio al empleo para todos los empleados activos. Las incidencias APROBADAS (horas extra, incapacidades, faltas) se incluyen automaticamente. Usa tablas actualizadas al 2026 (Anexo 8 RMF, DOF 28/dic/2025). Sin body — calcula automaticamente.

Request
curl -X POST https://api.fiscafacil.mx/nomina/periodos/cm_periodo_abc123 \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID"
Response 200
{
  "mode": "sandbox",
  "success": true,
  "data": {
    "periodoId": "cm_periodo_abc123",
    "recibosCalculados": 15,
    "totalNomina": 112500.00,
    "status": "CALCULADO"
  }
}

Timbrar Recibos de Nomina

POST/api/nomina/periodos/{id}/timbrar
Session o API Key + x-empresa-id

Timbra todos los recibos CALCULADOS del periodo. Genera CFDI 4.0 con complemento nomina 1.2 por cada empleado. Requiere CSD configurado y registro patronal en la empresa. Valida saldo de timbres con lock distribuido.

Protecciones:valida empleado activo, totalDeducciones <= totalPercepciones, lock en timbres. Si un recibo falla, los demas continuan (timbrado parcial). Recibos fallidos se resetean a PENDIENTE (retryable).

Request
curl -X POST https://api.fiscafacil.mx/nomina/periodos/cm_periodo_abc123/timbrar \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID"
Response 201
{
  "mode": "sandbox",
  "success": true,
  "data": {
    "periodoId": "cm_periodo_abc123",
    "totalRecibos": 15,
    "timbrados": 14,
    "errores": 1,
    "recibos": [
      {
        "reciboId": "cm_recibo_001",
        "empleadoNombre": "Carlos Castro Lopez",
        "uuid": "ABC12345-6789-ABCD-EF01-234567890ABC",
        "total": 6947.55
      }
    ],
    "detalleErrores": [
      {
        "reciboId": "cm_recibo_015",
        "empleadoNombre": "Maria Garcia",
        "error": "Empleado dado de baja"
      }
    ]
  }
}

Errores posibles

CodigoHTTPCausa
TIMBRE_001402Saldo de timbres insuficiente
NOMINA_002400Falta registro patronal en la empresa
NOMINA_999500Error interno en pipeline de timbrado

Cancelar Recibo de Nomina

POST/api/nomina/periodos/{id}/cancelar
Session o API Key + x-empresa-id

Cancela un recibo timbrado via PAC. Mismo flujo SAT que cancelacion de CFDI regular. Reembolsa el timbre si la cancelacion es inmediata.

ParametroTipoDescripcion
reciboIdrequiredstringID del recibo a cancelar
motivorequired"01"|"02"|"03"|"04"01=Con relacion (requiere folioSustitucion), 02=Sin relacion, 03=No se llevo a cabo, 04=Nominativa en global
folioSustitucionstringUUID del CFDI sustituto (obligatorio si motivo=01)
Request
curl -X POST https://api.fiscafacil.mx/nomina/periodos/cm_periodo_abc123/cancelar \
  -H "Authorization: Bearer ff_YOUR_API_KEY" \
  -H "x-empresa-id: clx_EMPRESA_ID" \
  -H "Content-Type: application/json" \
  -d '{ "reciboId": "cm_recibo_001", "motivo": "02" }'
Response 200
{
  "mode": "sandbox",
  "success": true,
  "data": {
    "uuid": "ABC12345-6789-ABCD-EF01-234567890ABC",
    "status": "CANCELADO",
    "acuse": "<xml>...</xml>",
    "empleado": "Carlos Castro Lopez"
  }
}

Roles y Permisos

Cada usuario tiene un rol por empresa. Los roles son jerarquicos — un rol superior hereda todos los permisos de los inferiores.

PROPIETARIOADMINISTRADORCONTADORFACTURADORUSUARIO
AccionRol Minimo
cfdi:timbrarFACTURADOR
cfdi:cancelarCONTADOR
cfdi:descargarCONTADOR
cfdi:viewUSUARIO
cliente:create / editFACTURADOR
cliente:deleteCONTADOR
cliente:viewUSUARIO
producto:create / editFACTURADOR
producto:deleteCONTADOR
producto:viewUSUARIO
empresa:editADMINISTRADOR
empresa:csdADMINISTRADOR
empresa:deletePROPIETARIO
member:manageADMINISTRADOR