API de Flow
Catálogo, existencias, terceros, ventas, facturas, cuentas por pagar, pagos y webhooks.
Base: https://flow.eel.software/api/public/v1
La app de finanzas y operaciones. Todo POST que crea o registra algo exige
el encabezado Idempotency-Key, con una excepción: las dos rutas de gestión
de webhooks al final de esta página. Ver las reglas
compartidas para paginación, errores y
ritmo, una sola vez para las cuatro apps.
Catálogo y existencias
| Método | Ruta | Permiso |
|---|---|---|
GET |
/products |
flow:catalog:read |
GET |
/products/{upid} |
flow:catalog:read |
PATCH |
/products/{upid} |
flow:catalog:write |
GET |
/products/{upid}/stock |
flow:stock:read |
GET |
/warehouses |
flow:catalog:read |
GET |
/financial-accounts |
flow:sales:write |
GET /products pagina con cursor y filtra con q (nombre o SKU), active, o
updated_since (fecha ISO). Cada fila trae su UPID, el id que toma
cualquier otra ruta de producto: sku, name, active, list_price,
currency, tax y uom.
PATCH /products/{upid} edita name, list_price (string decimal, null la
borra), tax_code (null lo borra) o active. sku y uom son
deliberadamente inmutables por la API.
GET /products/{upid}/stock devuelve on_hand y disponible-para-vender por
bodega (available = on_hand menos las reservas activas), opcionalmente
filtrado a una warehouse. Es eventualmente consistente con el checkout.
GET /warehouses lista todas las bodegas activas (CENTRAL y STORE) con el
warehouse_id que toman las ventas y las lecturas de existencias; las filas
STORE traen además el partner_id del tercero que representa esa tienda.
GET /financial-accounts lista cuentas activas CASH / BANK / PROCESSOR
con su currency, solo identidad, sin saldos. Es la fuente del
financial_account_id que toma una venta o un pago.
Terceros
| Método | Ruta | Permiso |
|---|---|---|
GET |
/partners |
flow:partners:write |
GET |
/partners/{id} |
flow:partners:write |
POST |
/partners |
flow:partners:write |
No hay un permiso de lectura dedicado para terceros: leer y buscar van los dos
sobre flow:partners:write, la misma asimetría que el catálogo de
permisos señala para las notas y recordatorios
de Wrap.
GET /partners?q= busca por nombre (contiene) o prefijo de identificación
tributaria. POST /partners hace upsert de un tercero (cliente/proveedor)
por identificación tributaria (tax_id_type + tax_id_number) o email:
devuelve el registro existente cuando hay coincidencia, así que también sirve
para buscar por NIT. El dígito de verificación del NIT se valida, o se calcula
si se omite.
| Campo | Tipo | Notas |
|---|---|---|
name |
string, 1 a 200 caracteres | Obligatorio. |
tax_id_type |
NIT\ |
CC\ |
tax_id_number |
string, hasta 40 caracteres | Opcional. |
verification_digit |
string, hasta 2 caracteres | El DV del NIT. Se calcula si se omite. |
email |
string | Opcional. |
roles |
string[] | P. ej. CUSTOMER, SUPPLIER, EMPLOYEE. |
Ventas
| Método | Ruta | Permiso |
|---|---|---|
POST |
/sales |
flow:sales:write |
GET |
/sales/{id} |
flow:sales:write |
POST /sales es la venta de una sola llamada: descuenta existencias de una
bodega, factura al cliente y opcionalmente registra el pago.
| Campo | Tipo | Notas |
|---|---|---|
external_ref |
string, hasta 200 caracteres | Tu propio id de orden. También el ancla de deduplicación. |
warehouse_id |
uuid | Obligatorio. |
customer |
`{ partner_id? \ | name/tax_id/email }` |
lines |
{ upid, qty, unit_price? }[], mínimo 1 |
unit_price sobreescribe el precio de lista resuelto si se envía. |
payment |
{ method, financial_account_id?, processor_ref?, amount? } |
method es CASH o PROCESSOR. |
emit_einvoice |
boolean | |
notes |
string, hasta 2000 caracteres |
GET /sales/{id} devuelve el número y estado de la factura, la referencia de
salida, y dian_status (estado de la facturación electrónica ante la DIAN).
Facturas y cuentas por pagar
| Método | Ruta | Permiso |
|---|---|---|
GET |
/invoices |
flow:documents:read |
GET |
/bills/list |
flow:documents:read |
POST |
/bills |
flow:bills:write |
GET /invoices recorre documentos de cartera por cobrar (facturas de venta)
por fecha de emisión más reciente primero, con cursor: la vista "ingresos
este mes". GET /bills/list es la misma forma para documentos de cartera por
pagar (facturas de proveedor), más supplier_number y PENDING_APPROVAL como
estado extra. flow_list_open_items (abajo) solo muestra el subconjunto sin
pagar de cualquiera de las dos.
Ambas filtran por status, partner_id, o una ventana issued_from/
issued_to (fechas ISO), y ambas devuelven el number formateado (null
mientras está DRAFT), partner_id/nombre, dinero como string y el
remaining consciente de retenciones.
| Superficie | Estados |
|---|---|
| Facturas de venta | DRAFT, OPEN, PARTIAL, PAID, VOID |
| Cuentas por pagar | DRAFT, OPEN, PARTIAL, PAID, VOID, PENDING_APPROVAL |
POST /bills crea una factura de compra en DRAFT; una persona la contabiliza
dentro de Flow. Referencia al proveedor por partner_id o pasa un objeto
partner en línea (con upsert por identificación tributaria o email). Un par
(partner, supplier_number) duplicado se rechaza con conflict y el
bill_id existente en los detalles del error.
| Campo | Tipo | Notas |
|---|---|---|
partner_id |
uuid, opcional | |
partner |
objeto, opcional | Proveedor en línea: name, tax_id_type, tax_id_number, email. |
supplier_number |
string, 1 a 60 caracteres | El número de factura propio del proveedor. |
issue_date |
fecha ISO | Obligatorio. |
due_date |
fecha ISO, opcional | |
currency |
string, 3 caracteres, opcional | |
notes |
string, hasta 2000 caracteres, opcional | |
lines |
{ description, qty, unit_price, tax_code?, product_upid? }[], mínimo 1 |
Dinero como números, no strings. |
Pagos
| Método | Ruta | Permiso |
|---|---|---|
POST |
/invoices/{id}/payments |
flow:payments:write |
POST |
/bills/{id}/payments |
flow:payments:write |
Las dos registran un pago (un recaudo contra una factura de venta, o un
desembolso contra una cuenta por pagar), con las mismas reglas: amount es un
string decimal en la moneda propia del documento, y financial_account_id
debe coincidir con esa moneda. Se rechaza cuando el documento está
DRAFT/VOID/ya PAID, el monto excede lo que resta, o el mes fiscal está
cerrado.
| Campo | Tipo | Notas |
|---|---|---|
financial_account_id |
uuid | De GET /financial-accounts. |
amount |
string decimal | P. ej. "150000.00", en la moneda del documento. |
date |
fecha ISO | Obligatorio. |
reference |
string, hasta 120 caracteres, opcional |
Un pago contra una cuenta por pagar en o por encima del umbral de aprobación
del espacio solo pasa cuando quien llama es administrador del espacio. Las
dos rutas devuelven el pago más el remaining y status del documento tras
el pago.
Cartera (items abiertos)
| Método | Ruta | Permiso |
|---|---|---|
GET |
/open-items |
flow:open-items:read |
Documentos abiertos (sin pagar) con su saldo pendiente: side=AP para
cuentas por pagar a proveedores, side=AR para facturas de venta que nos
deben. Filtra por partner_nit o una fecha as_of. Es la ruta detrás de
"qué le debemos a X", "quién nos debe", y preguntas de cartera en general.
Webhooks
| Método | Ruta | Permiso |
|---|---|---|
GET |
/webhooks |
flow:webhooks:manage |
POST |
/webhooks |
flow:webhooks:manage |
DELETE |
/webhooks/{id} |
flow:webhooks:manage |
GET |
/webhook-deliveries |
flow:webhooks:manage |
POST |
/webhook-deliveries/{id}/redeliver |
flow:webhooks:manage |
Estas dos rutas POST son la excepción a la regla de idempotencia de arriba:
POST /webhooks y POST /webhook-deliveries/{id}/redeliver ni exigen ni
miran Idempotency-Key.
POST /webhooks toma url (hasta 2000 caracteres) y events (al menos uno
de invoice.posted, invoice.paid, bill.posted, payment.created,
stock.changed). La respuesta incluye el secreto de firma una sola vez,
al crear, nunca después. GET /webhook-deliveries?webhook= lista entregas
recientes, opcionalmente filtradas a un webhook; POST
/webhook-deliveries/{id}/redeliver reencola una para el siguiente drenaje.
La entrega es al menos una vez: quien consume un webhook debe ser idempotente por su cuenta, usando el cuerpo del evento como clave, no el número de entregas.