Documentación ACIv2 API

API de integración para facturación electrónica con múltiples plataformas

Acerca de esta API

ACIv2 es una API basada en Firebase Functions que proporciona integración con múltiples plataformas de gestión empresarial para la emisión de facturas electrónicas en Panamá.

Plataformas Soportadas

QuickBooks

Sistema de contabilidad y gestión empresarial

Zoho

Suite de gestión empresarial

Xero

Software de contabilidad en la nube

Shopify

Plataforma de comercio electrónico

WooCommerce

Plugin de tienda para WordPress

Dentalink

Sistema de gestión dental

Características Principales

Base URL

https://us-central1-zoho-books-edocs-integracion.cloudfunctions.net/aciv2

Arquitectura del Sistema

Infraestructura y componentes técnicos de ACIv2

Stack Tecnológico

Plataforma Backend

  • Firebase Functions: Serverless computing en Google Cloud Platform
  • Node.js 20+: Runtime de ejecución
  • Express.js: Framework web para endpoints REST
  • Firestore: Base de datos NoSQL para persistencia

Sistema de Colas

Redis + Bee-Queue

Procesamiento asíncrono de facturas y eventos de webhooks con reintentos automáticos

Autenticación

JWT + Firebase Auth

Tokens RS256 firmados con clave privada, validación contra Firebase Authentication

Integraciones

6 Plataformas

APIs oficiales de QuickBooks, Zoho, Xero, Shopify, WooCommerce, Dentalink

Facturación

PAC Panamá

Integración con Proveedores Autorizados: Docucenter, Alanube, Digifact

Arquitectura de Componentes

aciv2/
├── app/               # Lógica de negocio por plataforma
│   ├── quickbooks/    # Módulos QuickBooks (Invoice, Contact, Item)
│   ├── zoho/          # Módulos Zoho Books/CRM
│   ├── xero/          # Módulos Xero Accounting
│   ├── shopify/       # Módulos Shopify
│   ├── woocommerce/   # Módulos WooCommerce
│   └── dentalink/     # Módulos Dentalink
├── router/            # Endpoints HTTP por plataforma
├── jobs/              # Procesadores de colas y tareas programadas
│   ├── queue.js       # Configuración Redis + Bee-Queue
│   └── processors.js  # Procesadores centralizados
├── config/            # Configuración y claves
│   └── jwt-key.json   # Clave privada RS256
├── email/             # Sistema de envío de comprobantes
├── template/          # Plantillas PDF/XML
└── doc/               # Documentación técnica

Sistema de Colas (Redis + Bee-Queue)

Procesamiento Asíncrono

ACIv2 utiliza un sistema robusto de colas para operaciones críticas:

Colas Disponibles

zohoInvoiceQueue

Procesa emisión de facturas de Zoho al PAC con reintentos automáticos.

  • Endpoint: POST /queue/invoices/:invoice_id
  • Reintentos: Automáticos con backoff exponencial
  • Timeout: 5 minutos por intento
  • Validaciones críticas: Prevención de CUFE duplicado y lock de 10 minutos entre emisiones

Política de Reintentos: Los clientes pueden reintentar emisión inmediatamente sin restricciones de intentos. El PAC aplica sus propias validaciones.

zohoCreditNoteQueue

Procesa emisión de notas de crédito de Zoho.

  • Reintentos: Automáticos sin límite artificial
  • Manejo de errores: Jobs fallidos almacenados en Redis
  • Validaciones críticas: Prevención de CUFE duplicado y lock de 10 minutos entre emisiones

Política de Reintentos: Similar a facturas, reintentos inmediatos permitidos sin restricciones de tiempo.

quickbooksInvoiceQueue

Procesa eventos de webhooks de QuickBooks en segundo plano.

  • Triggered por: POST /quickbooks/event_processor
  • Procesamiento: Facturas creadas/actualizadas automáticamente
  • Reintentos inteligentes: Hasta 8 intentos con delays adaptativos

Características del Sistema de Colas

Validaciones Críticas en Emisión Zoho

Validaciones Activas:

  • CUFE Duplicado: Bloquea emisión si el documento ya tiene CUFE asignado
  • Lock de 10 minutos: Previene emisiones simultáneas del mismo documento
  • Sin límite de intentos: Los clientes pueden reintentar inmediatamente para corregir errores de validación

Nota: El contador de intentos se mantiene solo con fines estadísticos en el panel de gestión.

Sistema de Prevención de Duplicados

Validación Pre-Creación

ACIv2 incluye un sistema robusto de prevención de facturas y pagos duplicados.

Validaciones Automáticas

// Prevención de Facturas Duplicadas
- Verifica DocNumber existente en QuickBooks
- Compara datos de factura (cliente, monto, fecha)
- Detecta similitudes >95% para alertar
- Bloquea creación si CUFE ya existe

// Prevención de Pagos Huérfanos
- Valida que pago tenga líneas de aplicación
- Verifica que facturas relacionadas existan
- Detecta pagos sin aplicar (orphan payments)
- Sugiere vinculación o eliminación

// Auditoría Completa
- Todos los intentos registrados en Firestore
- Logs estructurados por operación
- Métricas de salud del sistema (0-100)

Jobs de Mantenimiento

Reconciliación de Pagos Huérfanos

// Ejecutar manualmente
node jobs/reconcile_orphans_job.js

// Programar con cron (diario 2 AM)
0 2 * * * cd /path/to/aciv2 && node jobs/reconcile_orphans_job.js

Funcionalidades:

  • Escanea todos los pagos en QuickBooks
  • Identifica pagos sin líneas de aplicación
  • Clasifica: eliminar ($0) vs vincular (>$0)
  • Genera reporte con acciones recomendadas

Mantenimiento de Webhooks

Sistema Automático de Mantenimiento

Limpieza periódica de configuraciones obsoletas y consolidación de duplicados.

Periodicidad Recomendada

Comandos de Mantenimiento

// Reporte de configuraciones
GET /quickbooks/maintenance/webhook_configs?action=report

// Limpieza de obsoletos (>90 días)
GET /quickbooks/maintenance/webhook_configs?action=cleanup&days=90

// Consolidación de duplicados
GET /quickbooks/maintenance/webhook_configs?action=consolidate

// Mantenimiento completo (dry run)
POST /quickbooks/maintenance/webhook_configs/full
{
  "days": 90,
  "dryRun": true
}

Dependencias Principales

{
  "firebase-admin": "^12.3.1",
  "firebase-functions": "^6.3.2",
  "express": "^4.18.1",
  "redis": "^4.7.0",
  "bee-queue": "^1.7.1",
  "intuit-oauth": "^4.0.0",
  "node-quickbooks": "^2.0.43",
  "@shopify/shopify-api": "^10.0.0",
  "@woocommerce/woocommerce-rest-api": "^1.0.1",
  "axios": "^1.11.0",
  "jsonwebtoken": "^9.0.1",
  "puppeteer": "^21.7.0",
  "nodemailer": "^6.9.9"
}

Configuración de Despliegue

// Firebase Functions Config
{
  "region": "us-central1",
  "runtime": "nodejs20",
  "timeout": 540,  // 9 minutos
  "memory": "1GB",
  "minInstances": 0,
  "maxInstances": 100
}

// Variables de Entorno Requeridas
API_KEY=firebase_api_key
REDIS_HOST=redis_host
REDIS_PORT=6379
JWT_SECRET_KEY=path/to/jwt-key.json

Monitoreo y Logs

Dashboard de Salud

Sistema integrado para monitorear la salud general de la API.

// Ejecutar dashboard
node test/health_check_dashboard.js

// Salida ejemplo:
SCORE DE SALUD DEL SISTEMA: 85/100
Estado: BUENO ⚠️

Facturas creadas: 45
Duplicados bloqueados: 0 ✅
Pagos creados: 42
Huérfanos bloqueados: 2 ⚠️

Recomendaciones:
- Revisar 2 pagos sin líneas de aplicación
- Sistema operando normalmente

Logs Estructurados

Todos los componentes generan logs con el siguiente formato:

[PLATAFORMA] [realm_id/org_id] Mensaje descriptivo
[QUICKBOOKS] [123456] Procesando factura 789 - Intento 1/8
[ZOHO] [org_456] Job 12345 completado exitosamente
[WEBHOOK] webhook_abc123: 3 eventos procesados

Autenticación

La API soporta dos métodos de autenticación:

1. Basic Authentication

Utiliza el header Authorization con credenciales codificadas en Base64:

Authorization: Basic base64(email:password)

Importante

Las credenciales se validan contra Firebase Authentication. En el primer acceso, se genera y almacena un token de sesión en Firestore.

2. JWT Token

Utiliza un token JWT firmado con RS256:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

También se puede enviar como parámetro de query:

GET /endpoint?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Ejemplo de Autenticación con cURL

curl -X GET "https://[base-url]/quickbooks/invoices" \
  -H "Authorization: Basic $(echo -n 'user@example.com:password' | base64)"

QuickBooks API

Endpoints para integración con QuickBooks Online.

Autorización

GET /quickbooks/authorization_url

Obtiene la URL de autorización de QuickBooks OAuth2.

Respuesta

{
  "authUri": "https://appcenter.intuit.com/connect/oauth2?...",
  "state": "random-state-string"
}
POST /quickbooks/authorization_url/token_set

Establece los tokens de acceso después de la autorización OAuth2.

Body

{
  "code": "authorization_code",
  "realmId": "realm_id",
  "state": "state_string"
}
POST /quickbooks/revoking_refresh_token/:sid

Revoca el refresh token de una conexión.

Parámetros

  • sid - ID de la conexión

Configuración de Clientes

Campos Requeridos para Facturación Electrónica

Para la facturación electrónica panameña, es necesario configurar correctamente los datos RUC/DV en los clientes de QuickBooks. El sistema ACIv2 extrae automáticamente esta información de campos específicos.

Campos Utilizados por ACIv2

1. PrimaryTaxIdentifier (Campo Principal)

Ubicación en QuickBooks: Customer → Tax Info → Business ID No.

Este es el campo oficial de QuickBooks para identificación tributaria. Tiene prioridad 1 en la extracción de datos.

2. AlternatePhone.FreeFormNumber (Campo Alternativo)

Ubicación en QuickBooks: Customer → Phone → Other Phone

Campo de fallback con prioridad 2. Se usa si PrimaryTaxIdentifier está vacío o no tiene formato válido.

Tipos de Receptor

Código Tipo Receptor Descripción Uso
01 Contribuyente Cliente con RUC válido Empresas o personas registradas en DGI
02 Consumidor Final Sin RUC o cliente genérico Personas sin registro tributario
03 Gobierno Entidades gubernamentales Instituciones públicas de Panamá
04 Extranjero Identificación no panameña Pasaporte o ID extranjera

Tipos de Contribuyente

Código Tipo Ejemplo RUC Formato en QB
1 Persona Natural 9-734-1672 XXXX9-734-1672 DV:56
2 Persona Jurídica 1825706-1-709732 XXXX:1825706-1-709732 DV:90

Nota: El prefijo XXXX (sin dos puntos) indica Persona Natural. El prefijo XXXX: (con dos puntos) indica Persona Jurídica.

Formatos Soportados en PrimaryTaxIdentifier

1. Persona Natural - Formato Estándar

XXXX9-734-1672 DV:56
XXXX8-123-4567 DV:12
XXXX1-234-5678 DV:34

Patrón: XXXX[provincia]-[tomo]-[asiento] DV:[dv]

  • Provincia: 1-13 o E/N/PE (1 o 2 caracteres)
  • DV puede escribirse con o sin dos puntos: DV:56 o DV56

2. Persona Natural - Con Prefijos Especiales (NT, AV, PI, etc.)

XXXX13-NT-2-727784 DV:49
XXXX8-AV-1-123456 DV:34
XXXX7-PI-3-654321 DV:78

Patrón 4 segmentos: XXXX[provincia]-[prefijo]-[grupo]-[numero] DV:[dv]

XXXX13-NT-727784 DV:49
XXXX8-AV-123456 DV:34

Patrón 3 segmentos: XXXX[provincia]-[prefijo]-[numero] DV:[dv]

3. Persona Natural - Con Provincias Especiales

XXXE-1234-12345 DV:23
XXXPE-5678-91011 DV:45
XXXN-9876-54321 DV:67

Provincias especiales:

  • E - Extranjero naturalizado
  • PE - Provincia especial
  • N - Provincia N

4. Persona Jurídica (Empresa)

XXXX:1825706-1-709732 DV:90
XXXX:1234567-1-123456 DV:45
XXXX:9876543-2-654321 DV:78

Importante: El prefijo XXXX: (con dos puntos) es obligatorio para Persona Jurídica.

Patrón: XXXX:[numero]-[digito]-[correlativo] DV:[dv]

5. Extranjero con Pasaporte

XXXXPORTE:XYZABC123
XXXXPORTE:ABC123XYZ
XXXXPORTE:N1234567890

Patrón: XXXXPORTE:[numero_pasaporte]

Tipo Receptor automático: 04 - Extranjero

6. Formato con TIPO y TIPO_RECEPTOR Explícitos (Opcional)

XXXX9-734-1672 DV:56 TIPO:1 TIPO_RECEPTOR:01
XXXX:1825706-1-709732 DV:90 TIPO:2 TIPO_RECEPTOR:01
XXXX13-NT-2-727784 DV:49 TIPO:1 TIPO_RECEPTOR:03

Estos campos son opcionales y permiten especificar explícitamente:

  • TIPO:1 - Persona Natural
  • TIPO:2 - Persona Jurídica
  • TIPO_RECEPTOR:01 - Contribuyente
  • TIPO_RECEPTOR:02 - Consumidor Final
  • TIPO_RECEPTOR:03 - Gobierno
  • TIPO_RECEPTOR:04 - Extranjero

Formatos Soportados en AlternatePhone (Fallback)

Si PrimaryTaxIdentifier está vacío, el sistema intentará extraer RUC/DV del campo AlternatePhone.FreeFormNumber (Other Phone).

Formatos Aceptados

// Formato estándar
9-734-1672 56
1825706-1-709732 DV90
8-123-4567 12

// Con DV explícito
9-734-1672 DV:56
1825706-1-709732 DV:90

// Cualquier formato con guiones
123-45-67890 12
E-1234-12345 23
PE-5678-91011 45

Nota: En AlternatePhone no se distingue automáticamente entre Natural/Jurídica. El sistema analiza el RUC para determinarlo.

Ejemplos de Configuración

Ejemplo 1: Cliente Persona Natural

DisplayName: "JEAN CARLOS NARVAEZ"
GivenName: "Jean Carlos"
FamilyName: "Narvaez"
PrimaryTaxIdentifier: "XXXX9-734-1672 DV:56"

Resultado:
- RUC: 9-734-1672
- DV: 56
- TIPO: 1 (Persona Natural)
- TIPO_RECEPTOR: 01 (Contribuyente)

Ejemplo 2: Cliente Persona Jurídica (Empresa)

DisplayName: "EMPRESA XYZ S.A."
CompanyName: "EMPRESA XYZ S.A."
PrimaryTaxIdentifier: "XXXX:1825706-1-709732 DV:90"

Resultado:
- RUC: 1825706-1-709732
- DV: 90
- TIPO: 2 (Persona Jurídica)
- TIPO_RECEPTOR: 01 (Contribuyente)

Ejemplo 3: Cliente con Prefijo Especial NT

DisplayName: "GERALDINE JIMENEZ"
GivenName: "GERALDINE"
MiddleName: "DAILETH MANZANILLA"
FamilyName: "JIMENEZ"
PrimaryTaxIdentifier: "XXXX13-NT-2-727784 DV:49"

Resultado:
- RUC: 13-NT-2-727784
- DV: 49
- TIPO: 1 (Persona Natural)
- TIPO_RECEPTOR: 01 (Contribuyente)

Ejemplo 4: Cliente Extranjero con Pasaporte

DisplayName: "JOHN DOE"
GivenName: "John"
FamilyName: "Doe"
PrimaryTaxIdentifier: "XXXXPORTE:N1234567890"

Resultado:
- PASAPORTE: N1234567890
- RUC: null
- DV: null
- TIPO: null
- TIPO_RECEPTOR: 04 (Extranjero)

Ejemplo 5: Cliente sin RUC (Consumidor Final)

DisplayName: "CLIENTE GENERICO"
PrimaryTaxIdentifier: ""
AlternatePhone: null

Resultado:
- RUC: null
- DV: null
- TIPO: null
- TIPO_RECEPTOR: 02 (Consumidor Final)

Ejemplo 6: Usando AlternatePhone como Fallback

DisplayName: "MARIA GONZALEZ"
PrimaryTaxIdentifier: ""  // Vacío
AlternatePhone.FreeFormNumber: "8-456-7890 45"

Resultado:
- RUC: 8-456-7890
- DV: 45
- TIPO: 1 (Persona Natural)
- TIPO_RECEPTOR: 01 (Contribuyente)
- Source: AlternatePhone_Short

Notas Importantes

  • Campo Obligatorio en QB: DisplayName debe ser único en QuickBooks
  • Prioridad de Extracción: PrimaryTaxIdentifier (1°) → AlternatePhone (2°) → Consumidor Final
  • Prefijo XXXX: Con dos puntos = Jurídica, sin dos puntos = Natural
  • DV Flexible: Puede escribirse como DV:56 o DV56
  • Case Insensitive: Los patrones no distinguen mayúsculas/minúsculas
  • Validación Automática: El sistema valida la estructura del RUC y determina el tipo automáticamente
  • Gobierno (Tipo 03): Debe especificarse explícitamente con TIPO_RECEPTOR:03

Facturas

GET /quickbooks/invoices

Obtiene una lista de facturas de QuickBooks.

Query Parameters

  • limit - Límite de resultados (default: 100)
  • offset - Offset para paginación
  • startDate - Fecha de inicio (ISO 8601)
  • endDate - Fecha de fin (ISO 8601)

Headers Requeridos

  • Authorization - Token JWT con orgId
GET /auth/quickbooks/invoices

Obtiene facturas con autenticación básica (para uso interno).

Query Parameters

  • id - ID de factura específica
  • docNumber - Número de documento
GET /quickbooks/invoice/:invoice_sid

Obtiene una factura específica por su ID.

Parámetros

  • invoice_sid - ID de la factura
GET /quickbooks/invoice/:invoice_id/details

Obtiene detalles completos de una factura con minor version específica.

Query Parameters

  • minorversion - Versión de la API de QuickBooks (default: 75)
POST /quickbooks/to_emit

Emite una factura al PAC (Proveedor Autorizado de Certificación).

Body

{
  "invoiceId": "123",
  "organization": "org_id"
}

Este endpoint procesa la factura y envía al PAC panameño para obtener el CUFE.

POST /quickbooks/credits_note/to_emit

Emite una nota de crédito al PAC.

Webhooks

POST /quickbooks/event_processor

Procesa eventos de webhooks de QuickBooks (create, update, delete).

Body

{
  "eventNotifications": [{
    "realmId": "realm_id",
    "dataChangeEvent": {
      "entities": [{
        "name": "Invoice",
        "id": "123",
        "operation": "Create"
      }]
    }
  }]
}

Procesamiento Asíncrono

Este endpoint responde inmediatamente con código 200 y procesa los eventos en segundo plano utilizando sistema de colas.

GET /quickbooks/webhook_health

Health check para verificar el estado del procesador de eventos.

GET /quickbooks/webhook_processing_config/:realm_id/:organization_id

Obtiene la configuración de procesamiento de webhooks para una organización.

POST /quickbooks/webhook_processing_config

Actualiza la configuración de procesamiento de webhooks.

Body

{
  "realmId": "realm_id",
  "organizationId": "org_id",
  "docucenterEnabled": true,
  "reason": "Motivo del cambio"
}

Mantenimiento

GET /quickbooks/maintenance/webhook_configs

Operaciones de mantenimiento para configuraciones de webhooks.

Query Parameters

  • action - Tipo de operación: report | cleanup | consolidate
  • days - Días de antigüedad para cleanup (default: 90)
POST /quickbooks/maintenance/webhook_configs/full

Ejecuta mantenimiento completo (reporte, consolidación y limpieza).

Body

{
  "days": 90,
  "dryRun": true
}
GET /quickbooks/mappings/diagnostic/:connection_id

Diagnóstico de mappings entre QuickBooks y Docucenter.

POST /quickbooks/mappings/cleanup/:connection_id

Limpia mappings obsoletos.

Body

{
  "dryRun": true
}

Administración

Endpoints para gestión avanzada de clientes, facturas y sincronización con QuickBooks.

Endpoints Especializados

Estos endpoints están diseñados para operaciones administrativas y correcciones de datos. Usan reintentos automáticos y manejo robusto de errores.

Gestión de Clientes

Zoho API

Endpoints para integración con Zoho Books y Zoho CRM.

Autorización

GET /authorization_url/:sid

Obtiene la URL de autorización de Zoho OAuth2.

Parámetros

  • sid - ID de la conexión
GET /generate_access/:sid

Genera access token y refresh token desde código de autorización.

GET /revoking_refresh_token/:sid

Revoca el refresh token de Zoho.

Facturas

GET /invoices

Obtiene lista de facturas de Zoho Books.

Query Parameters

  • page - Número de página
  • per_page - Facturaspor página
  • status - Estado: sent | draft | paid | void
GET /invoices/:invoice_number

Obtiene una factura específica por su número.

POST /invoices

Emite facturas de Zoho al PAC.

Body

{
  "invoices": ["invoice_id_1", "invoice_id_2"]
}
POST /invoices/:invoice_id

Emite una factura específica al PAC (síncrono).

Parámetros

  • invoice_id - ID de la factura en Zoho

Respuesta

{
  "success": true,
  "message": "FE01234567890...",
  "automaticallyRedirect": "No"
}
POST /queue/invoices/:invoice_id

Emite una factura usando sistema de colas (asíncrono recomendado).

Parámetros

  • invoice_id - ID de la factura en Zoho

Respuesta

{
  "success": true,
  "message": "Trabajo de emisión de factura en progreso.",
  "jobId": "12345",
  "invoiceId": "invoice_123",
  "automaticallyRedirect": "No"
}

Sistema de Colas

Este endpoint usa Redis y Bee-Queue para procesamiento asíncrono. La factura se procesa en segundo plano con reintentos automáticos.

GET /shipments

Obtiene facturas electrónicas emitidas (shipments).

Query Parameters

  • page - Número de página
  • per_page - Resultados por página
GET /credit_notes

Obtiene lista de notas de crédito de Zoho.

Notas de Crédito

GET /credit_notes/:credit_number

Obtiene una nota de crédito específica.

POST /credit_notes

Emite notas de crédito al PAC.

Campos Personalizados para Zoho Books

Configuración Requerida en Zoho Books

Para la facturación electrónica panameña, es necesario configurar campos personalizados específicos en Zoho Books. Estos campos almacenan la información requerida por la DGI de Panamá.

Campos Personalizados para Facturas

Configurar en: Personalización de campos de facturashttps://books.zoho.com/app#/settings/preferences/invoices/customfields

Campos Obligatorios

Campo / API name Tipo Valores
Tipo de documento
cf_tipo_de_documento
Menú desplegable
(Obligatorio: Sí)
1-Factura de Operación Interna
2-Factura de Importación
3-Factura de Exportación
4-Nota de Crédito
5-Nota de Débito
6-Nota de Crédito Genérica
7-Nota de Débito Genérica
8-Factura de Zona Franca
9-Reembolso
Punto de Facturación
cf_punto_de_facturacio_n
Menú desplegable
(Obligatorio: Sí)
001-Nombre personalizado 1
002-Nombre personalizado 2
003-Nombre personalizado 3
(Formato: 3 dígitos + nombre)
Naturaleza de la Operación
cf_naturaleza_de_la_operacio_n
Menú desplegable
(Obligatorio: Sí)
1-Venta
2-Exportación
10-Transferencia
11-Devolución
12-Consignación
13-Remesa
14-Entrega gratuita
20-Compra
21-Importación
Tipo de la operación
cf_tipo_de_la_operacio_n
Menú desplegable
(Obligatorio: Sí)
1-Salida o venta
2-Entrada o compra
Tipo de transacción de venta
cf_tipo_de_transaccio_n_de_ven
Menú desplegable
(Obligatorio: Sí)
1-Venta de Giro del negocio
2-Venta Activo Fijo
3-Venta de Bienes Raíces
4-Prestación de Servicio
Emisor
cf_emisor
Lookup (Módulo: Usuarios)
(Obligatorio: Sí)
Usuario del sistema que emite
Forma de pago
cf_forma_de_pago
Menú desplegable
(Obligatorio: Sí)
01-Crédito
02-Efectivo
03-Tarjeta Crédito
04-Tarjeta Débito
05-Tarjeta Fidelización
06-Vale
07-Tarjeta de Regalo
08-Transf./Depósito Bancario
09-Cheque
10-Punto de Pago
99-Otro
Tiempo de pago
cf_tiempo_de_pago
Menú desplegable
(Obligatorio: Sí)
1-Inmediato
2-Plazo
3-Mixto
CUFE
cf_cufe
Cuadro de texto (varias líneas)
(Obligatorio: Sí)
Generado por el PAC al emitir

Campos Opcionales

  • cf_informaci_n_de_inter_s - Cuadro de texto (Información de interés del emisor)
  • cf_estado_factura - Cuadro de texto (Estado de la factura)
  • cf_n_mero_secuencial - Número (Número secuencial interno)
  • cf_condiciones_de_entrega - Texto (Condiciones de entrega)

Campos para Exportación

  • cf_moneda_de_la_operaci_n_de_e - Moneda de la operación
  • cf_descripci_n_de_moneda_de_la - Descripción de la moneda
  • cf_tipo_de_cambio_a_la_fecha_d - Tipo de cambio
  • cf_monto_en_la_moneda_extranje - Monto en moneda extranjera (Decimal)
  • cf_puerto_de_embarque_de_la_me - Puerto de embarque

Campos de Retención

  • cf_c_digo_de_retenci_n_a_aplic - Código de retención (Menú desplegable):
    • 01-Pago por servicio profesional al estado 100%
    • 02-Pago por venta bienes/servicios al estado 50%
    • 03-Pago a no domiciliado 100%
    • 04-Pago por compra bienes/servicios 50%
    • 07-Pago a comercio TC/TD 50%
    • 08-Otros (disminución)

Campos Personalizados para Notas de Crédito

Configurar en: Personalización de campos de Nota de créditohttps://books.zoho.com/app#/settings/preferences/creditnotes/customfields

Campo / API name Tipo Valores
Tipo de documento
cf_tipo_de_documento
Menú desplegable
(Obligatorio: Sí)
4-Nota de Crédito Referente a una o varias FE
6-Nota de Crédito Genérica
CUFE
cf_cufe
Cuadro de texto (varias líneas)
(Obligatorio: Sí)
Generado por el PAC al emitir

Campos Personalizados para Artículos/Items

Configurar en: Personalización de campos de artículoshttps://books.zoho.com/app#/settings/preferences/items/customfields

Campo / API name Tipo Descripción
Número secuencial
cf_nu_mero_secuencial
Número (Opcional) Mostrar en transacciones: Sí
Código interno
cf_co_digo_interno
Texto (Opcional) Código interno del ítem
Código del Ítem Abreviado
cf_co_digo_del_i_tem_abreviado
Texto (Opcional) Código abreviado
Código del Ítem
cf_co_digo_del_i_tem
Texto (Opcional) Código completo del ítem
Código GTIN
cf_co_digo_gtin_del_i_tem
Número (Opcional) Código GTIN/EAN del producto
Fecha de fabricación
cf_fecha_de_fabricacio_n
Fecha (Opcional) Fecha de fabricación del producto
Fecha de caducidad
cf_fecha_de_caducidad
Fecha (Opcional) Fecha de caducidad del producto

Campos Personalizados para Usuarios/Clientes

Configurar en: Personalización de campos de usuarioshttps://books.zoho.com/app#/settings/preferences/users/customfields

Campo / API name Tipo Valores
Tipo de Contribuyente
cf_tipo_de_contribuyente
Menú desplegable 1-Natural
2-Jurídico
RUC
cf_ruc
Texto Número de RUC del usuario
Dígito Verificador
cf_di_gito_verificador
Número DV del RUC
Teléfono
cf_tele_fono
Texto Número telefónico
Código PDC
cf_co_digo_de_provincia_distrito_y_corregimiento
Texto Código completo (Provincia-Distrito-Corregimiento)
Provincia
cf_provincia
Menú desplegable BOCAS DEL TORO
COCLE
COLON
CHIRIQUI
DARIEN
HERRERA
LOS SANTOS
PANAMA
VERAGUAS
PANAMA OESTE
Distrito
cf_distrito
Texto Nombre del distrito
Corregimiento
cf_corregimiento
Texto Nombre del corregimiento
Coordenadas geográficas
cf_coordenadas_geogr_ficas
Texto Lat,Long del emisor

Campos Personalizados para Contactos (Clientes)

Configurar en: Personalización de campos de clienteshttps://books.zoho.com/app#/settings/preferences/contacts

Campo / API name Tipo Valores
Tipo de receptor
cf_tipo_de_receptor
Menú desplegable 1-Contribuyente
2-Consumidor final
3-Gobierno
4-Extranjero
Tipo de Contribuyente
cf_tipo_de_contribuyente
Menú desplegable 1-Natural
2-Jurídico

Configuración de Impuestos

Configurar en: Tasas de impuestoshttps://books.zoho.com/app#/settings/taxes/taxrates

Tasas de ITBMS (Panamá)

Nombre del Impuesto Tarifa (%)
1: 7% 7
2: 10% 10
3: 15% 15

Integración con Scripts Deluge (Opcional)

Botones Personalizados en Zoho

Zoho Books permite crear botones personalizados usando Deluge Script para automatizar la emisión de facturas y notas de crédito directamente desde la interfaz web.

Script para timbrar Factura (Deluge)

Ubicación: Preferencias → Facturas → Botones Personalizados

custom_field = invoice.get("custom_field_hash");
if(custom_field != null && custom_field.get("cf_cufe") != null && custom_field.get("cf_cufe") != "CUFE")
{
    return {"code":2830,"message":"Ya existe Factura autorizada: " + custom_field.get("cf_cufe")};
}
else
{
    invoiceId = invoice.get("invoice_id");
    Base64Encoded = zoho.encryption.base64Encode("email:password");
    AuthorizationBasic = " Basic " + Base64Encoded;
    headers = Map();
    headers.put("Accept","application/json");
    headers.put("Content-Type","application/json");
    headers.put("Authorization",AuthorizationBasic);
    requestMap = Map();
    requestMap.put("organization_id","your_org_id");
    setInvoice = postUrl("https://us-central1-zoho-books-edocs-integracion.cloudfunctions.net/aciv2/invoices/" + invoiceId,requestMap,headers);
    if(setInvoice.get("success") == false)
    {
        return {"code":2830,"message":setInvoice.get("message")};
    }
    else
    {
        return setInvoice;
    }
}

Script para timbrar Nota de Crédito (Deluge)

Ubicación: Preferencias → Notas de Crédito → Botones Personalizados

custom_field = creditnote.get("custom_field_hash");
if(custom_field != null && custom_field.get("cf_cufe") != null && custom_field.get("cf_cufe") != "CUFE")
{
    return {"code":2830,"message":"Ya existe Nota de crédito autorizada: " + custom_field.get("cf_cufe")};
}
else
{
    creditnoteId = creditnote.get("creditnote_id");
    Base64Encoded = zoho.encryption.base64Encode("email:password");
    AuthorizationBasic = " Basic " + Base64Encoded;
    headers = Map();
    headers.put("Accept","application/json");
    headers.put("Content-Type","application/json");
    headers.put("Authorization",AuthorizationBasic);
    requestMap = Map();
    requestMap.put("organization_id","your_org_id");
    setCreditNote = postUrl("https://us-central1-zoho-books-edocs-integracion.cloudfunctions.net/aciv2/credit_notes/" + creditnoteId,requestMap,headers);
    if(setCreditNote.get("success") == false)
    {
        return {"code":2830,"message":setCreditNote.get("message")};
    }
    else
    {
        return setCreditNote;
    }
}

Notas Importantes

  • Reemplazar email:password con las credenciales de autenticación Basic Auth
  • Reemplazar your_org_id con el ID de organización del sistema
  • Reemplazar [proyecto] con el ID del proyecto Firebase
  • Los scripts validan que no exista CUFE previo para evitar duplicados

Xero API

Endpoints para integración con Xero Accounting.

Autorización

GET /xero/authorization_url

Obtiene la URL de autorización de Xero OAuth2.

POST /xero/authorization_url/token_set

Establece los tokens de acceso de Xero.

POST /xero/revoking_refresh_token/:sid

Revoca el refresh token.

Facturas

GET /xero/invoices

Obtiene facturas de Xero.

GET /xero/credits_note/:credit_note

Obtiene una nota de crédito específica.

GET /xero/invoice/:invoice_sid

Obtiene una factura específica por su ID.

POST /xero/to_emit

Emite facturas de Xero al PAC.

POST /xero/invoices/:invoice_id

Emite una factura específica por su ID.

Parámetros

  • invoice_id - ID de la factura en Xero

Respuesta

{
  "success": true,
  "message": "FE01234567890..."
}
GET /auth/xero/invoices

Obtiene facturas con autenticación básica (para uso interno).

GET /auth/xero/credits_note/:credit_note

Obtiene nota de crédito con autenticación básica.

Exportación de Datos

GET /xero/export_json/:org_sid

Exporta JSON de factura para pruebas y debugging.

Query Parameters

  • invoice_sid - ID de la factura

Respuesta

{
  "path": "https://storage.googleapis.com/.../12345.txt"
}
GET /xero/credit_note/export_json/:org_sid

Exporta JSON de nota de crédito.

Query Parameters

  • invoice_sid - ID de la nota de crédito
GET /xero/shipments/export_json/:org_sid

Exporta JSON de factura emitida (shipment).

Query Parameters

  • invoice_sid - ID de la factura emitida
POST /xero/credits_note/to_emit

Emite notas de crédito al PAC.

Shopify API

Endpoints para integración con Shopify.

Autorización

POST /shopify/authorization_url

Obtiene la URL de autorización de Shopify.

Body

{
  "shop": "tienda.myshopify.com",
  "scopes": "read_orders,write_orders"
}
POST /shopify/authorization_url/token_set/:sid

Establece el access token de Shopify.

PUT /shopify/update_client/:sid

Actualiza la configuración del cliente Shopify.

POST /shopify/revoking_refresh_token/:sid

Revoca el token de acceso.

Órdenes

GET /shopify/orders

Obtiene órdenes de Shopify para facturación.

Query Parameters

  • status - Estado de la orden
  • limit - Límite de resultados
  • since_id - ID mínimo para paginación
GET /shopify/orders/list

Lista de órdenes sin procesamiento adicional.

GET /shopify/orders/:sid

Obtiene una orden específica.

GET /shopify/orders/refund/:sid

Obtiene reembolsos de una orden (para notas de crédito).

Emisión de Facturas

POST /shopify/orders/to_emit/:sid

Procesa emisión de factura desde webhook de Shopify (automático).

Parámetros

  • sid - ID de la organización

Respuesta

{
  "success": true,
  "error": false,
  "message": "Orden emitida correctamente",
  "data": {...},
  "timestamp": "2026-02-12T10:30:00.000Z"
}

Este endpoint se usa típicamente como receptor de webhooks de Shopify y retorna siempre código 200 con el estado en el body.

POST /shopify/orders/to_emit_manual/:sid

Emite factura manualmente (invocación directa).

Parámetros

  • sid - ID de la organización

Body

{
  "order_id": "123456789",
  "force": false
}
POST /shopify/orders/credits_note/to_emit_manual/:sid

Emite nota de crédito manualmente desde un reembolso.

Webhooks

GET /shopify/orders/post_webhooks/:sid

Lista los webhooks registrados en Shopify.

POST /shopify/orders/post_webhooks

Registra un webhook en Shopify para notificaciones automáticas.

Body

{
  "topic": "orders/create",
  "address": "https://your-api.com/shopify/orders/to_emit/:sid",
  "format": "json"
}
POST /shopify/orders/post_webhooks/:sid/remove

Elimina un webhook registrado.

Body

{
  "webhook_id": "123456789"
}

Facturas Emitidas

GET /shopify/shipments

Obtiene facturas electrónicas emitidas (shipments).

Query Parameters

  • page - Número de página
  • per_page - Resultados por página
GET /shipments/export_json/:org_sid

Exporta JSON de factura emitida para debugging.

Query Parameters

  • invoice_sid - ID de la factura emitida

WooCommerce API

Endpoints para integración con WooCommerce.

WooCommerce utiliza autenticación mediante Consumer Key y Consumer Secret de la API REST de WooCommerce.

Configuración

POST /woo/authorization_url/token_set/:sid

Configura las credenciales de API de WooCommerce.

Parámetros

  • sid - ID de la conexión

Body

{
  "url": "https://tienda.com",
  "consumerKey": "ck_xxxxxxxxxxxxxxxxxxxxx",
  "consumerSecret": "cs_xxxxxxxxxxxxxxxxxxxxx"
}

Órdenes

GET /woo/invoices

Obtiene lista de órdenes de WooCommerce para facturación.

Query Parameters

  • status - Estado de órdenes: completed | processing | pending
  • page - Número de página
  • per_page - Órdenes por página
  • after - Fecha de inicio (ISO 8601)
  • before - Fecha de fin (ISO 8601)

Respuesta

{
  "code": 0,
  "message": "success",
  "data": [...],
  "page_context": {
    "page": 1,
    "per_page": 10,
    "has_more_page": false
  }
}
POST /woo/invoices/:invoice_id

Emite una factura específica al PAC.

Parámetros

  • invoice_id - ID de la orden en WooCommerce

Respuesta

{
  "success": true,
  "message": "FE01234567890...",
  "automaticallyRedirect": "No"
}
POST /woo/invoices/to_emit/:sid

Procesa emisión de factura desde webhook de WooCommerce.

Parámetros

  • sid - ID de la aplicación WooCommerce

Este endpoint se usa típicamente como receptor de webhooks de WooCommerce.

Webhooks

POST /woo/invoices/post_webhooks

Registra un webhook en WooCommerce para notificaciones automáticas.

Body

{
  "topic": "order.created",
  "delivery_url": "https://your-api.com/woo/invoices/to_emit/:sid"
}
POST /woo/invoices/post_webhooks/:sid/remove

Elimina un webhook registrado.

Body

{
  "webhook_id": "123"
}

Envíos

GET /woo/shipments

Obtiene información de envíos asociados a órdenes.

Exportación

GET /woo/export/pdf/:cufe

Exporta PDF de factura emitida por su CUFE.

Parámetros

  • cufe - Código Único de Factura Electrónica

Redirige automáticamente a la URL del PDF según el PAC (Docucenter, Alanube, etc.)

GET /woo/export/xml/public/:cufe/:app_id

Exporta XML de la factura electrónica.

GET /woo/export/carta/public/pdf/:cufe/:app_id

Genera carta de representación gráfica en PDF.

GET /woo/export/cinta/public/pdf/:cufe/:app_id

Genera cinta de auditoría en PDF.

Utilidades y Catálogos

Endpoints para gestión de catálogos, configuraciones y datos auxiliares.

Organizaciones

GET /token_organization

Obtiene la organización asociada al token JWT.

Headers Requeridos

  • Authorization - Token JWT con orgId

Respuesta

{
  "id": "org_123",
  "name": "Mi Organización",
  "ruc": "8-123-456",
  "connections": [...]  
}
GET /organizations/:sid

Obtiene organizaciones asociadas a un SID específico.

Query Parameters

  • module - Módulo (quickbooks, zoho, xero, etc.)
GET /organizations/connection/:organization_id

Obtiene conexiones asociadas a una organización.

POST /save_organization_settings

Guarda configuración de organización incluyendo logo.

Body (multipart/form-data)

organization_id: org_123
mostrarTituloExportable: true
logo: [file]

Aplicaciones

GET /apps/:application

Lista todas las conexiones de aplicaciones por tipo.

Parámetros

  • application - quickbooks | zoho | xero | shopify | woocommerce | dentalink

Ubicaciones y Geografía

GET /locations

Obtiene catálogo de ubicaciones fiscales de Panamá.

POST /locations

Crea una nueva ubicación en el catálogo.

GET /countries

Obtiene catálogo de países para facturación internacional.

POST /countries

Crea o actualiza un país en el catálogo.

GET /countries/:country_id

Obtiene un país específico por su ID.

GET /countries/:country_code/by_code

Obtiene un país por su código ISO (ej: PA, US, ES).

Catálogos Fiscales

GET /units

Obtiene catálogo de unidades de medida fiscales.

GET /delivery_conditions

Obtiene catálogo de condiciones de entrega (Incoterms).

GET /coins

Obtiene catálogo de monedas para facturación multi-moneda.

POST /coins

Crea o actualiza una moneda en el catálogo.

Exportación de Archivos

GET /export/xml/:cufe

Exporta el XML de una factura electrónica por su CUFE.

Parámetros

  • cufe - Código Único de Factura Electrónica

Descarga directa de archivo XML.

GET /export/pdf/:cufe

Redirige al PDF de la factura electrónica según el PAC.

Parámetros

  • cufe - Código Único de Factura Electrónica

Redirige automáticamente según el PAC: Docucenter, Alanube, Digifact, etc.

POST /send_invoice/:cufe

Envía comprobante de factura por email al cliente.

Body

{
  "organization_id": "org_123"
}

Usuario

GET /user

Obtiene información del usuario autenticado desde el token JWT.

Respuesta

{
  "userId": "user_123",
  "email": "usuario@example.com",
  "admin": false
}
GET /user_by_email

Búsqueda de usuario por email (solo para administradores).

Query Parameters

  • email - Email del usuario a buscar

Mejores Prácticas

Códigos de Respuesta y Errores

Códigos HTTP

La API utiliza códigos de estado HTTP estándar para indicar éxito o fallo de las peticiones.

Código Significado Descripción
200 OK Petición exitosa
201 Created Recurso creado exitosamente
400 Bad Request Parámetros inválidos o faltantes
401 Unauthorized Autenticación inválida o token expirado
404 Not Found Recurso no encontrado
422 Unprocessable Entity Error de validación o procesamiento
500 Internal Server Error Error interno del servidor

Formato de Errores

Los errores se devuelven en formato JSON con la siguiente estructura:

{
  "error": {
    "message": "Descripción del error",
    "code": "ERROR_CODE",
    "details": {
      "field": "campo_con_error",
      "reason": "explicación específica"
    }
  }
}

Errores Comunes

Token Expirado

{
  "error": {
    "message": "Token has expired",
    "code": "TOKEN_EXPIRED"
  }
}

Solución: Renovar el access token usando el refresh token correspondiente.

RUC Inválido

{
  "error": {
    "message": "RUC inválido detectado (0-0-0)",
    "code": "INVALID_RUC"
  }
}

Solución: Verificar que el cliente tenga un RUC válido en la plataforma de origen.

Factura Ya Emitida

{
  "skipped": true,
  "reason": "already_emitted",
  "cufe": "FE01234567890...",
  "message": "Factura ya fue emitida al PAC"
}

Solución: La factura ya tiene CUFE, no se puede reemitir. Este no es un error, es un estado informativo.

Rate Limit

Si se excede el límite de peticiones, se recibirá un error 429. El sistema implementa reintentos automáticos con backoff exponencial.

Respuestas Exitosas

Factura Emitida

{
  "success": true,
  "cufe": "FE0123456789012345678901234567890123456789012345",
  "transactionId": "abc123def456",
  "docNumber": "001-001-00001234",
  "pdfUrl": "https://api.pac.com/pdf/...",
  "xmlUrl": "https://api.pac.com/xml/..."
}

Lista de Facturas

{
  "code": 0,
  "message": "success",
  "data": [
    {
      "id": "123",
      "docNumber": "001-001-00001234",
      "customer": {...},
      "total": 150.00,
      "cufe": "FE01234567..."
    }
  ],
  "page_context": {
    "page": 1,
    "per_page": 10,
    "has_more_page": true
  }
}

Reintentos y Recuperación

Sistema de Reintentos

La API implementa reintentos automáticos para operaciones críticas:

  • Facturas: Hasta 8 intentos con backoff exponencial
  • Webhooks: Hasta 5 intentos con delays incrementales
  • Tokens: Renovación automática en errores 401
  • Rate Limits: Espera inteligente según tipo de error

Workflows Comunes

1. Configuración Inicial de Integración

// Paso 1: Obtener URL de autorización
GET /quickbooks/authorization_url
// o para Zoho
GET /authorization_url/:sid

// Paso 2: Usuario autoriza en plataforma
// (redirigir al authUri recibido)

// Paso 3: Establecer tokens
POST /quickbooks/authorization_url/token_set
{
  "code": "authorization_code",
  "realmId": "realm_id"
}

// Paso 4: Verificar conexión
GET /quickbooks/invoices?limit=1

2. Emisión de Factura (Recomendado)

Usar Sistema de Colas para Mayor Confiabilidad

Para Zoho, se recomienda usar el endpoint con cola:

// QuickBooks (procesamiento asíncrono automático vía webhook)
// Las facturas se procesan automáticamente cuando llegan webhooks

// Zoho (usar cola para asíncrono)
POST /queue/invoices/:invoice_id
{
  "organization_id": "org_123"
}

// Respuesta inmediata con job ID
{
  "success": true,
  "jobId": "12345",
  "message": "Trabajo de emisión de factura en progreso."
}

// Shopify/WooCommerce (webhook automático)
// Configurar webhook que apunte a:
POST /shopify/orders/to_emit/:sid
POST /woo/invoices/to_emit/:sid

3. Verificación de Factura Emitida

// Obtener factura con CUFE
GET /quickbooks/invoice/:invoice_id/details?minorversion=75

// Verificar en PrivateNote
{
  "Invoice": {
    "Id": "123",
    "DocNumber": "001-001-00001234",
    "PrivateNote": "CUFE: FE01234567890..."
  }
}

// Si no tiene CUFE, emitir
POST /quickbooks/to_emit
{
  "invoiceId": "123",
  "organization": "org_id"
}

Manejo de Webhooks

QuickBooks Webhooks

// Configurar endpoint en QuickBooks Developer Dashboard:
URL: https://your-api.com/quickbooks/event_processor

// Payload recibido:
{
  "eventNotifications": [{
    "realmId": "123456789",
    "dataChangeEvent": {
      "entities": [{
        "name": "Invoice",
        "id": "456",
        "operation": "Create"
      }]
    }
  }]
}

// Respuesta inmediata (< 3 segundos)
{
  "success": true,
  "webhookId": "webhook_abc123",
  "processing": "En progreso en segundo plano"
}

Shopify/WooCommerce Webhooks

// Registrar webhook
POST /shopify/orders/post_webhooks
{
  "topic": "orders/create",
  "address": "https://your-api.com/shopify/orders/to_emit/:sid"
}

// Listar webhooks activos
GET /shopify/orders/post_webhooks/:sid

// Eliminar webhook
POST /shopify/orders/post_webhooks/:sid/remove
{
  "webhook_id": "123456789"
}

Optimizaciones y Consideraciones

Rate Limits

  • QuickBooks: 500 peticiones/minuto por realmId
  • Zoho: 200 peticiones/minuto
  • Xero: 60 peticiones/minuto
  • Shopify: 2 peticiones/segundo por tienda

La API implementa reintentos automáticos con backoff exponencial.

Validaciones Automáticas

La API realiza las siguientes validaciones antes de emitir:

  • RUC válido (no 0-0-0 ni valores placeholder)
  • Verificación de CUFE existente (evita duplicados)
  • Tax codes válidos (ITBMS0, ITBMS7, ITBMS10, ITBMS15)
  • Datos de cliente completos
  • Tipo de receptor (nacional 01-02-03 o extranjero 04)

Debugging y Troubleshooting

Exportar JSON para Debugging

// QuickBooks
GET /quickbooks/export_json?id=:invoice_id

// Zoho/Xero/Shopify/WooCommerce/Dentalink
GET /xero/export_json/:org_sid?invoice_sid=:id
GET /shopify/shipments/export_json/:org_sid?invoice_sid=:id
GET /woo/export_json/:app_id
GET /dentalink/shipments/export_json/:org_sid?invoice_sid=:id

// Respuesta
{
  "path": "https://storage.googleapis.com/.../invoice.txt"
}

Verificar Configuración de Webhooks

// QuickBooks - Health check
GET /quickbooks/webhook_health

// QuickBooks - Configuración por organización
GET /quickbooks/webhook_processing_config/:realm_id/:organization_id

// QuickBooks - Actualizar configuración
POST /quickbooks/webhook_processing_config
{
  "realmId": "123",
  "organizationId": "org_456",
  "docucenterEnabled": true,
  "reason": "Habilitar procesamiento automático"
}

Mantenimiento de Mappings

// Diagnóstico de mappings
GET /quickbooks/mappings/diagnostic/:connection_id

// Limpieza de mappings obsoletos (dry run)
POST /quickbooks/mappings/cleanup/:connection_id
{
  "dryRun": true
}

// Ejecutar limpieza real
POST /quickbooks/mappings/cleanup/:connection_id
{
  "dryRun": false
}

Seguridad y Autenticación

Protección de Credenciales

  • Nunca exponer tokens en logs o respuestas de error
  • Usar HTTPS para todas las peticiones
  • Rotar refresh tokens periódicamente
  • Implementar validación de signatures en webhooks (cuando disponible)
  • Almacenar tokens encriptados en Firestore

Renovación Automática de Tokens

La API maneja automáticamente la renovación de tokens:

  • Detecta errores 401 y renueva el access token
  • Usa refresh token para obtener nuevo access token
  • Reintentos automáticos después de renovación
  • Actualiza tokens en Firestore para persistencia

Monitoreo y Logs

Logs Estructurados

Los logs de la API incluyen:

// Formato de log típico
[QUICKBOOKS] [realm_id] Procesando factura 123 - Intento 1/8
[QUICKBOOKS] [realm_id] RUC: 8-123-456, DV: 78, TIPO: 01
[QUICKBOOKS] [realm_id] Factura 123 procesada exitosamente
[QUICKBOOKS] [realm_id] CUFE: FE01234567890...

// Logs de webhook
WEBHOOK webhook_abc123: Iniciando procesamiento
WEBHOOK webhook_abc123: 3 eventos recibidos
WEBHOOK webhook_abc123: Procesamiento exitoso - 3/3 procesados

Eventos en Cola

// Ver eventos pausados
GET /quickbooks/paused_webhook_events/:realm_id?organization_id=:org_id

// Reprocesar eventos pausados
POST /quickbooks/reprocess_paused_events/:realm_id
{
  "eventIds": ["event_1", "event_2"]
}

Arquitectura y Escalabilidad

Sistema de Colas (Redis + Bee-Queue)

Para operaciones de larga duración:

  • Zoho Invoices: Cola dedicada con procesador centralizado
  • Zoho Credit Notes: Cola separada para notas de crédito
  • QuickBooks Webhooks: Procesamiento en segundo plano
  • Reintentos: Hasta 3 intentos por job con backoff exponencial
  • Failed Jobs: Almacenados en Redis para análisis

Firebase Functions

  • Region: us-central1
  • Timeout: 540 segundos (9 minutos)
  • Memory: 1GB
  • Runtime: Node.js 20+