Desarrolladores
Facturas recibidas extraídas por el flujo de documentos.
GET /suppliers Listar facturas recibidasGET /suppliers/items/{id} Consultar una factura recibidaGET /suppliers/items/{id}/file Descargar el fichero de una factura recibidaPOST /ingest/batches Subir un documento de compra/suppliersListar facturas recibidas
Facturas de compra extraídas por el flujo de lectura de documentos. Los filtros de fecha se aplican a `createdAt` (fecha de entrada), no a la fecha de la factura.
Permiso exigido:
purchases:documents.read (Compras › Facturas de proveedor y gastos › Leer)
Paginación: Parámetros page y limit. La respuesta incluye total, page, limit, hasMore.
| Nombre | En | Tipo | Descripción |
|---|---|---|---|
state | query | string | Estado en el flujo de entrada de documentos, p. ej. BOOKED o NEEDS_REVIEW. |
needsReview | query | boolean | |
dateFrom | query | string (date) | |
dateTo | query | string (date) | |
page | query | integer | Por defecto: 1 |
limit | query | integer | Por defecto: 50 · máximo: 500 |
200 Lista de facturas recibidas · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
items | object[] | |
items[].id | string | |
items[].companyId | string | |
items[].filename | string | |
items[].confidence | numberpuede ser null | |
items[].state | string | |
items[].needsReview | boolean | |
items[].createdAt | string (date-time) | |
items[].updatedAt | string (date-time) | |
total | integer | Total de elementos que cumplen el filtro. |
page | integer | Página devuelta (empieza en 1). |
limit | integer | Tamaño de página aplicado. |
hasMore | boolean | Hay más páginas después de esta. |
401 Falta el token Bearer o no es válido. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
403 El token no tiene el permiso exigido o el recurso queda fuera de su alcance. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
429 Se ha alcanzado un límite de uso. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
curl -X GET "https://app.bm.consulting/api/v1/suppliers?limit=50" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/suppliers?limit=50", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/suppliers?limit=50",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /suppliers/items/{id}Consultar una factura recibida
Detalle extraído completo, con los campos de cada línea. Responde 404 si el elemento queda fuera del alcance del token.
Permiso exigido:
purchases:documents.read (Compras › Facturas de proveedor y gastos › Leer)
Paginación: Sin paginación: devuelve el conjunto completo.
| Nombre | En | Tipo | Descripción |
|---|---|---|---|
idobligatorio | ruta | string |
200 Factura recibida · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
id | string | |
companyId | string | |
filename | string | |
confidence | numberpuede ser null | |
issuerNif | stringpuede ser null | |
issuerName | stringpuede ser null | |
invoiceNumber | stringpuede ser null | |
invoiceDate | string (date) | |
dueDate | string (date)puede ser null | |
baseAmount | numberpuede ser null | |
vatAmount | numberpuede ser null | |
total | numberpuede ser null | |
currency | string | |
state | string | |
lines | object[] | |
lines[].description | stringpuede ser null | |
lines[].quantity | numberpuede ser null | |
lines[].unitPrice | numberpuede ser null | |
lines[].lineTotal | numberpuede ser null | |
lines[].vatRate | numberpuede ser null | |
lines[].taxCode | stringpuede ser null | Código de régimen del SII |
lines[].accountCode | stringpuede ser null | Código de cuenta del PGC |
fileUrl | string (uri) | Se canjea por una descarga firmada con GET /suppliers/items/{id}/file. |
401 Falta el token Bearer o no es válido. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
403 El token no tiene el permiso exigido o el recurso queda fuera de su alcance. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
404 El recurso no existe o queda fuera del alcance del token. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
429 Se ha alcanzado un límite de uso. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
curl -X GET "https://app.bm.consulting/api/v1/suppliers/items/<id>" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/suppliers/items/<id>", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/suppliers/items/<id>",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /suppliers/items/{id}/fileDescargar el fichero de una factura recibida
Redirige a una URL firmada de corta duración con el fichero original.
Permiso exigido:
purchases:documents.read (Compras › Facturas de proveedor y gastos › Leer)
Paginación: Sin paginación: devuelve el conjunto completo.
| Nombre | En | Tipo | Descripción |
|---|---|---|---|
idobligatorio | ruta | string |
302 Redirección a una URL de descarga firmada
401 Falta el token Bearer o no es válido. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
403 El token no tiene el permiso exigido o el recurso queda fuera de su alcance. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
404 El recurso no existe o queda fuera del alcance del token. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
429 Se ha alcanzado un límite de uso. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
curl -X GET "https://app.bm.consulting/api/v1/suppliers/items/<id>/file" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/suppliers/items/<id>/file", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/suppliers/items/<id>/file",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /ingest/batchesSubir un documento de compra
Subida multipart de una factura de compra (PDF o imagen). La deja en cola para OCR y extracción. Si el fichero es idéntico a uno ya subido (SHA-256), responde 200. `companyId` sale del token.
Permiso exigido:
documents:ingest.create (Documentos › Lectura automática de documentos › Crear)
Paginación: Sin paginación: devuelve el conjunto completo.
multipart/form-data| Nombre | Tipo | Descripción |
|---|---|---|
fileobligatorio | string (binary) | El contenido del documento. |
filename | string |
200 Duplicado: ya se había recibido un fichero idéntico
201 Fichero aceptado y en cola (devuelve batchId e itemId)
400 Falta el fichero, su tipo no se admite o es demasiado grande · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
401 Falta el token Bearer o no es válido. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
403 El token no tiene el permiso exigido o el recurso queda fuera de su alcance. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
429 Se ha alcanzado un límite de uso. · application/json
| Nombre | Tipo | Descripción |
|---|---|---|
error | string | Mensaje de error legible |
required_permission | string | Solo en el 403: el permiso que falta (área:recurso.acción) |
curl -X POST "https://app.bm.consulting/api/v1/ingest/batches" \
-H "Authorization: Bearer $BMC_TOKEN" \
-F "file=@documento.pdf" import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("file", new Blob([await readFile("documento.pdf")]), "documento.pdf");
const res = await fetch("https://app.bm.consulting/api/v1/ingest/batches", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
body: form,
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.post(
"https://app.bm.consulting/api/v1/ingest/batches",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
files={"file": open("documento.pdf", "rb")},
timeout=30,
)
res.raise_for_status()
data = res.json()