Clientes de BORME API para Python y TypeScript
Dos bibliotecas cliente para BORME API, un servicio independiente que ofrece, a través de una API REST, datos derivados de publicaciones del BORME y de otros registros públicos. Los dos paquetes se llaman bormeapi, se publican con licencia MIT y parten de la versión 1.0.0.
- Python:
pip install bormeapi. Solo usa la biblioteca estándar, no tiene dependencias en tiempo de ejecución y requiere Python 3.9 o posterior. bormeapi en PyPI - TypeScript y JavaScript:
npm install bormeapi. No tiene dependencias en tiempo de ejecución: usa elfetchglobal (Node 18 o posterior, Deno, Bun, navegadores). Incluye compilaciones ESM y CommonJS con declaraciones de tipos. bormeapi en npm
Inicio rápido en Python · Inicio rápido en TypeScript · Su clave de API · Qué incluyen los clientes · Paginación · Errores y reintentos · Referencia de la API
Inicio rápido en Python
pip install bormeapi
from bormeapi import BormeClient
client = BormeClient("SU_CLAVE_API") # o BormeClient() con BORME_API_KEY definida
company = client.company_by_nif("A46103834")
print(company["company_name"], company["status"])
for event in client.iter_events(province="MADRID", act_type="INCORPORATION", max_items=20):
print(event["date"], event["company_name"])
Pase su clave explícitamente o utilice client = BormeClient() después de definir BORME_API_KEY: la variable solo se lee cuando no se pasa ninguna clave.
Inicio rápido en TypeScript
npm install bormeapi
import { BormeClient } from "bormeapi";
const client = new BormeClient({ apiKey: process.env.BORME_API_KEY });
const company = await client.companyByNif("A46103834");
console.log(company.company_name, company.status);
for await (const ev of client.iterEvents({ province: "MADRID", act_type: "INCORPORATION" }, { maxItems: 20 }))
console.log(ev.date, ev.company_name);
También funciona con CommonJS: const { BormeClient } = require("bormeapi");
Su clave de API
Puede obtener una clave gratuita en su cuenta. El plan gratuito permite realizar 50 peticiones al día y acceder a los últimos 7 días de historial; algunos endpoints y filtros requieren un plan de pago (consulte los precios). La clave se envía únicamente en la cabecera X-API-Key.
No incluya su clave en código que se ejecute en el navegador de sus visitantes: cualquiera podría leerla.
Qué incluyen los clientes
Los dos clientes ofrecen las mismas operaciones. Python usa nombres de método en snake_case y TypeScript, en camelCase.
Python
- Sociedades:
company(slug, as_of=, include_inferred=),company_by_nif(nif),companies_by_nif([...])(hasta 100),companies_by_hoja(hoja),search_companies(name, province=, status=, limit=, offset=),company_events(slug, ...),company_signals(slug, ...),company_risk(slug),company_network(slug, ...),person_roles(name). - Números de identificación a efectos del IVA (NIF-IVA) de la UE:
vat_check(vat_number). - Actos:
events(**filtros)para una página,iter_events(**filtros)para recorrer las páginas automáticamente (con los límites indicados en Paginación),events_csv(**filtros)para obtener datos CSV en bytes. - Señales:
signals(signal_type=, date_from=, date_to=, province=, ...). - Marcas y nombres comerciales:
search_brands(q),company_brands(slug). - Listas de seguimiento:
create_watchlist(webhook_url=, company_slug= | name_contains= | filter=),list_watchlists(),delete_watchlist(id). - Datos de referencia:
act_types(),provinces(),sources(),health(). - Cualquier otro endpoint:
request("GET", "/v1/...", params={...}).
Con include_inferred=True, company() y company_events() pueden devolver también una división de la CNAE-2009 inferida por un modelo de lenguaje a partir del objeto social, si alcanza el umbral de confianza (0,9 por defecto) y no consta ningún código CNAE en la ficha de la sociedad (para company()) o en ninguno de los actos del evento (para company_events()) (cnae_source jev, con los detalles en cnae_inference). Describe el objeto social, no la actividad verificada de la sociedad, y no es un código publicado en el BORME. Si se omite include_inferred o se establece en False, no se incluyen valores inferidos.
Las respuestas son diccionarios con tipos TypedDict (bormeapi.models), de modo que los campos nuevos que añada la API le llegan sin actualizar el paquete.
TypeScript
- Sociedades:
company(slug, { asOf, include_inferred }),companyByNif(nif),companiesByNif([...])(hasta 100),companiesByHoja(hoja),searchCompanies(name, { province, status, limit, offset }),companyEvents(slug, ...),companySignals(slug, ...),companyRisk(slug),companyNetwork(slug, ...),personRoles(name). - Números de identificación a efectos del IVA (NIF-IVA) de la UE:
vatCheck(vatNumber). - Actos:
events(filtros)para una página,iterEvents(filtros, { pageSize, maxItems })para recorrer las páginas automáticamente (con los límites indicados en Paginación),eventsCsv(filtros)para obtener texto CSV. - Señales:
signals({ signal_type, date_from, date_to, province, ... }). - Marcas y nombres comerciales:
searchBrands(q),companyBrands(slug). - Listas de seguimiento:
createWatchlist({ webhook_url, company_slug | name_contains | filter }),listWatchlists(),deleteWatchlist(id). - Datos de referencia:
actTypes(),provinces(),sources(),health(). - Cualquier otro endpoint:
request("GET", "/v1/...", { params }).
Con { include_inferred: true }, company() y companyEvents() pueden devolver también una división de la CNAE-2009 inferida por un modelo de lenguaje a partir del objeto social, si alcanza el umbral de confianza (0,9 por defecto) y no consta ningún código CNAE en la ficha de la sociedad (para company()) o en ninguno de los actos del evento (para companyEvents()) (cnae_source jev, con los detalles en cnae_inference). Describe el objeto social, no la actividad verificada de la sociedad, y no es un código publicado en el BORME. Si se omite include_inferred o se establece en false, no se incluyen valores inferidos.
Los campos de las respuestas conservan los nombres en snake_case de la API, de modo que la referencia de la API se aplica tal cual.
En los dos clientes
- Filtros de actos:
date_from,date_to,province,act_type,company_name_contains,capital_min,capital_max,municipality. - La comprobación del NIF-IVA indica si, según VIES, el número era válido para operaciones intracomunitarias en la fecha
request_date(plan Basic o superior). - Las respuestas de sociedades incluyen también
lei(el identificador LEI de GLEIF localizado por NIF) ywebsite(la dirección tal como se publicó en el BORME); la referencia de la API explica en qué casos estos campos tienen el valornull.
Paginación
iter_events (Python) e iterEvents (TypeScript) solicitan páginas de hasta 200 actos y se detienen en la última página, al alcanzar max_items / maxItems o cuando el desplazamiento superaría 10 000 (el límite de la API). Para conjuntos mayores, divida el intervalo de fechas. Cada página es una petición y cuenta para su cuota.
Errores y reintentos
Las respuestas HTTP de error lanzan ApiError o una de sus subclases, con status, code (el código de error de la API, cuando lo hay), el mensaje (message en Python, apiMessage en TypeScript), body y headers:
AuthenticationError(401),PermissionDeniedError(403),NotFoundError(404, consuggestionssi el slug no existe),ConflictError(409, concandidatessi el NIF es ambiguo),ValidationError(422, conerrors),RateLimitError(429),ServiceUnavailableError(503),GatewayTimeoutError(504).- Los fallos de red lanzan
TransportError.
Las respuestas 429 y 503 se reintentan hasta tres veces (max_retries=3 en Python, maxRetries: 3 en TypeScript) únicamente si Retry-After es válido e indica una espera de 60 segundos como máximo (max_retry_wait=60, maxRetryWaitSeconds: 60); en caso contrario, el error se lanza de inmediato. Las respuestas 503 solo se reintentan para GET y DELETE. Una 429 sin Retry-After indica que se ha agotado la cuota diaria, que se renueva a las 00:00 UTC; por eso se lanza de inmediato, con limit y upgrade_url (upgradeUrl en TypeScript).
from bormeapi import NotFoundError
try:
client.company("mercadona-sl")
except NotFoundError as e:
print(e.message, e.suggestions)
import { NotFoundError } from "bormeapi";
try {
await client.company("mercadona-sl");
} catch (e) {
if (e instanceof NotFoundError) console.log(e.apiMessage, e.suggestions);
}
Un slug antiguo de una sociedad que ha cambiado de denominación o se ha fusionado se redirige al actual. Los clientes siguen hasta tres redirecciones, solo al mismo origen, de modo que la clave nunca se envía a otro. El cliente de TypeScript lo hace cuando el entorno permite leer Location (Node, Deno, Bun); en navegadores, una redirección opaca lanza TransportError.
Referencia de la API
Todos los campos, filtros y códigos de error se explican en la documentación de la API; la referencia interactiva, en inglés, está en api.bormeapi.com/docs. Los paquetes: bormeapi en PyPI · bormeapi en npm.
¿Preguntas sobre una integración? Escríbanos; respondemos personalmente, normalmente el mismo día hábil.