Las integraciones externas permiten conectar sistemas de terceros (ERPs, tiendas en línea, aplicaciones propias) con FileXpress Hub mediante una API REST autenticada con credenciales propias.
Crear una integración
Ir a Gestión → Integraciones → Nueva Integración
Ingresar el nombre descriptivo de la integración (mínimo 3 caracteres)
Seleccionar los endpoints permitidos
| Endpoint | Datos accesibles |
|---|
| Ventas | Facturas y documentos de venta |
| Gastos | Compras y gastos registrados |
| Clientes | Directorio de clientes |
| Productos | Catálogo de productos |
Configurar el rate limit (solicitudes por minuto, máximo 1,000 — por defecto 100)
Guardar
El sistema genera el API Key y API Secret. Copiarlos antes de cerrar el modal — el Secret no se vuelve a mostrar completo.
El API Secret solo se muestra una vez. Si se pierde, debe regenerarse desde el listado de integraciones (invalida el anterior).
Gestionar credenciales
Desde el listado de integraciones:
- Activar / Desactivar sin eliminar la integración.
- Regenerar API Key — nuevo key, el anterior deja de funcionar.
- Regenerar API Secret — nuevo secret, el anterior deja de funcionar.
Estadísticas y logs
- Estadísticas: volumen total, solicitudes exitosas, errores, tiempo promedio de respuesta, último uso, desglose por endpoint y errores recientes.
- Logs: historial paginado de cada llamada con estado HTTP, duración y cuerpo de respuesta.
Autenticación
Todas las solicitudes deben incluir las dos cabeceras:
x-api-key: TU_API_KEY
x-api-secret: TU_API_SECRET
URL base: https://api.filexpress.app/api/external
| Código | Causa |
|---|
401 | Credenciales inválidas, desactivadas o cabeceras ausentes |
403 | Endpoint no incluido en los permisos de la integración, o recurso de otro negocio |
404 | Recurso no encontrado |
422 | Error de validación — revisar errors en el cuerpo de la respuesta |
429 | Rate limit excedido |
500 | Error interno — reportar con el log del request |
Obtener el branch_id
El branch_id es un UUID requerido en la mayoría de endpoints. Se obtiene desde la vista de soporte del panel de administración de FileXpress (Support → Sucursales), donde se listan todos los IDs de sucursales del negocio.
Ventas
Crear venta
Este endpoint requiere que el sistema externo pre-calcule los desgloses fiscales por línea de producto y los totales globales. No los calcula automáticamente.
Cuerpo de la solicitud
{
"branch_id": "uuid",
"customer_id": "uuid",
"document_type": "fc",
"date": "2025-06-01T10:00:00",
"observation": "Entrega en bodega central",
"is_credit": false,
"credit_days": 0,
"payment_details": [
{
"code": "01",
"payment_method": "Efectivo",
"amount": 22.60,
"reference": ""
}
],
"products": [
{
"id": "uuid-del-producto",
"sku": "PRD-001",
"name": "Producto A",
"quantity": 2,
"price_before_taxes": 10.00,
"sale_not_suject": 0,
"sale_exent": 0,
"sale_taxed": 20.00,
"subtotal": 20.00,
"discount": 0,
"type": "phisical"
}
],
"totals": {
"netTotals": 20.00,
"saleTotalNotSuject": 0,
"saleTotalExent": 0,
"saleTotalTax": 20.00,
"totalTax": 2.60,
"totalRetein": 0,
"totalRent": 0,
"freight": 0,
"insurance": 0,
"saleTotalToPayment": 22.60
}
}
Campos principales
| Campo | Tipo | Requerido | Descripción |
|---|
branch_id | uuid | Sí | Sucursal que emite la venta |
customer_id | uuid | Sí | Cliente receptor |
document_type | string | Sí | fc (Factura Consumidor), ccf (Crédito Fiscal), fex (Exportación), nc (Nota Crédito), nd (Nota Débito), nr (Nota Remisión) |
date | datetime | No | Fecha/hora de emisión (ISO 8601). Por defecto: ahora |
observation | string | No | Observaciones del documento |
is_credit | boolean | No | Si la venta es al crédito (defecto false) |
credit_days | integer | No | Días de crédito (requiere is_credit: true) |
products | array | Sí | Líneas de detalle (mínimo 1) |
payment_details | array | Sí | Métodos de pago utilizados (mínimo 1) |
totals | array | Sí | Totales globales del documento |
Estructura products[]
| Campo | Tipo | Descripción |
|---|
id | uuid | ID del producto en FileXpress (opcional pero recomendado) |
sku | string | Código SKU del producto |
name | string | Nombre del producto tal como aparecerá en el documento |
quantity | number | Cantidad vendida |
price_before_taxes | number | Precio unitario sin impuestos |
sale_not_suject | number | Subtotal de ventas no sujetas de esta línea |
sale_exent | number | Subtotal de ventas exentas de esta línea |
sale_taxed | number | Subtotal de ventas gravadas de esta línea (price_before_taxes × quantity) |
subtotal | number | Total de la línea sin impuestos |
discount | number | Descuento en dólares aplicado a la línea |
type | string | phisical (bien) o service |
Estructura payment_details[]
| Campo | Tipo | Descripción |
|---|
code | string | Código del método de pago — ver GET /payment-methods |
payment_method | string | Nombre descriptivo del método (ej: “Efectivo”, “Tarjeta”) |
amount | number | Monto pagado con este método |
reference | string | Referencia de transacción (número de cheque, autorización, etc.) |
Estructura totals
| Campo | Tipo | Descripción |
|---|
netTotals | number | Suma de subtotales de todas las líneas antes de impuestos |
saleTotalNotSuject | number | Total de ventas no sujetas |
saleTotalExent | number | Total de ventas exentas |
saleTotalTax | number | Total de ventas gravadas (base imponible) |
totalTax | number | Monto total de IVA (saleTotalTax × 0.13) |
totalRetein | number | Total de retenciones (0 si no aplica) |
totalRent | number | Total de renta (0 si no aplica) |
freight | number | Flete (0 si no aplica) |
insurance | number | Seguro (0 si no aplica) |
saleTotalToPayment | number | Total a pagar (saleTotalTax + totalTax + saleTotalExent + saleTotalNotSuject) |
Respuesta exitosa 200
{
"status": true,
"data": {
"sale_id": "uuid",
"generation_code": "GC-2025-001",
"control_number": "DTE-01-0001-000000001",
"status": "processed",
"issue_time": "2025-06-01T10:30:00Z",
"stamp": "...",
"total": 22.60
}
}
Obtener venta
GET /api/external/sales/{sale_id}
Respuesta exitosa 200
{
"status": true,
"data": {
"sale_id": "uuid",
"generation_code": "GC-2025-001",
"control_number": "DTE-01-0001-000000001",
"document_type": "fc",
"status": "processed",
"issue_time": "2025-06-01T10:30:00Z",
"stamp": "...",
"payment_status": "paid",
"is_credit": false,
"customer": {
"id": "uuid",
"legal_name": "Razón Social S.A.",
"customer_name": "Nombre Comercial"
},
"totals": {
"sale_total": 22.60,
"sale_to_payment": 22.60
},
"products": [
{
"name": "Producto A",
"quantity": 2,
"individual_price": 10.00,
"subtotal": 20.00
}
]
}
}
Gastos
Crear gasto
POST /api/external/expenses
Al igual que ventas, el sistema externo debe pre-calcular los desgloses fiscales por línea y los totales globales.
Cuerpo de la solicitud
{
"branch_id": "uuid",
"provider_id": "uuid",
"document_type": "ccf",
"date": "2025-06-01",
"observation": "Compra de insumos",
"is_credit": false,
"credit_days": 0,
"number_control": "DTE-03-...",
"generation_code": null,
"stamp": null,
"products": [
{
"sku": "INS-001",
"name": "Insumo A",
"type": "goods",
"quantity": 5,
"price_before_taxes": 8.00,
"expense_not_suject": 0,
"expense_exent": 0,
"expense_taxed": 40.00,
"subtotal": 40.00
}
],
"totals": {
"netTotals": 40.00,
"charge_1": 0,
"charge_2": 0,
"expenseTotalTax": 40.00,
"totalRent": 0,
"totalTax": 5.20,
"totalRetein": 0,
"expenseTotalToPayment": 45.20
}
}
Campos principales
| Campo | Tipo | Requerido | Descripción |
|---|
branch_id | uuid | Sí | Sucursal que registra el gasto |
provider_id | uuid | Sí | Proveedor emisor del documento |
document_type | string | Sí | fse (Factura Sujeto Excluido), ccf (Crédito Fiscal), ticket |
date | date | Sí | Fecha del documento (YYYY-MM-DD) |
is_credit | boolean | Sí | Si es al crédito |
credit_days | integer | No | Días de crédito |
number_control | string | No | Número de control del documento físico |
generation_code | string | No | Código de generación del DTE |
stamp | string | No | Sello electrónico |
products | array | Sí | Líneas de detalle |
totals | array | Sí | Totales globales |
Estructura products[] para gastos
| Campo | Tipo | Descripción |
|---|
sku | string | Código del producto/servicio |
name | string | Descripción de la línea |
type | string | goods (bien) o services (servicio) |
quantity | number | Cantidad |
price_before_taxes | number | Precio unitario sin impuestos |
expense_not_suject | number | Monto no sujeto de la línea |
expense_exent | number | Monto exento de la línea |
expense_taxed | number | Monto gravado de la línea |
subtotal | number | Total de la línea |
Estructura totals para gastos
| Campo | Tipo | Descripción |
|---|
netTotals | number | Suma de subtotales antes de impuestos |
charge_1 | number | Cargo adicional 1 (0 si no aplica) |
charge_2 | number | Cargo adicional 2 (0 si no aplica) |
expenseTotalTax | number | Base imponible gravada total |
totalRent | number | Renta retenida (0 si no aplica) |
totalTax | number | Monto total de IVA |
totalRetein | number | Retenciones (0 si no aplica) |
expenseTotalToPayment | number | Total a pagar |
Respuesta exitosa 200
{
"status": true,
"data": {
"expense_id": "uuid",
"generation_code": null,
"control_number": "DTE-03-...",
"status": "processed",
"issue_time": "2025-06-01T10:00:00Z",
"total": 45.20
}
}
Obtener gasto
GET /api/external/expenses/{expense_id}
Devuelve el gasto con proveedor, líneas de detalle y totales (expense_total, expense_to_payment).
Clientes
Listar clientes de una sucursal
GET /api/external/customers/branch/{branch_id}
Devuelve todos los clientes activos de la sucursal (no paginado).
Obtener cliente
GET /api/external/customers/{id}
Crear cliente
POST /api/external/customers
Cuerpo de la solicitud
{
"customer_name": "Juan Pérez",
"legal_name": "Juan Antonio Pérez García",
"register_number": "12345-6",
"tax_number": "0614-000101-000-0",
"document_type": "DUI",
"document_number": "00000000-0",
"address": "Col. San Benito, Av. La Revolución #123",
"country_id": "uuid",
"state_id": "uuid",
"city_id": "uuid",
"phone": "7777-1234",
"email": "juan@example.com",
"business_type": "non-business",
"business_size": "",
"activity_id": "uuid",
"branch_id": "uuid",
"is_exent": false,
"is_public_institution": false
}
Campos requeridos: customer_name, address, country_id, state_id, city_id, phone, email, business_type, branch_id
| Campo | Valores válidos |
|---|
business_type | non-business (persona individual), natural (persona natural), legal (persona jurídica) |
document_type | Tipo de documento de identidad (DUI, pasaporte, carné de residente, etc.) |
is_exent | true = el sistema elimina el IVA al facturar a este cliente |
is_public_institution | true = entidad gubernamental — restringe los tipos de DTE disponibles |
Respuesta 200: objeto del cliente creado con id.
Actualizar cliente
PUT /api/external/customers/{id}
Mismos campos requeridos que la creación. Acepta además: legal_name, register_number, tax_number, document_type, document_number, activity_id, business_size.
Eliminar cliente
DELETE /api/external/customers/{id}
Borrado lógico (trashed = true). Responde 200 con confirmación.
Productos
Listar productos de una sucursal
GET /api/external/products/branch/{branch_id}
Obtener producto
GET /api/external/products/{id}
Incluye portions y components si el producto tiene composición avanzada.
Crear producto
POST /api/external/products
Cuerpo de la solicitud
{
"name": "Refresco 350ml",
"sku": "BEB-001",
"price_before_taxes": 1.11,
"cost": 0.70,
"tax_method": "is_taxed",
"composition_type": "simple",
"product_type": "phisical",
"product_category_id": "uuid",
"product_measurement_id": "uuid",
"branch_id": "uuid",
"availability": 100,
"limit_availability": 10
}
Campos requeridos: name, price_before_taxes, product_category_id, product_measurement_id, product_type, tax_method, composition_type, branch_id, availability, limit_availability
| Campo | Valores válidos |
|---|
tax_method | is_taxed (gravado), is_exent (exento), is_not_subject (no sujeto) |
composition_type | simple, with_portions, with_recipe |
product_type | phisical (bien), service (servicio), both |
Con porciones (composition_type: with_portions) — campos adicionales:
{
"base_unit_quantity": 1000,
"base_unit": "ml",
"portions": [
{
"portion_name": "Vaso 250ml",
"portion_quantity": 250,
"portion_unit": "ml",
"portion_price": 0.44,
"is_active": true
}
]
}
Con receta (composition_type: with_recipe) — campos adicionales:
{
"components": [
{
"component_product_id": "uuid-ingrediente",
"quantity_needed": 2,
"unit_type": "base"
}
]
}
Al crear un producto físico con availability > 0, se registra automáticamente un movimiento de inventario de entrada.
Actualizar producto
PUT /api/external/products/{id}
Acepta los mismos campos. Si cambia availability, se genera un movimiento de ajuste automático. Al cambiar composition_type, las porciones o componentes anteriores se eliminan y reemplazan.
Eliminar producto
DELETE /api/external/products/{id}
Borrado lógico. Responde 200 con confirmación.
Proveedores
Listar proveedores de una sucursal
GET /api/external/providers/branch/{branch_id}
Crear proveedor
POST /api/external/providers
El cuerpo debe enviarse dentro de una clave data:
{
"data": {
"provider_name": "Distribuidora XYZ",
"legal_name": "Distribuidora XYZ S.A. de C.V.",
"register_number": "54321-0",
"tax_number": "0614-000000-000-0",
"address": "San Salvador",
"country_id": "uuid",
"state_id": "uuid",
"city_id": "uuid",
"phone": "2222-3333",
"email": "ventas@xyz.com",
"business_type": "legal",
"branch_id": "uuid"
}
}
Campos requeridos (dentro de data): provider_name, address, country_id, state_id, city_id, phone, email, business_type, branch_id
Actualizar proveedor
PUT /api/external/providers/{id}
Mismos campos que la creación (sin wrapper data en update).
Eliminar proveedor
DELETE /api/external/providers/{id}
Catálogos (solo lectura)
| Recurso | Endpoint |
|---|
| Países | GET /countries, GET /countries/{id} |
| Departamentos | GET /states, GET /states/{id}, GET /states/country/{country_id} |
| Municipios | GET /cities, GET /cities/{id}, GET /cities/state/{state_id} |
| Categorías de producto | GET /product-categories, GET /product-categories/{id} |
| Unidades de medida | GET /product-measurements, GET /product-measurements/{id} |
| Actividades económicas | GET /activities, GET /activities/{id} |
| Métodos de pago | GET /payment-methods |
| Incoterms | GET /incoterms |