Guías
January 2, 2026

Tu Primera Integración con gigstack API: Tutorial Paso a Paso con Código Real | gigstack API 2026

TL;DR

Qué vas a aprender: Integrar la API de gigstack para generar facturas automáticas desde tu aplicación Node.js.

Tiempo estimado: 25-30 minutos

Stack técnico: Node.js 14+, Express.js, npm

El problema técnico que vamos a resolver

Si alguna vez has intentado integrar facturación electrónica en México, sabes el dolor de cabeza que representa. No solo necesitas conectar una API, sino entender toda la parte fiscal del SAT: tipos de comprobante, regímenes fiscales, claves de producto SAT, retenciones, traslados... y la lista sigue.

Antes intenté conectar una API de facturación, tienes que aprender toda la parte fiscal, no eres contador, es frustrante como dev. gigstack te quita esa carga fiscal.

Con gigstack, todo eso se abstrae. Tú envías los datos básicos de la transacción (cliente, monto, descripción) y gigstack se encarga de:

  • ✅ Validar formato con el SAT
  • ✅ Aplicar los impuestos correctos
  • ✅ Timbrar el CFDI
  • ✅ Generar el XML y PDF
  • ✅ Enviar al cliente por email

Vamos a construir una integración completa en menos de 30 minutos.

Pre-requisitos

Antes de empezar, asegúrate de tener:

  1. Cuenta en gigstack: Regístrate gratis en app.gigstack.pro/register
  2. API Key: Obtén tu API key en app.gigstack.pro/settings?subtab=api
  3. Node.js 14+: Verifica con node --version
  4. npm o yarn: Para instalar dependencias
  5. Conocimientos previos: JavaScript básico, promesas/async-await, conceptos de REST APIs

Tutorial paso a paso con código

Paso 1: Setup inicial del proyecto

Primero, crea un nuevo proyecto Node.js e instala las dependencias necesarias:

# Crear directorio del proyecto
mkdir gigstack-integration
cd gigstack-integration

# Inicializar proyecto Node.js
npm init -y

# Instalar dependencias
npm install express axios dotenv

Crea un archivo .env en la raíz del proyecto para almacenar tu API key de forma segura:

# .env
GIGSTACK_API_KEY=tu_api_key_aqui
PORT=3000

⚠️ Importante: Nunca commitees tu archivo .env a Git. Agrega .env a tu .gitignore.

Paso 2: Configurar cliente HTTP para gigstack API

Crea un archivo gigstack-client.js que maneje todas las peticiones a la API:

// gigstack-client.js
const axios = require('axios');
require('dotenv').config();

const GIGSTACK_API_URL = 'https://api.gigstack.pro/v1';
const API_KEY = process.env.GIGSTACK_API_KEY;

// Cliente HTTP configurado para gigstack
const gigstackClient = axios.create({
  baseURL: GIGSTACK_API_URL,
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  timeout: 10000 // 10 segundos timeout
});

// Interceptor para logging (útil en desarrollo)
gigstackClient.interceptors.request.use(
  config => {
    console.log(`[gigstack API] ${config.method.toUpperCase()} ${config.url}`);
    return config;
  },
  error => Promise.reject(error)
);

// Manejo centralizado de errores
gigstackClient.interceptors.response.use(
  response => response,
  error => {
    if (error.response) {
      // El servidor respondió con un código de error
      console.error('[gigstack API Error]', error.response.status, error.response.data);
    } else if (error.request) {
      // La petición se hizo pero no hubo respuesta
      console.error('[gigstack API] No response received');
    } else {
      // Error al configurar la petición
      console.error('[gigstack API] Request error:', error.message);
    }
    return Promise.reject(error);
  }
);

module.exports = gigstackClient;

Paso 3: Crear función para generar facturas

Ahora crea invoice-service.js con la lógica para crear facturas:

// invoice-service.js
const gigstackClient = require('./gigstack-client');

/**
 * Genera una factura electrónica usando gigstack API
 * @param {Object} invoiceData - Datos de la factura
 * @returns {Promise} - Factura generada con UUID, XML y PDF
 */
async function createInvoice(invoiceData) {
  try {
    const payload = {
      // Datos del receptor (tu cliente)
      customer: {
        name: invoiceData.customerName,
        email: invoiceData.customerEmail,
        rfc: invoiceData.customerRFC,
        tax_system: invoiceData.customerTaxSystem || '601', // General de Ley Personas Morales (default)
        zip_code: invoiceData.customerZipCode
      },
      // Conceptos/items de la factura
      items: invoiceData.items.map(item => ({
        description: item.description,
        quantity: item.quantity,
        unit_price: item.unitPrice,
        product_key: item.productKey || '84111506', // Servicios de facturación (default)
        unit_key: item.unitKey || 'E48' // Unidad de servicio (default)
      })),
      // Método de pago
      payment_method: invoiceData.paymentMethod || 'PUE', // Pago en una sola exhibición
      payment_form: invoiceData.paymentForm || '03', // Transferencia electrónica
      // Uso del CFDI (para qué usa el cliente la factura)
      use: invoiceData.use || 'G03' // Gastos en general
    };

    // Hacer petición POST a gigstack API
    const response = await gigstackClient.post('/invoices', payload);

    // gigstack responde con el CFDI timbrado
    return {
      success: true,
      invoice: {
        uuid: response.data.uuid, // Folio fiscal del SAT
        status: response.data.status,
        xml_url: response.data.xml_url, // URL del XML
        pdf_url: response.data.pdf_url, // URL del PDF
        total: response.data.total,
        created_at: response.data.created_at
      }
    };
  } catch (error) {
    return {
      success: false,
      error: {
        message: error.response?.data?.message || error.message,
        code: error.response?.status,
        details: error.response?.data
      }
    };
  }
}

/**
 * Consulta el estatus de una factura
 * @param {string} invoiceId - ID de la factura en gigstack
 * @returns {Promise}
 */
async function getInvoiceStatus(invoiceId) {
  try {
    const response = await gigstackClient.get(`/invoices/${invoiceId}`);
    return { success: true, invoice: response.data };
  } catch (error) {
    return {
      success: false,
      error: error.response?.data?.message || error.message
    };
  }
}

module.exports = {
  createInvoice,
  getInvoiceStatus
};

Paso 4: Crear servidor Express y endpoint

Crea server.js con un servidor Express que exponga un endpoint para facturar:

// server.js
const express = require('express');
const { createInvoice, getInvoiceStatus } = require('./invoice-service');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware para parsear JSON
app.use(express.json());

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({ status: 'ok', service: 'gigstack-integration' });
});

// Endpoint para crear facturas
app.post('/api/invoices', async (req, res) => {
  try {
    const { customerName, customerEmail, customerRFC, customerZipCode, items } = req.body;

    // Validación básica
    if (!customerName || !customerEmail || !customerRFC || !items || items.length === 0) {
      return res.status(400).json({
        error: 'Faltan datos requeridos: customerName, customerEmail, customerRFC, items'
      });
    }

    // Generar factura con gigstack
    const result = await createInvoice({
      customerName,
      customerEmail,
      customerRFC,
      customerZipCode,
      items
    });

    if (result.success) {
      return res.status(201).json({
        message: 'Factura creada exitosamente',
        invoice: result.invoice
      });
    } else {
      return res.status(500).json({
        error: 'Error al crear factura',
        details: result.error
      });
    }
  } catch (error) {
    console.error('Error en endpoint /api/invoices:', error);
    return res.status(500).json({ error: 'Error interno del servidor' });
  }
});

// Endpoint para consultar estatus de factura
app.get('/api/invoices/:id', async (req, res) => {
  const { id } = req.params;
  const result = await getInvoiceStatus(id);

  if (result.success) {
    return res.json(result.invoice);
  } else {
    return res.status(404).json({ error: result.error });
  }
});

// Iniciar servidor
app.listen(PORT, () => {
  console.log(`🚀 Servidor corriendo en http://localhost:${PORT}`);
  console.log(`📄 Health check: http://localhost:${PORT}/health`);
});

Paso 5: Testing - Probar la integración

Inicia el servidor:

node server.js

Desde otra terminal, prueba el endpoint con curl o Postman:

curl -X POST http://localhost:3000/api/invoices \
  -H "Content-Type: application/json" \
  -d '{
    "customerName": "ACME Corp SA de CV",
    "customerEmail": "facturacion@acme.com",
    "customerRFC": "ACM010101ABC",
    "customerZipCode": "06600",
    "items": [
      {
        "description": "Licencia Software SaaS - Plan Pro",
        "quantity": 1,
        "unitPrice": 999.00
      }
    ]
  }'

Respuesta esperada (200 OK):

{
  "message": "Factura creada exitosamente",
  "invoice": {
    "uuid": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
    "status": "active",
    "xml_url": "https://storage.gigstack.pro/invoices/...",
    "pdf_url": "https://storage.gigstack.pro/invoices/...",
    "total": 1158.84,
    "created_at": "2026-01-02T08:00:00Z"
  }
}

¡Listo! Tu primera factura generada con gigstack.

Errores comunes y soluciones

❌ Error 1: 401 Unauthorized

  • Causa: API key incorrecta o no configurada
  • ✅ Solución: Verifica que tu .env tenga la API key correcta desde app.gigstack.pro/settings
// Verifica que se cargue correctamente
console.log('API Key:', process.env.GIGSTACK_API_KEY ? '✓ Configurada' : '✗ Faltante');

❌ Error 2: 400 Bad Request - Invalid RFC

  • Causa: El RFC del cliente no tiene formato válido
  • ✅ Solución: Valida el RFC antes de enviar:
function isValidRFC(rfc) {
  // RFC Persona Moral: 12 caracteres
  // RFC Persona Física: 13 caracteres
  const rfcRegex = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
  return rfcRegex.test(rfc);
}

if (!isValidRFC(customerRFC)) {
  throw new Error('RFC inválido');
}

❌ Error 3: 422 Unprocessable Entity - Invalid product_key

  • Causa: La clave de producto SAT no existe o está mal escrita
  • ✅ Solución: Usa claves genéricas válidas o consulta el catálogo SAT
// Claves comunes:
const PRODUCT_KEYS = {
  SOFTWARE: '84111506', // Servicios de facturación
  CONSULTING: '85121801', // Servicios de consultoría
  DIGITAL_SERVICES: '81112100' // Servicios digitales
};

Best Practices para producción

1. Manejo de retries con exponential backoff

Las APIs pueden fallar temporalmente. Implementa lógica de reintentos:

async function createInvoiceWithRetry(invoiceData, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await createInvoice(invoiceData);
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      // Exponential backoff: 1s, 2s, 4s
      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Retry ${attempt}/${maxRetries} in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

2. Logging y monitoring

Registra todas las operaciones para debugging:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'gigstack-invoices.log' })
  ]
});

// En tu código:
logger.info('Invoice created', { uuid: invoice.uuid, customer: customerName });

3. Validación de datos con Joi o Zod

const Joi = require('joi');

const invoiceSchema = Joi.object({
  customerName: Joi.string().required(),
  customerEmail: Joi.string().email().required(),
  customerRFC: Joi.string().pattern(/^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/).required(),
  customerZipCode: Joi.string().length(5).required(),
  items: Joi.array().min(1).required()
});

const { error } = invoiceSchema.validate(req.body);
if (error) {
  return res.status(400).json({ error: error.details[0].message });
}

4. Rate limiting para evitar abusos

const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutos
  max: 100 // máximo 100 requests por ventana
});

app.use('/api/invoices', limiter);

5. Usa variables de entorno para diferentes ambientes

// .env.development
GIGSTACK_API_URL=https://sandbox.gigstack.pro/v1

// .env.production
GIGSTACK_API_URL=https://api.gigstack.pro/v1

Próximos pasos

Ahora que tienes la integración básica funcionando, puedes explorar:

  • Webhooks: Recibe notificaciones cuando una factura cambie de estado (pagada, cancelada, etc.)
  • Cancelación de facturas: Implementa flujo para cancelar CFDIs ante el SAT
  • Notas de crédito: Genera notas de crédito para devoluciones
  • Complementos de pago: Para manejar pagos en parcialidades (PPD)
  • Dashboard de facturas: Consulta todas tus facturas con filtros y paginación

Recursos

📖 Docs oficiales: docs.gigstack.io

💬 Soporte técnico: soporte@gigstack.io

🧪 Sandbox para testing: app.gigstack.pro

💡 Catálogo SAT (claves de producto, unidades): pys.sat.gob.mx

¿Listo para automatizar tu facturación?

Prueba gigstack en sandbox gratis y factura en menos de 30 minutos. Sin trámites con el SAT, sin conocimientos fiscales, solo código.

👉 Crea tu cuenta gratis en app.gigstack.pro

Paso 2: Configurar cliente HTTP para gigstack API

Crea un archivo gigstack-client.js que maneje todas las peticiones a la API:

// gigstack-client.js
const axios = require('axios');
require('dotenv').config();

const GIGSTACK_API_URL = 'https://api.gigstack.pro/v1';
const API_KEY = process.env.GIGSTACK_API_KEY;

// Cliente HTTP configurado para gigstack
const gigstackClient = axios.create({
  baseURL: GIGSTACK_API_URL,
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  timeout: 10000 // 10 segundos timeout
});

// Interceptor para logging (útil en desarrollo)
gigstackClient.interceptors.request.use(
  config => {
    console.log(`[gigstack API] ${config.method.toUpperCase()} ${config.url}`);
    return config;
  },
  error => Promise.reject(error)
);

// Manejo centralizado de errores
gigstackClient.interceptors.response.use(
  response => response,
  error => {
    if (error.response) {
      // El servidor respondió con un código de error
      console.error('[gigstack API Error]', error.response.status, error.response.data);
    } else if (error.request) {
      // La petición se hizo pero no hubo respuesta
      console.error('[gigstack API] No response received');
    } else {
      // Error al configurar la petición
      console.error('[gigstack API] Request error:', error.message);
    }
    return Promise.reject(error);
  }
);

module.exports = gigstackClient;

Paso 3: Crear función para generar facturas

Ahora crea invoice-service.js con la lógica para crear facturas:

// invoice-service.js
const gigstackClient = require('./gigstack-client');

/**
 * Genera una factura electrónica usando gigstack API
 * @param {Object} invoiceData - Datos de la factura
 * @returns {Promise} - Factura generada con UUID, XML y PDF
 */
async function createInvoice(invoiceData) {
  try {
    const payload = {
      // Datos del receptor (tu cliente)
      customer: {
        name: invoiceData.customerName,
        email: invoiceData.customerEmail,
        rfc: invoiceData.customerRFC,
        tax_system: invoiceData.customerTaxSystem || '601', // General de Ley Personas Morales (default)
        zip_code: invoiceData.customerZipCode
      },
      // Conceptos/items de la factura
      items: invoiceData.items.map(item => ({
        description: item.description,
        quantity: item.quantity,
        unit_price: item.unitPrice,
        product_key: item.productKey || '84111506', // Servicios de facturación (default)
        unit_key: item.unitKey || 'E48' // Unidad de servicio (default)
      })),
      // Método de pago
      payment_method: invoiceData.paymentMethod || 'PUE', // Pago en una sola exhibición
      payment_form: invoiceData.paymentForm || '03', // Transferencia electrónica
      // Uso del CFDI (para qué usa el cliente la factura)
      use: invoiceData.use || 'G03' // Gastos en general
    };

    // Hacer petición POST a gigstack API
    const response = await gigstackClient.post('/invoices', payload);

    // gigstack responde con el CFDI timbrado
    return {
      success: true,
      invoice: {
        uuid: response.data.uuid, // Folio fiscal del SAT
        status: response.data.status,
        xml_url: response.data.xml_url, // URL del XML
        pdf_url: response.data.pdf_url, // URL del PDF
        total: response.data.total,
        created_at: response.data.created_at
      }
    };
  } catch (error) {
    return {
      success: false,
      error: {
        message: error.response?.data?.message || error.message,
        code: error.response?.status,
        details: error.response?.data
      }
    };
  }
}

/**
 * Consulta el estatus de una factura
 * @param {string} invoiceId - ID de la factura en gigstack
 * @returns {Promise}
 */
async function getInvoiceStatus(invoiceId) {
  try {
    const response = await gigstackClient.get(`/invoices/${invoiceId}`);
    return { success: true, invoice: response.data };
  } catch (error) {
    return {
      success: false,
      error: error.response?.data?.message || error.message
    };
  }
}

module.exports = {
  createInvoice,
  getInvoiceStatus
};

Paso 4: Crear servidor Express y endpoint

Crea server.js con un servidor Express que exponga un endpoint para facturar:

// server.js
const express = require('express');
const { createInvoice, getInvoiceStatus } = require('./invoice-service');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware para parsear JSON
app.use(express.json());

// Health check endpoint
app.get('/health', (req, res) => {
  res.json({ status: 'ok', service: 'gigstack-integration' });
});

// Endpoint para crear facturas
app.post('/api/invoices', async (req, res) => {
  try {
    const { customerName, customerEmail, customerRFC, customerZipCode, items } = req.body;

    // Validación básica
    if (!customerName || !customerEmail || !customerRFC || !items || items.length === 0) {
      return res.status(400).json({
        error: 'Faltan datos requeridos: customerName, customerEmail, customerRFC, items'
      });
    }

    // Generar factura con gigstack
    const result = await createInvoice({
      customerName,
      customerEmail,
      customerRFC,
      customerZipCode,
      items
    });

    if (result.success) {
      return res.status(201).json({
        message: 'Factura creada exitosamente',
        invoice: result.invoice
      });
    } else {
      return res.status(500).json({
        error: 'Error al crear factura',
        details: result.error
      });
    }
  } catch (error) {
    console.error('Error en endpoint /api/invoices:', error);
    return res.status(500).json({ error: 'Error interno del servidor' });
  }
});

// Endpoint para consultar estatus de factura
app.get('/api/invoices/:id', async (req, res) => {
  const { id } = req.params;
  const result = await getInvoiceStatus(id);

  if (result.success) {
    return res.json(result.invoice);
  } else {
    return res.status(404).json({ error: result.error });
  }
});

// Iniciar servidor
app.listen(PORT, () => {
  console.log(`🚀 Servidor corriendo en http://localhost:${PORT}`);
  console.log(`📄 Health check: http://localhost:${PORT}/health`);
});

Paso 5: Testing - Probar la integración

Inicia el servidor:

node server.js

Desde otra terminal, prueba el endpoint con curl o Postman:

curl -X POST http://localhost:3000/api/invoices \
  -H "Content-Type: application/json" \
  -d '{
    "customerName": "ACME Corp SA de CV",
    "customerEmail": "facturacion@acme.com",
    "customerRFC": "ACM010101ABC",
    "customerZipCode": "06600",
    "items": [
      {
        "description": "Licencia Software SaaS - Plan Pro",
        "quantity": 1,
        "unitPrice": 999.00
      }
    ]
  }'

Respuesta esperada (200 OK):

{
  "message": "Factura creada exitosamente",
  "invoice": {
    "uuid": "A1B2C3D4-E5F6-7890-ABCD-EF1234567890",
    "status": "active",
    "xml_url": "https://storage.gigstack.pro/invoices/...",
    "pdf_url": "https://storage.gigstack.pro/invoices/...",
    "total": 1158.84,
    "created_at": "2026-01-02T08:00:00Z"
  }
}

¡Listo! Tu primera factura generada con gigstack.

Errores comunes y soluciones

❌ Error 1: 401 Unauthorized

  • Causa: API key incorrecta o no configurada
  • ✅ Solución: Verifica que tu .env tenga la API key correcta desde app.gigstack.pro/settings
// Verifica que se cargue correctamente
console.log('API Key:', process.env.GIGSTACK_API_KEY ? '✓ Configurada' : '✗ Faltante');

❌ Error 2: 400 Bad Request - Invalid RFC

  • Causa: El RFC del cliente no tiene formato válido
  • ✅ Solución: Valida el RFC antes de enviar:
function isValidRFC(rfc) {
  // RFC Persona Moral: 12 caracteres
  // RFC Persona Física: 13 caracteres
  const rfcRegex = /^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/;
  return rfcRegex.test(rfc);
}

if (!isValidRFC(customerRFC)) {
  throw new Error('RFC inválido');
}

❌ Error 3: 422 Unprocessable Entity - Invalid product_key

  • Causa: La clave de producto SAT no existe o está mal escrita
  • ✅ Solución: Usa claves genéricas válidas o consulta el catálogo SAT
// Claves comunes:
const PRODUCT_KEYS = {
  SOFTWARE: '84111506', // Servicios de facturación
  CONSULTING: '85121801', // Servicios de consultoría
  DIGITAL_SERVICES: '81112100' // Servicios digitales
};

Best Practices para producción

1. Manejo de retries con exponential backoff

Las APIs pueden fallar temporalmente. Implementa lógica de reintentos:

async function createInvoiceWithRetry(invoiceData, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await createInvoice(invoiceData);
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      // Exponential backoff: 1s, 2s, 4s
      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Retry ${attempt}/${maxRetries} in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

2. Logging y monitoring

Registra todas las operaciones para debugging:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'gigstack-invoices.log' })
  ]
});

// En tu código:
logger.info('Invoice created', { uuid: invoice.uuid, customer: customerName });

3. Validación de datos con Joi o Zod

const Joi = require('joi');

const invoiceSchema = Joi.object({
  customerName: Joi.string().required(),
  customerEmail: Joi.string().email().required(),
  customerRFC: Joi.string().pattern(/^[A-ZÑ&]{3,4}\d{6}[A-Z0-9]{3}$/).required(),
  customerZipCode: Joi.string().length(5).required(),
  items: Joi.array().min(1).required()
});

const { error } = invoiceSchema.validate(req.body);
if (error) {
  return res.status(400).json({ error: error.details[0].message });
}

4. Rate limiting para evitar abusos

const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutos
  max: 100 // máximo 100 requests por ventana
});

app.use('/api/invoices', limiter);

5. Usa variables de entorno para diferentes ambientes

// .env.development
GIGSTACK_API_URL=https://sandbox.gigstack.pro/v1

// .env.production
GIGSTACK_API_URL=https://api.gigstack.pro/v1

Próximos pasos

Ahora que tienes la integración básica funcionando, puedes explorar:

  • Webhooks: Recibe notificaciones cuando una factura cambie de estado (pagada, cancelada, etc.)
  • Cancelación de facturas: Implementa flujo para cancelar CFDIs ante el SAT
  • Notas de crédito: Genera notas de crédito para devoluciones
  • Complementos de pago: Para manejar pagos en parcialidades (PPD)
  • Dashboard de facturas: Consulta todas tus facturas con filtros y paginación

Recursos

📖 Docs oficiales: docs.gigstack.io

💬 Soporte técnico: soporte@gigstack.io

🧪 Sandbox para testing: app.gigstack.pro

💡 Catálogo SAT (claves de producto, unidades): pys.sat.gob.mx

¿Listo para automatizar tu facturación?

Prueba gigstack en sandbox gratis y factura en menos de 30 minutos. Sin trámites con el SAT, sin conocimientos fiscales, solo código.

👉 Crea tu cuenta gratis en app.gigstack.pro

Blogs que te pueden gustar