Ir al contenido principal

Consulta analítica

Consulta analítica

La consulta analítica agrega los datos de la empresa en una sola llamada: eliges una fuente, las medidas que quieres sumar, las dimensiones por las que agrupar, un periodo y unos filtros, y la API devuelve una tabla ya calculada. Es la forma de responder preguntas como «¿quiénes son mis cinco mejores clientes del año?», «¿cuánto suman las facturas vencidas?» o «¿qué provincias facturan más que el año pasado?» sin recorrer los listados página a página.

Las cifras son las mismas que muestran los listados y los informes de la aplicación: cada medida se define una sola vez y con el mismo criterio que la pantalla equivalente. Los importes de las facturas son los del documento (base, impuestos, total y pendiente); los del diario, los de los apuntes.

Es de solo lectura. Las consultas se calculan en el momento, sobre los datos actuales, y cada una tiene un tope de 30 segundos.

Para los informes oficiales (resumen de resultados, pérdidas y ganancias, balance, sumas y saldos) usa los informes: aplican las reglas de presentación de cada modelo. La consulta analítica sirve para rankings, totales y comparativas a medida.

Fuentes

Cada fuente se llama como el recurso de la API cuyo listado devolvería esos documentos. No hay fuentes genéricas como «ventas» o «compras»: la contabilidad es solo journal.

Fuente

Qué contiene

Scope

Medida por defecto

invoices

Facturas de venta definitivas y no borradas, con los importes del documento. Un apunte manual de ventas no está aquí: está en journal.

invoices:read

totalBeforeTaxes

bills

Facturas de compra y tickets definitivos y no borrados, con los importes del documento. Las nóminas y las amortizaciones no están aquí: están en journal.

bills:read

totalBeforeTaxes

contacts

Contactos no borrados que la credencial puede ver: clientes, proveedores y empleados según sus permisos.

contacts:read

count

journal

Apuntes del diario de todos los documentos y asientos, sin los asientos de mantenimiento (apertura, regularización y cierre). Es la única fuente contable.

accounting:read

net

Los borradores no entran salvo que lo pidas con el filtro draft. Los documentos borrados no entran nunca.

Petición

POST /{companyId}/query con un cuerpo JSON:

Campo

Tipo

Significado

from

string

Fuente: invoices, bills, contacts o journal. Obligatorio.

measures

string[]

Hasta 10 medidas de la fuente. En las medidas de días, la agregación va como sufijo: daysToPayment.median. Sin indicar, la medida por defecto de la fuente.

dimensions

string[]

Hasta 2 dimensiones por las que agrupar, en orden. Sin indicar, una sola fila con los totales.

period

object

start y end (YYYY-MM-DD), las dos fechas incluidas. Por defecto, el año natural en curso. Como máximo, 5 años. En contacts es opcional y sin tope: sin period entran todos los contactos.

compare

string

previousPeriod (el periodo anterior de la misma duración) o previousYear (el mismo periodo del año anterior). Añade a cada medida las columnas de referencia, diferencia y variación.

breakdown

string

month, quarter o year: divide el periodo en tramos naturales y añade la dimensión period. Como máximo, 24 tramos. No se combina con compare.

filters

object[]

Hasta 10 filtros { field, op, value } o { field, op, values }. Ver Filtros.

orderBy

object[]

Hasta 4 criterios { field, direction } sobre las medidas y dimensiones de la consulta. direction es asc o desc (por defecto). Sin indicar, la primera medida de mayor a menor.

limit

integer

Filas como máximo, entre 1 y 500. Por defecto, 10.

includeOther

boolean

Añade other con la suma de los grupos que quedan fuera de limit. No se aplica con breakdown.

El periodo acota por la fecha del documento en invoices y bills y por la fecha del apunte en journal. En contacts acota por la fecha de alta del contacto y es opcional: sin period, la consulta cuenta todos los contactos («¿cuántos clientes tengo por provincia?»); con period, los dados de alta en esas fechas, sin el tope de 5 años. compare y breakdown necesitan period también en contacts.

Medidas

Facturas de venta y de compra

Medida

Tipo

Significado

count

número

Documentos del conjunto filtrado.

contacts

número

Contactos distintos de los documentos del grupo. Con la dimensión fiscalId, más de uno indica contactos duplicados con el mismo identificador fiscal.

totalBeforeTaxes

importe

Suma de la base imponible de cada documento, en su moneda. Es la cifra que el listado muestra como base.

taxes

importe

Suma de la diferencia entre el total y la base imponible: IVA, recargos y retenciones con su signo.

total

importe

Suma del total de cada documento, impuestos incluidos.

pending

importe

Importe pendiente de cobro (o de pago, en bills): el total menos lo cobrado. Negativo si se ha cobrado de más.

average

importe

Base imponible media por documento: totalBeforeTaxes entre count.

daysToPayment

días

Días entre la fecha del documento y la fecha del último cobro (o pago) que lo salda. Solo cuentan los documentos cobrados.

daysOverdue

días

Días entre el vencimiento y el cobro, o hasta hoy si sigue pendiente; nunca negativos. Solo cuentan los documentos con vencimiento.

Las medidas de días admiten la agregación como sufijo: .avg (por defecto), .median, .p90, .min, .max o .count (cuántos documentos entran en el cálculo). Puedes pedir varias a la vez: daysToPayment y daysToPayment.median.

Contactos

Medida

Tipo

Significado

count

número

Contactos del conjunto filtrado.

Diario

Todos los importes van en la moneda de la empresa.

Medida

Tipo

Significado

count

número

Apuntes del conjunto filtrado.

debit

importe

Suma del debe.

credit

importe

Suma del haber.

balance

importe

Debe menos haber: saldo deudor en positivo.

net

importe

Importe con el signo natural de cada cuenta: haber menos debe en el grupo 7 (ingresos en positivo) y debe menos haber en el resto (gastos en positivo). Es la medida de un ranking de ventas o de gastos.

income

importe

Haber menos debe de los apuntes del grupo 7, como el resumen de resultados.

expenses

importe

Debe menos haber de los apuntes del grupo 6, como el resumen de resultados.

result

importe

income menos expenses.

Dimensiones

Facturas de venta y de compra

Dimensión

Valor

Significado

contact

entidad

Cliente o proveedor del documento.

contact.region

entidad

Provincia de la dirección actual del contacto (la del contacto hoy, no la del documento). id es el código de provincia y name su nombre, para España.

fiscalId

entidad

Identificador fiscal de la contraparte: NIF, CIF o NIE en España, NIF-IVA intracomunitario (VAT number) en la UE o el identificador fiscal de su país. id es el identificador normalizado (ver Identificador fiscal) y name el nombre de la contraparte en el documento más reciente del grupo.

country

código

País del documento (ISO 3166-1 alpha-2).

series

código

Serie de numeración.

currency

código

Moneda del documento.

state

valor

Estado del documento: pending, overdue, paid, overpaid o voided.

paymentMethod

entidad

Método de cobro o de pago del documento.

agingBucket

tramo

Antigüedad del pendiente: notDue (sin vencer), 1-30, 31-60, 61-90 y over90 días de retraso; settled para los cobrados o pagados.

month, quarter, year

periodo

Mes, trimestre o año natural de la fecha del documento (2026-03, 2026-Q1, 2026).

account

código

Solo en bills: cuenta contable de gasto de la cabecera del documento.

Contactos

Dimensión

Valor

Significado

address.region

entidad

Provincia de la dirección del contacto, con id (código) y name (nombre, para España).

address.country

código

País de la dirección del contacto.

fiscalId

entidad

Identificador fiscal del contacto, normalizado como en las facturas. Con count, un grupo de más de uno son contactos duplicados. name es el nombre del contacto dado de alta más recientemente.

isClient, isProvider, isEmployee

booleano

El contacto tiene esa faceta.

createdMonth

periodo

Mes natural de alta del contacto (2026-03).

Diario

Dimensión

Valor

Significado

account

entidad

Cuenta contable completa, con id (700000) y name (su título en el plan contable).

account.group, account.subgroup, account.code

código

La primera cifra de la cuenta (7), las dos primeras (70) o las tres primeras (700).

thirdParty

entidad

A quién se imputa el apunte: el contacto en las cuentas de clientes y proveedores, el banco en las de tesorería, el producto en las de ventas y compras cuando la línea lleva producto. Incluye type (contact, bank o product).

contact

entidad

Contacto del documento que generó el asiento (la factura, la compra, la nómina, el cobro o la cabecera de un asiento manual). Si el documento no tiene contacto y el asiento tiene una sola contrapartida de cliente, proveedor o acreedor (cuentas 43, 40 o 41), ese contacto. Si no, unassigned.

category

valor

Origen del importe, el del resumen de resultados: invoices, currencyGains, otherIncome, bills, payrolls, depreciation, currencyLosses, otherExpenses. Solo los apuntes de los grupos 6 y 7 tienen categoría.

documentType

valor

Tipo del documento que generó el asiento: invoice, bill, payroll, transaction (cobros, pagos y asientos manuales) u other.

month, quarter, year

periodo

Mes, trimestre o año natural de la fecha del apunte.

La dimensión contact del diario es la que responde «ventas de las cuentas 7 por cliente» incluyendo los asientos manuales, algo que invoices no ve. Un apunte de ventas sin contacto queda en unassigned.

Identificador fiscal

fiscalId agrupa por el identificador fiscal y no por el contacto: dos contactos duplicados con el mismo NIF suman en una sola fila. En las facturas es el identificador que el documento copió de su contacto al emitirse; los documentos más antiguos, que no lo guardan, toman el del contacto hoy, como el listado.

Para agrupar, el identificador se normaliza según su país:

País del identificador

Clave

Ejemplo

España

En mayúsculas, sin espacios ni signos, sin el prefijo ES y con el DNI completado con ceros a la izquierda.

ESB-12345674 y b12345674 son B12345674; 1234567L es 01234567L.

Resto de la UE

En mayúsculas, sin espacios ni signos y en la forma del NIF-IVA intracomunitario: con el prefijo de su país, lo lleve o no (EL en Grecia).

12 345 678 901 de Francia es FR12345678901.

Resto del mundo

En mayúsculas y sin espacios ni signos.

12-3456789 es 123456789.

El país es el del identificador del contacto o, si no lo tiene, el de su dirección. Los documentos sin identificador forman el grupo null, que en un negocio con muchos tickets puede ser el más grande.

El filtro fiscalId busca la clave tal como la da la dimensión. Admite separadores y minúsculas, y un NIF español con el prefijo ES o un DNI sin sus ceros. Un identificador de otro país de la UE tiene que llevar su prefijo (FR12345678901): sin él, las mismas cifras podrían ser de otro país.

Filtros

Cada filtro tiene un campo, un operador y un valor (value) o una lista de valores (values):

Operador

Valor

Uso

eq

value

Igual a.

in

values

Cualquiera de la lista, hasta 100 valores.

gte, lte

value

Mayor o igual, menor o igual. Importes y fechas.

between

values

Dos valores, los dos incluidos. Importes y fechas.

startsWith

value

Empieza por. Cuentas contables: 7, 629.

Fuente

Filtro

Operadores

Significado

invoices, bills

contact

eq, in

Identificador del contacto (con_…).

contact.region

eq, in

Código de provincia de la dirección del contacto.

fiscalId

eq, in

Identificador fiscal de la contraparte, sea cual sea el contacto. Ver Identificador fiscal.

country

eq, in

Código ISO del país del documento.

series

eq, in

Serie de numeración.

currency

eq, in

Moneda del documento.

state

eq, in

pending, overdue, paid, overpaid o voided.

paymentMethod

eq, in

Identificador del método de pago.

total, totalBeforeTaxes

gte, lte, between

Importes del documento.

dueDate

gte, lte, between

Fecha de vencimiento (YYYY-MM-DD).

tag

eq, in

Etiquetas que el documento debe tener, todas ellas.

draft

eq

true incluye los borradores junto a los definitivos.

bills

account

eq, in, startsWith

Cuenta contable de gasto del documento.

contacts

address.region, address.country

eq, in

Provincia y país de la dirección.

fiscalId

eq, in

Identificador fiscal del contacto.

isClient, isProvider, isEmployee

eq

Faceta del contacto.

tag

eq, in

Etiquetas que el contacto debe tener, todas ellas.

journal

account

eq, in, startsWith

Cuenta contable o prefijo.

thirdParty

eq, in

Identificador del contacto, banco o producto al que se imputa el apunte.

contact

eq, in

Identificador del contacto del documento que generó el asiento.

category

eq, in

Categoría del resumen de resultados.

documentType

eq, in

Tipo del documento que generó el asiento.

Respuesta

Campo

Tipo

Significado

meta.source, meta.basis

string

La fuente y su base: documents (cifras de los documentos) o accounting (cifras del diario).

meta.period

object

El periodo consultado, start y end. Ausente en contacts sin period.

meta.compare

object

Con compare: kind, start y end del periodo de referencia.

meta.breakdown

string

Con breakdown: la unidad de los tramos.

meta.currency

string

Moneda de los importes cuando currency no es una dimensión de la respuesta.

meta.limit, meta.generatedAt

El límite aplicado y el momento del cálculo.

columns

object[]

Qué es cada clave de las filas, en orden: id, kind (dimension o measure), title, description, type y, en las medidas, measure y period.

rows

object[]

Los grupos, ordenados y limitados. Una clave por columna.

totals

object

El valor de cada medida sobre el conjunto filtrado completo, no solo sobre las filas devueltas.

other

object

Con includeOther, si hay más grupos que limit: groups (cuántos quedan fuera) y la suma de cada medida que se puede sumar; null en las que no (average, las de días).

truncated

boolean

Había más grupos que limit.

En cada fila, el valor de una dimensión depende de su tipo:

  • Entidad (contact, fiscalId, paymentMethod, thirdParty, account, las provincias): { "id", "name" }, más type en thirdParty y webUrl cuando el elemento tiene ficha en la aplicación (ver Abrir un resultado en FacturaDirecta). name es null si el elemento ya no existe.

  • Periodo (month, quarter, year, createdMonth y la dimensión period del desglose): { "id", "start", "end" }.

  • El resto: un texto, un número o un booleano. Una dimensión sin valor (un documento sin país, por ejemplo) vale null y forma su propio grupo.

Las medidas valen un número, o null cuando no hay dato (la media de días de un cliente sin cobros). Los importes van redondeados a céntimos y los días a una décima.

Con compare, cada medida añade tres columnas: <medida>_reference (el valor en el periodo de referencia), <medida>_difference (periodo menos referencia) y <medida>_variance (la variación como fracción, 0.2 es un 20 %, o null si la referencia es cero). Con breakdown, la columna period identifica el tramo de cada fila.

En empresas con multimoneda, currency es una dimensión implícita de invoices y bills: aparece en las filas aunque no la pidas y los importes de monedas distintas nunca se mezclan. Los importes de journal van siempre en la moneda de la empresa.

Operaciones

Consultar

POST /{companyId}/query

Necesita el scope de la fuente: invoices:read, bills:read, contacts:read o accounting:read. Una API key con varios de ellos puede consultar varias fuentes, una por llamada. No admite la cabecera Idempotency-Key: repetir la consulta no tiene efectos.

Ejemplo: los cinco mejores clientes del año

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "invoices",    "measures": ["totalBeforeTaxes", "count"],    "dimensions": ["contact"],    "limit": 5,    "includeOther": true  }'

{  "meta": {    "source": "invoices",    "basis": "documents",    "period": { "start": "2026-01-01", "end": "2026-12-31" },    "currency": "EUR",    "limit": 5,    "generatedAt": "2026-10-18T10:00:00.000Z"  },  "columns": [    { "id": "contact", "kind": "dimension", "title": "Contacto", "description": "Cliente o proveedor del documento (`id`, `name`).", "type": "entity" },    { "id": "totalBeforeTaxes", "kind": "measure", "title": "Base imponible", "description": "Suma de la base imponible de cada factura, en la moneda del documento. Es la cifra que el listado muestra como «base».", "type": "money", "measure": "totalBeforeTaxes", "period": { "start": "2026-01-01", "end": "2026-12-31" } },    { "id": "count", "kind": "measure", "title": "Documentos", "description": "Número de facturas del conjunto filtrado.", "type": "count", "measure": "count", "period": { "start": "2026-01-01", "end": "2026-12-31" } }  ],  "rows": [    { "contact": { "id": "<id-contacto>", "name": "Cliente Uno", "webUrl": "https://app.facturadirecta.com/company/<id-empresa>/contacts/<id-contacto>" }, "totalBeforeTaxes": 18400, "count": 14 },    { "contact": { "id": "<id-contacto-2>", "name": "Cliente Dos", "webUrl": "https://app.facturadirecta.com/company/<id-empresa>/contacts/<id-contacto-2>" }, "totalBeforeTaxes": 12750, "count": 9 }  ],  "totals": { "totalBeforeTaxes": 48200, "count": 61 },  "other": { "groups": 23, "totalBeforeTaxes": 17050, "count": 38 },  "truncated": true}

La respuesta real tiene cinco filas; aquí se muestran dos. totals suma las 61 facturas del año y other las 38 de los 23 clientes que quedan fuera de las cinco primeras filas.

Ejemplo: los mejores clientes por identificador fiscal

Si el mismo cliente está dado de alta dos veces, contact lo reparte en dos filas. fiscalId lo reúne, y contacts dice cuántos contactos hay detrás de cada fila.

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "invoices",    "measures": ["totalBeforeTaxes", "contacts"],    "dimensions": ["fiscalId"],    "limit": 5  }'

{  "rows": [    { "fiscalId": { "id": "B12345674", "name": "Cliente Uno SL" }, "totalBeforeTaxes": 21300, "contacts": 2 },    { "fiscalId": { "id": "FR12345678901", "name": "Client Deux SARL" }, "totalBeforeTaxes": 9800, "contacts": 1 }  ],  "totals": { "totalBeforeTaxes": 48200, "contacts": 37 }}

La primera fila reúne dos contactos con el NIF B12345674. Para ver cuáles son, repite la consulta con "dimensions": ["fiscalId", "contact"] y el filtro { "field": "fiscalId", "op": "eq", "value": "B12345674" }. Para buscar todos los contactos duplicados sin mirar facturas, consulta contacts con la medida count y la dimensión fiscalId: los grupos de más de uno salen primero.

Ejemplo: facturas vencidas y cuánto suman

Sin dimensiones, la respuesta es una sola fila con los totales del conjunto filtrado.

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "invoices",    "measures": ["count", "total", "pending"],    "period": { "start": "2022-01-01", "end": "2026-12-31" },    "filters": [{ "field": "state", "op": "in", "values": ["overdue"] }]  }'

{  "meta": { "source": "invoices", "basis": "documents", "period": { "start": "2022-01-01", "end": "2026-12-31" }, "currency": "EUR", "limit": 10, "generatedAt": "2026-10-18T10:00:00.000Z" },  "columns": [    { "id": "count", "kind": "measure", "title": "Documentos", "description": "Número de facturas del conjunto filtrado.", "type": "count", "measure": "count", "period": { "start": "2022-01-01", "end": "2026-12-31" } },    { "id": "total", "kind": "measure", "title": "Total", "description": "Suma del total de cada factura, impuestos incluidos, en la moneda del documento.", "type": "money", "measure": "total", "period": { "start": "2022-01-01", "end": "2026-12-31" } },    { "id": "pending", "kind": "measure", "title": "Pendiente", "description": "Importe pendiente de cobro, en la moneda del documento: el total menos lo cobrado; negativo si se ha cobrado de más.", "type": "money", "measure": "pending", "period": { "start": "2022-01-01", "end": "2026-12-31" } }  ],  "rows": [    { "count": 3, "total": 1815, "pending": 1815 }  ],  "totals": { "count": 3, "total": 1815, "pending": 1815 },  "truncated": false}

Para la lista de esas facturas, con sus datos, usa el listado con state=overdue; con totals=true el listado devuelve también estas sumas.

Ejemplo: provincias con más facturación, frente al año anterior

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "invoices",    "measures": ["totalBeforeTaxes"],    "dimensions": ["contact.region"],    "period": { "start": "2026-01-01", "end": "2026-06-30" },    "compare": "previousYear",    "limit": 5  }'

{  "meta": { "source": "invoices", "basis": "documents", "period": { "start": "2026-01-01", "end": "2026-06-30" }, "compare": { "kind": "previousYear", "start": "2025-01-01", "end": "2025-06-30" }, "currency": "EUR", "limit": 5, "generatedAt": "2026-10-18T10:00:00.000Z" },  "columns": [    { "id": "contact.region", "kind": "dimension", "title": "Provincia del contacto", "description": "Provincia de la dirección actual del contacto (la del contacto hoy, no la del documento): `id` es el código y `name` el nombre para España.", "type": "entity" },    { "id": "totalBeforeTaxes", "kind": "measure", "title": "Base imponible", "description": "…", "type": "money", "measure": "totalBeforeTaxes", "period": { "start": "2026-01-01", "end": "2026-06-30" } },    { "id": "totalBeforeTaxes_reference", "kind": "measure", "title": "Base imponible (referencia)", "description": "La medida en el periodo de referencia (el mismo periodo del año anterior).", "type": "money", "measure": "totalBeforeTaxes", "period": { "start": "2025-01-01", "end": "2025-06-30" } },    { "id": "totalBeforeTaxes_difference", "kind": "measure", "title": "Base imponible (diferencia)", "description": "Periodo menos referencia.", "type": "money", "measure": "totalBeforeTaxes" },    { "id": "totalBeforeTaxes_variance", "kind": "measure", "title": "Base imponible (variación)", "description": "Variación sobre la referencia, como fracción (`0.2` es un 20 %); `null` si la referencia es cero.", "type": "ratio", "measure": "totalBeforeTaxes" }  ],  "rows": [    { "contact.region": { "id": "08", "name": "Barcelona" }, "totalBeforeTaxes": 31200, "totalBeforeTaxes_reference": 27400, "totalBeforeTaxes_difference": 3800, "totalBeforeTaxes_variance": 0.1387 },    { "contact.region": { "id": "28", "name": "Madrid" }, "totalBeforeTaxes": 12900, "totalBeforeTaxes_reference": 14100, "totalBeforeTaxes_difference": -1200, "totalBeforeTaxes_variance": -0.0851 }  ],  "totals": { "totalBeforeTaxes": 52300, "totalBeforeTaxes_reference": 48900, "totalBeforeTaxes_difference": 3400, "totalBeforeTaxes_variance": 0.0695 },  "truncated": false}

Ejemplo: ventas de las cuentas 7 por cliente, asientos manuales incluidos

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "journal",    "measures": ["net"],    "dimensions": ["contact"],    "filters": [{ "field": "account", "op": "startsWith", "value": "7" }],    "limit": 5  }'

{  "meta": { "source": "journal", "basis": "accounting", "period": { "start": "2026-01-01", "end": "2026-12-31" }, "currency": "EUR", "limit": 5, "generatedAt": "2026-10-18T10:00:00.000Z" },  "columns": [    { "id": "contact", "kind": "dimension", "title": "Contacto del asiento", "description": "…", "type": "entity" },    { "id": "net", "kind": "measure", "title": "Importe neto", "description": "…", "type": "money", "measure": "net", "period": { "start": "2026-01-01", "end": "2026-12-31" } }  ],  "rows": [    { "contact": { "id": "<id-contacto>", "name": "Cliente Uno", "webUrl": "https://app.facturadirecta.com/company/<id-empresa>/contacts/<id-contacto>" }, "net": 18400 },    { "contact": { "id": "unassigned", "name": null }, "net": 300 }  ],  "totals": { "net": 48500 },  "truncated": false}

Ejemplo: resultado del año mes a mes

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "journal",    "measures": ["income", "expenses", "result"],    "breakdown": "month",    "limit": 12  }'

Cada fila lleva la dimensión period con el tramo:

{  "meta": { "source": "journal", "basis": "accounting", "period": { "start": "2026-01-01", "end": "2026-12-31" }, "breakdown": "month", "currency": "EUR", "limit": 12, "generatedAt": "2026-10-18T10:00:00.000Z" },  "columns": [    { "id": "period", "kind": "dimension", "title": "Periodo", "description": "Tramo del desglose por meses: `id`, `start` y `end`.", "type": "period" },    { "id": "income", "kind": "measure", "title": "Ingresos", "description": "…", "type": "money", "measure": "income", "period": { "start": "2026-01-01", "end": "2026-12-31" } },    { "id": "expenses", "kind": "measure", "title": "Gastos", "description": "…", "type": "money", "measure": "expenses", "period": { "start": "2026-01-01", "end": "2026-12-31" } },    { "id": "result", "kind": "measure", "title": "Resultado", "description": "…", "type": "money", "measure": "result", "period": { "start": "2026-01-01", "end": "2026-12-31" } }  ],  "rows": [    { "period": { "id": "2026-01", "start": "2026-01-01", "end": "2026-01-31" }, "income": 8200, "expenses": 5100, "result": 3100 },    { "period": { "id": "2026-02", "start": "2026-02-01", "end": "2026-02-28" }, "income": 7600, "expenses": 5400, "result": 2200 }  ],  "totals": { "income": 91500, "expenses": 60300, "result": 31200 },  "truncated": false}

Las filas del desglose van por tramo y, dentro de cada tramo, por el orden pedido. Un tramo sin apuntes no aparece.

Ejemplo: días medios de cobro por cliente

curl "https://app.facturadirecta.com/api/$COMPANY_ID/query" \  -H "Authorization: Bearer $ACCESS_TOKEN" \  -H "Content-Type: application/json" \  -d '{    "from": "invoices",    "measures": ["daysToPayment", "daysToPayment.median", "count"],    "dimensions": ["contact"],    "orderBy": [{ "field": "daysToPayment", "direction": "desc" }],    "limit": 10  }'

{  "rows": [    { "contact": { "id": "<id-contacto>", "name": "Cliente Uno", "webUrl": "…" }, "daysToPayment": 41.5, "daysToPayment.median": 38, "count": 14 },    { "contact": { "id": "<id-contacto-2>", "name": "Cliente Dos", "webUrl": "…" }, "daysToPayment": null, "daysToPayment.median": null, "count": 2 }  ],  "totals": { "daysToPayment": 27.3, "daysToPayment.median": 24, "count": 61 }}

El segundo cliente tiene dos facturas sin cobrar: cuenta en count, pero no en los días, que valen null.

Qué cifras salen

  • Una consulta sin dimensiones sobre invoices da el mismo recuento y las mismas sumas que el listado de facturas con los mismos filtros y totals=true. Lo mismo entre bills y el listado de facturas de compra.

  • journal con la dimensión category da las mismas cifras que el resumen de resultados: los apuntes de los grupos 6 y 7 del periodo, sin el asiento de regularización.

  • La provincia (contact.region) es la de la dirección actual del contacto. Un cliente que cambió de provincia cuenta en la nueva para todas sus facturas.

  • state y agingBucket se calculan a la fecha de hoy en la zona horaria de la empresa, como el listado.

  • Las medidas que no se suman (average, contacts y las de días) se calculan en totals sobre todos los documentos, no como media o suma de las filas.

Permisos

Cada fuente necesita su scope: invoices:read, bills:read, contacts:read o accounting:read. En contacts, la credencial solo ve las facetas (clientes, proveedores, empleados) que su permiso le da.

Errores comunes

  • 400 Bad Request: una fuente, medida, dimensión o filtro fuera del vocabulario. El mensaje propone el nombre más parecido: «La medida 'totalbefore' no existe en 'invoices': ¿quieres decir 'totalBeforeTaxes'?». Algunos sinónimos también tienen sugerencia: taxId, nif o vat proponen fiscalId. También compare y breakdown a la vez, más de 2 dimensiones, 10 medidas o 10 filtros, un periodo de más de 5 años o de más de 24 tramos, una fecha que no existe, un operador que el filtro no admite o limit fuera de 1 a 500.

  • 403 Forbidden (token_scope_missing): la credencial no tiene el scope de la fuente.

  • 422 Unprocessable Entity (report_query_timeout): la consulta ha tardado más de 30 segundos. Acota el periodo, las dimensiones o los filtros.

Endpoints

Método

Path

operationId

Scopes

Descripción

POST

/{companyId}/query

analyticsQuery

accounting:read, bills:read, contacts:read, invoices:read

Consulta analítica

Scopes

  • accounting:read — Lectura de datos de contabilidad (diario).

  • bills:read — Lectura de facturas de compra y tickets.

  • contacts:read — Lectura de contactos.

  • invoices:read — Lectura de facturas.

¿Ha quedado contestada tu pregunta?