Elegí la sección que necesitás para comenzar tu integración
Todo lo que necesitás para empezar a usar la API
Administrá tokens y verificá tu autenticación
Endpoints disponibles y cómo usarlos
Buenas prácticas y resolución de problemas
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.
https://app.gestion.moda/apihttp://localhost/apiv1 (todas las rutas están prefijadas con /api/v1)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.throttle:auth).| 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
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. |
| 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. |
Requiere el scope prices:read. Usa paginación estándar y cabeceras adicionales con totales.
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.
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"
}
]
}
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
}
Disponible con la habilidad products:read.
GET /api/v1/productos/obtener
Filtros disponibles:
per_page, q, codecategory_id, provider_idactive (1 o 0)include_stock y include_variants para anexar stock total y variantes por tienda.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 }
]
}
]
}
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).
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 minoristawholesaler_price: precio mayoristacurl -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
}
}
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 minoristawholesaler_price: precio mayoristaunit_cost: costo unitariocurl -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.
Disponible con la habilidad inventory:read. Permite consultar el stock disponible (available_quantity) de los productos.
GET /api/v1/inventario/obtener
Filtros disponibles:
product_id: filtrar por producto específicosize_id: filtrar por tallastore_id: filtrar por tienda/depósitocode: filtrar por código de productoq: búsqueda por nombre o códigoinclude_physical: incluir stock físico y en producciónper_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 */ }
}
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 }
]
}
]
}
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.
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.
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_pagesearch, dateFrom, dateTofrom, to para compatibilidad legacyclient_id, channel_id, store_id, sale_state_idinclude_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 }
}
]
}
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_iditems[] con product_id, size_id, quantity, unit_price y opcional discountdate_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/ventas/obtener y /ventas/ver/{id} siguen soportadas en v1.
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:
product_id, size_id, quantitystore_id, date_production, planning, add_to_inventory (default true), create_service_expenses, all_services_paid, descriptioncantidad_producida × cantidad_por_unidad (según lo configurado en el producto).
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:
cost_type_id, amountsub_cost_type_id, cost_category_id, provider_id, channel_id, bill_date, cost_year, cost_month, vat_rate, amount_plan, descriptionpayments[] con amount, date_payment, account_id, descriptionPOST /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:
items[] con supply_id, quantity, unit_cost y opcional vat_rateprovider_id, buy_date, description, expense (bool)payments[] con amount, date_payment, account_id, descriptionpayments[] no puede superar el total de la compra. Si coincide, la compra queda como paid=true.
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:
nameemail, phone_number, cellphone_number, address, postal_code, city, provinceclient_type_id, client_state_id, client_category_id, channel_id, price_list_idbill_identification_number_type (CUIT/CUIL/DNI), bill_identification_number, kind_responsibility_id, bill_name, bill_address, bill_city, bill_province, bill_countrybillable se calcula automáticamente según los datos fiscales informados; no se puede enviar ni modificar desde la llamada.
meta y links propios de la paginación de Laravel.active_company) para garantizar el aislamiento multiempresa.La API implementa límites de solicitudes para proteger el servicio y garantizar disponibilidad para todos los usuarios.
| Tipo | Límite | Ventana |
|---|---|---|
| API General | 60 solicitudes | 1 minuto |
| Exportaciones | 10 solicitudes | 1 minuto |
| Autenticación | 5 intentos | 1 minuto |
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
Retry-After antes de reintentar.
| 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. |
active_company se aplica en todas las consultas.Cuando abras un ticket, incluí el request-id y la marca de tiempo de la solicitud para acelerar el análisis.
Generá una clave API o escribinos para planificar tu integración paso a paso.