Documentación API

Integrá tu aplicación con Gestion Nube para automatizar catálogos, precios, inventario y ventas.

Navegación rápida

Elegí la sección que necesitás para comenzar tu integración

Inicio Rápido

Todo lo que necesitás para empezar a usar la API

Gestión de Acceso

Administrá tokens y verificá tu autenticación

Inicio Rápido

API de Gestion Nube

La API permite integrar sistemas externos con Gestion Nube para automatizar procesos como sincronización de precios, catálogos, inventario y ventas. Todas las respuestas se entregan en JSON salvo las exportaciones de archivos.

URL base y versionado

  • Producción: https://app.gestion.moda/api
  • Sandbox o local: http://localhost/api
  • Versión actual: v1 (todas las rutas están prefijadas con /api/v1)

Autenticación

La autenticación se realiza mediante tokens personales emitidos por Laravel Sanctum. Generá un token enviando tus credenciales registradas.

curl -X POST "https://app.gestion.moda/api/sanctum/token" \
  -H "Accept: application/json" \
  -d '{
    "email": "usuario@ejemplo.com",
    "password": "********",
    "device_name": "integracion-tienda",
    "abilities": ["products:read", "prices:read", "inventory:read", "sales:read", "sales:write"]
  }'
  • device_name identifica el token emitido.
  • abilities es opcional. Si se omite, se asigna prices:read.
  • Respuesta: token en texto plano. Guardalo porque no vuelve a mostrarse.
  • Límite: 5 solicitudes por minuto (límite throttle:auth).

Permisos disponibles (abilities)

Permiso Descripción
products:read Leer información de productos (listado, detalle, exportación)
products:write Actualizar productos (precios minorista y mayorista)
prices:read Acceder a listas de precios
prices:write Actualizar precios vía endpoint /precios (incluye costo unitario)
inventory:read Consultar stock disponible por producto, talla y tienda
inventory:write Definido, no implementado aún en la API pública
sales:read Consultar ventas, clientes, items y pagos
sales:write Crear ventas por API y registrar pagos opcionales
production:write Registrar producciones con descuento automático de insumos (POST /produccion)
costs:write Crear gastos con categoría, cuenta y pagos (POST /gastos)
supplies:write Registrar compras de insumos con recepción automática al inventario (POST /compras/insumos)
clients:write Crear clientes con datos fiscales opcionales (POST /clientes)
categories:*, accounts:*, stores:*, clients:read Scopes definidos, no implementados aún en la API pública

Contrato técnico recomendado: OpenAPI v1. Las rutas action-style de v1 siguen soportadas por compatibilidad.

Incluí el token en todas las rutas protegidas usando el encabezado:

Authorization: Bearer <token>
Accept: application/json

Gestión de Acceso

Gestión de tokens

Estas rutas requieren autenticación y comparten el límite general de 60 solicitudes por minuto.

Método Ruta Descripción
GET /api/v1/tokens Lista los tokens del usuario autenticado con campos id, name, abilities, last_used_at, created_at, expires_at.
DELETE /api/v1/tokens/current Revoca el token utilizado en la llamada actual (devuelve 204).
DELETE /api/v1/tokens/{tokenId} Revoca un token especifico del usuario. Responde 404 si no existe.

Usuario autenticado y chequeo rápido

Método Ruta Descripción
GET /api/v1/usuario Devuelve el usuario autenticado incluyendo active_company.
GET /api/v1/ping Respuesta {"status":"ok"} para verificar que el token funciona.
GET /api/v1/precios/demo Mensaje de prueba disponible solo con la habilidad prices:read.

Referencia de API

Módulo de precios

Requiere el scope prices:read. Usa paginación estándar y cabeceras adicionales con totales.

Listar precios vigentes

GET /api/v1/precios/obtener

Parámetros de consulta:

  • per_page: cantidad por página (1-200, por defecto 50).
  • q: búsqueda por nombre o código.
  • lista_id o price_list_id: fuerza una lista específica; si se omite se toma la lista base activa de la compañía.
{
  "price_list": {
    "id": 7,
    "descripcion": "Lista Mayorista",
    "is_base": false,
    "moneda": "ARS",
    "variacion": 15
  },
  "data": [
    { "id": 120, "code": "REM-001", "name": "Remera Oversize", "price": 11999.9 },
    { "id": 122, "code": "REM-002", "name": "Remera Boxy", "price": 12499.0 }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 50,
    "total": 87,
    "last_page": 2,
    "from": 1,
    "to": 50,
    "has_more_pages": true
  },
  "links": {
    "first": "https://app.gestion.moda/api/v1/precios/obtener?page=1",
    "last": "https://app.gestion.moda/api/v1/precios/obtener?page=2",
    "prev": null,
    "next": "https://app.gestion.moda/api/v1/precios/obtener?page=2"
  }
}

Cabeceras útiles: X-Total-Count, X-Per-Page, X-Current-Page, X-Last-Page.

Listar listas de precios

GET /api/v1/precios/listas

Requiere la habilidad prices:read. Devuelve todas las listas de precios activas de la compañía.

{
  "data": [
    {
      "id": 1,
      "descripcion": "Lista Base Minorista",
      "is_base": true,
      "variacion": null,
      "moneda": "ARS"
    },
    {
      "id": 2,
      "descripcion": "Lista Mayorista",
      "is_base": false,
      "variacion": -15,
      "moneda": "ARS"
    }
  ]
}

Actualizar precio en lista base

PUT /api/v1/precios/{lista_id}/producto/{product_id}

Requiere la habilidad prices:write. Solo permite editar listas base (is_base = true). Las listas derivadas calculan precios automáticamente.

Parámetros del body (JSON):

  • price (requerido): precio del producto. Si envías 0, el precio se elimina de la lista.
  • aditional_price (opcional): precio adicional.
curl -X PUT "https://app.gestion.moda/api/v1/precios/1/producto/120" \
  -H "Authorization: Bearer TU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"price": 2500.00}'
{
  "message": "Precio actualizado correctamente",
  "price_list_id": 1,
  "product_id": 120,
  "product_code": "REM-001",
  "product_name": "Remera Oversize",
  "price": 2500.00,
  "aditional_price": null
}

Módulo de productos

Disponible con la habilidad products:read.

Listar productos

GET /api/v1/productos/obtener

Filtros disponibles:

  • per_page, q, code
  • category_id, provider_id
  • active (1 o 0)
  • include_stock y include_variants para anexar stock total y variantes por tienda.

Ver detalle

GET /api/v1/productos/ver/{id}. Admite los mismos flags para incluir stock y variantes.

{
  "id": 120,
  "code": "REM-001",
  "name": "Remera Oversize",
  "description": "Algodon 24/1",
  "retailer_price": 16999,
  "wholesaler_price": 11999,
  "unit_cost": 5400,
  "category": "Remeras",
  "provider": "Textiles SRL",
  "stock_total": 320,
  "variantes": [
    {
      "size_id": 4,
      "size": "M",
      "barcode": "7790000000012",
      "stock_por_tienda": [
        { "store_id": 1, "store_name": "Deposito Central", "stock_disponible": 120 },
        { "store_id": 2, "store_name": "Sucursal Palermo", "stock_disponible": 45 }
      ]
    }
  ]
}

Exportar catálogo

GET /api/v1/productos/exportar devuelve un archivo CSV (o XLSX si está disponible maatwebsite/excel). Respeta los mismos filtros que el listado y admite include_stock, include_variants. Esta ruta usa el limitador throttle:exports (10 solicitudes por minuto).

Actualizar producto

PUT /api/v1/productos/{id} o PATCH /api/v1/productos/{id}

Requiere la habilidad products:write. Permite actualizar los precios minorista y mayorista de un producto.

Campos disponibles (al menos uno requerido):

  • retailer_price: precio minorista
  • wholesaler_price: precio mayorista
curl -X PUT "https://app.gestion.moda/api/v1/productos/120" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "retailer_price": 18500,
    "wholesaler_price": 13000
  }'

Respuesta:

{
  "message": "Producto actualizado correctamente",
  "data": {
    "id": 120,
    "code": "REM-001",
    "name": "Remera Oversize",
    "retailer_price": 18500,
    "wholesaler_price": 13000,
    "unit_cost": 5400
  }
}

Actualizar precios (endpoint alternativo)

PUT /api/v1/productos/{id}/precios o PATCH /api/v1/productos/{id}/precios

Requiere la habilidad prices:write. Permite actualizar los precios de un producto incluyendo el costo unitario.

Campos disponibles (al menos uno requerido):

  • retailer_price: precio minorista
  • wholesaler_price: precio mayorista
  • unit_cost: costo unitario
curl -X PUT "https://app.gestion.moda/api/v1/productos/120/precios" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "retailer_price": 18500,
    "wholesaler_price": 13000
  }'

Respuesta:

{
  "message": "Precios actualizados correctamente",
  "data": {
    "id": 120,
    "code": "REM-001",
    "name": "Remera Oversize",
    "retailer_price": 18500,
    "wholesaler_price": 13000,
    "unit_cost": 5400
  }
}

Nota: Si el producto está vinculado a TiendaNube o MercadoLibre, los cambios de precio se sincronizarán automáticamente.

Módulo de inventario

Disponible con la habilidad inventory:read. Permite consultar el stock disponible (available_quantity) de los productos.

Listar inventario

GET /api/v1/inventario/obtener

Filtros disponibles:

  • product_id: filtrar por producto específico
  • size_id: filtrar por talla
  • store_id: filtrar por tienda/depósito
  • code: filtrar por código de producto
  • q: búsqueda por nombre o código
  • include_physical: incluir stock físico y en producción
  • per_page: paginación (1-200, por defecto 50)
{
  "data": [
    {
      "inventory_id": 1234,
      "product_id": 120,
      "product_code": "REM-001",
      "product_name": "Remera Oversize",
      "size_id": 4,
      "size_name": "M",
      "store_id": 1,
      "store_name": "Deposito Central",
      "available_quantity": 120,
      "barcode": "7790000000012",
      "sku": "REM-001-M"
    }
  ],
  "meta": { /* paginación estándar */ },
  "links": { /* links de navegación */ }
}

Inventario por producto

GET /api/v1/inventario/{product_id}

Devuelve el stock total del producto y el detalle por talla y tienda.

{
  "product_id": 120,
  "product_code": "REM-001",
  "product_name": "Remera Oversize",
  "stock_total": 320,
  "variantes": [
    {
      "size_id": 4,
      "size_name": "M",
      "barcode": "7790000000012",
      "sku": "REM-001-M",
      "stock_total_talla": 165,
      "stock_por_tienda": [
        { "inventory_id": 1234, "store_id": 1, "store_name": "Deposito Central", "available_quantity": 120 },
        { "inventory_id": 1235, "store_id": 2, "store_name": "Sucursal Palermo", "available_quantity": 45 }
      ]
    }
  ]
}

Módulo de ventas

La prioridad actual de la API v1 está en ventas. Las nuevas integraciones deberían usar las rutas REST y mantener las legacy solo por compatibilidad.

Bootstrap de referencias

GET /api/v1/ventas/referencias

Ahora tambien devuelve listas de precio, modos de venta, proveedores, vendedores, asociados y configuracion por defecto para bootstrap operativo.

Disponible con sales:read o sales:write. Devuelve canales, estados, tipos de venta, monedas, depósitos, cuentas y métodos de envío para preparar el POST /ventas.

Listar ventas

GET /api/v1/ventas es la ruta recomendada. GET /api/v1/ventas/obtener sigue activa como alias legacy.

El listado devuelve solo ventas activas, no archivadas y no presupuesto, respetando la visibilidad real del usuario del token.

Filtros disponibles:

  • limit o per_page
  • search, dateFrom, dateTo
  • from, to para compatibilidad legacy
  • client_id, channel_id, store_id, sale_state_id
  • include_details y include_payments para traer pagos aplicados y creditos por saldo a favor
{
  "data": [
    {
      "id": 5432,
      "number": 5432,
      "client": { "id": 123, "name": "Juan Pérez" },
      "totals": { "gross": 45000, "due": 0 }
    }
  ]
}

Crear ventas

POST /api/v1/ventas

El alta sigue siendo simplificada: cada item admite discount, payment_method_id es opcional y cualquier sobrepago pasa a saldo a favor del cliente.

Requiere sales:write. El servidor calcula subtotales, total, IVA, costo, profit y saldo. Si discount_inventory=true, reutiliza la lógica actual de stock y respeta allow_negative_stock.

Payload inicial:

  • client_id, channel_id, sale_type_id, currency_id
  • items[] con product_id, size_id, quantity, unit_price y opcional discount
  • Opcionales: date_sale, delivery_date, store_id, sale_state_id, payment_method_id, shipping_method_id, comments, discount_amount, shipping_cost_amount, payments[], integration_source, integration_id para deduplicacion por compania
Compatibilidad: La documentación pública recomienda las rutas REST, pero /ventas/obtener y /ventas/ver/{id} siguen soportadas en v1.

Módulo de producción

POST /api/v1/produccion - requiere production:write.

Registra una producción usando la lista de insumos definida en la ficha del producto. Calcula los costos totales y unitarios automáticamente y, salvo que sea una producción planificada, descuenta los insumos del stock y suma las unidades producidas al stock del producto.

Payload:

  • Obligatorios: product_id, size_id, quantity
  • Opcionales: store_id, date_production, planning, add_to_inventory (default true), create_service_expenses, all_services_paid, description
Descuento automático: No hace falta enviar el detalle de insumos: se toma automáticamente de la ficha del producto. Por cada insumo se descuenta cantidad_producida × cantidad_por_unidad (según lo configurado en el producto).

Módulo de gastos

POST /api/v1/gastos - requiere costs:write.

Crea un gasto (Cost) con categoría, tipo, proveedor y cuenta contable. Si la suma de payments[] cubre el amount, el gasto queda marcado como pagado y cada pago descuenta el balance de su cuenta.

Payload:

  • Obligatorios: cost_type_id, amount
  • Opcionales: sub_cost_type_id, cost_category_id, provider_id, channel_id, bill_date, cost_year, cost_month, vat_rate, amount_plan, description
  • payments[] con amount, date_payment, account_id, description

Módulo de compras de insumos

POST /api/v1/compras/insumos - requiere supplies:write.

Registra una compra con recepción automática: para cada insumo con control de stock activado, las unidades compradas se suman al stock en el momento de crear la compra. Si marcás la compra como gasto (opción por defecto), también se actualiza el costo final del insumo.

Payload:

  • Obligatorio: items[] con supply_id, quantity, unit_cost y opcional vat_rate
  • Opcionales: provider_id, buy_date, description, expense (bool)
  • payments[] con amount, date_payment, account_id, description
Validación: La suma de payments[] no puede superar el total de la compra. Si coincide, la compra queda como paid=true.

Módulo de clientes

POST /api/v1/clientes - requiere clients:write.

Crea un cliente. Los datos fiscales son opcionales; si los enviás, se valida la longitud del documento (CUIT y CUIL deben tener 11 dígitos, DNI 8). Según los datos fiscales informados, el sistema marca automáticamente si el cliente es facturable. Si ya existe otro cliente activo con el mismo nombre en la empresa, la llamada devuelve el código 409.

Payload:

  • Obligatorio: name
  • Contacto: email, phone_number, cellphone_number, address, postal_code, city, province
  • Clasificación: client_type_id, client_state_id, client_category_id, channel_id, price_list_id
  • Fiscales (opcionales, todos juntos o ninguno): bill_identification_number_type (CUIT/CUIL/DNI), bill_identification_number, kind_responsibility_id, bill_name, bill_address, bill_city, bill_province, bill_country
Campos calculados: El campo billable se calcula automáticamente según los datos fiscales informados; no se puede enviar ni modificar desde la llamada.

Paginación y formato

  • Todas las colecciones devuelven los bloques meta y links propios de la paginación de Laravel.
  • Los listados agregan cabeceras con totalizadores para facilitar integraciones.
  • Los importes se devuelven como decimales. Ajustá el formateo según tu moneda.
  • Las rutas autenticadas respetan la compañía activa del usuario (active_company) para garantizar el aislamiento multiempresa.

Guías y Seguridad

Límites de Solicitudes (Rate Limiting)

La API implementa límites de solicitudes para proteger el servicio y garantizar disponibilidad para todos los usuarios.

Límites por Tipo de Operación

Tipo Límite Ventana
API General 60 solicitudes 1 minuto
Exportaciones 10 solicitudes 1 minuto
Autenticación 5 intentos 1 minuto

Respuesta al Exceder Límite

Cuando se excede el límite, la API retorna código 429 Too Many Requests con el header Retry-After indicando segundos de espera.

{
  "message": "Demasiadas solicitudes. Intenta nuevamente en un minuto.",
  "retry_after": 60
}

Headers de respuesta:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json
Recomendación: Implementá backoff exponencial: esperá el tiempo indicado en Retry-After antes de reintentar.

Manejo de errores

Código Motivo Detalle
400 Solicitud inválida Parámetros con formato incorrecto.
401 No autenticado Falta token o es inválido.
403 Sin permisos No dispone de la habilidad requerida.
404 Recurso inexistente Ejemplo: producto o lista no encontrada.
422 Validación Datos faltantes o inválidos, típico en /sanctum/token.
429 Rate limit Se excedió el límite configurado para la ruta.
500 Error interno Registrar incidente y contactar soporte con el request-id.

Buenas prácticas y seguridad

  • Usá siempre HTTPS en producción.
  • Rotá y revocá tokens periódicamente.
  • Limitate a las habilidades necesarias para cada integración.
  • Respetá los límites: 60 solicitudes por minuto para el grupo general y 10 por minuto para exportaciones.
  • No mezcles datos de distintas compañías: el active_company se aplica en todas las consultas.

Soporte

Cuando abras un ticket, incluí el request-id y la marca de tiempo de la solicitud para acelerar el análisis.

¿Listo para automatizar tu operación?

Generá una clave API o escribinos para planificar tu integración paso a paso.

Administrar tokens Contactar soporte