Cómo consultar el BORME con Node.js

Tutorial paso a paso para acceder al Boletín Oficial del Registro Mercantil desde Node.js. Busca empresas, consulta actos y recibe alertas de cambios con webhooks.

El BORME (Boletín Oficial del Registro Mercantil) publica a diario todos los actos societarios de las empresas españolas: constituciones, nombramientos de administradores, disoluciones, ampliaciones de capital y concursos de acreedores.

Acceder a estos datos directamente desde la web del BORME implica parsear PDFs y XMLs con formato inconsistente. En este tutorial te mostramos cómo hacerlo desde Node.js en minutos, usando la API de Apispain.

Requisitos previos

  • Node.js 18 o superior
  • Una API key gratuita de apispain.es

Instalación del SDK

La forma más rápida es usar el SDK oficial:

npm install apispain

O con fetch nativo si prefieres sin dependencias (Node.js 18+ lo incluye de serie).

Configuración básica

import Apispain from 'apispain'

const client = new Apispain({
  apiKey: process.env.APISPAIN_API_KEY, // nunca hardcodees la key
})

Crea un archivo .env con tu key:

APISPAIN_API_KEY=tu_api_key_aqui

Buscar una empresa por nombre

const resultados = await client.borme.getSociedades({
  nombre: 'Telefonica',
  provincia: 'Madrid',
})

console.log(resultados)
// [
//   { nif: 'A28015865', nombre: 'TELEFONICA SA', estadoRegistral: 'activa', ... },
//   ...
// ]

Obtener datos completos por NIF

const empresa = await client.borme.getSociedadById('A28015865')

console.log({
  nombre: empresa.nombre,
  estado: empresa.estadoRegistral,
  domicilio: `${empresa.municipio}, ${empresa.provincia}`,
  constituida: new Date(empresa.fechaConstitucion).toLocaleDateString('es-ES'),
  capital: empresa.capitalSocial
    ? `${Number(empresa.capitalSocial).toLocaleString('es-ES')}€`
    : 'No disponible',
})

Consultar el historial de actos

Los actos son el corazón del BORME: cada cambio societario queda registrado con fecha, tipo y datos estructurados.

const actos = await client.borme.getActos({ empresaNif: 'A28015865' })

for (const acto of actos) {
  console.log(`[${new Date(acto.fechaPublicacion).toLocaleDateString('es-ES')}] ${acto.tipoActo}`)
  if (acto.datosParseados) {
    console.log('  Datos:', acto.datosParseados)
  }
}

Salida de ejemplo:

[03/11/2024] Nombramiento de consejero delegado
  Datos: { nombre: 'MARC MURTRA MILLAR', cargo: 'Consejero Delegado' }
[15/06/2023] Ampliación de capital
  Datos: { capitalAnterior: '4864235.00', capitalNuevo: '5012890.00' }
[22/01/2020] Cese de administrador
  Datos: { nombre: 'JOSÉ MARÍA ÁLVAREZ-PALLETE', cargo: 'Presidente' }

Actos publicados en el BORME hoy

Si quieres procesar todos los actos del día (útil para pipelines de datos):

const hoy = new Date().toISOString().split('T')[0] // '2026-04-14'
const actosHoy = await client.borme.getActos({ fecha: hoy })

console.log(`${actosHoy.length} actos publicados hoy en el BORME`)

// Filtrar solo constituciones
const constituciones = actosHoy.filter(a =>
  a.tipoActo.toLowerCase().includes('constitución')
)
console.log(`${constituciones.length} empresas constituidas hoy`)

Sin SDK: fetch nativo

Si prefieres no añadir dependencias:

const API_KEY = process.env.APISPAIN_API_KEY
const BASE = 'https://api.apispain.es/v1'

async function bormeGet(path, params = {}) {
  const url = new URL(`${BASE}${path}`)
  Object.entries(params).forEach(([k, v]) => {
    if (v !== undefined) url.searchParams.set(k, v)
  })

  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  })

  if (!res.ok) {
    const err = await res.json().catch(() => ({}))
    throw new Error(err.message ?? `HTTP ${res.status}`)
  }

  return res.json()
}

// Uso
const empresa = await bormeGet('/borme/empresas/A28015865')
const actos   = await bormeGet('/borme/empresas/A28015865/actos')
const hoy     = await bormeGet('/borme/actos/2026-04-14')

Caso de uso: script de monitorización diaria

Este script comprueba cada día si alguna de tus empresas monitorizadas tiene nuevos actos y lo registra en un log:

import Apispain from 'apispain'
import fs from 'fs/promises'

const client = new Apispain({ apiKey: process.env.APISPAIN_API_KEY })

const EMPRESAS_MONITORIZADAS = [
  { nif: 'A28015865', alias: 'Telefonica' },
  { nif: 'B12345678', alias: 'Proveedor Principal' },
  { nif: 'A08000003', alias: 'Cliente Clave' },
]

async function revisarCambios() {
  const hoy = new Date().toISOString().split('T')[0]
  const log = []

  for (const { nif, alias } of EMPRESAS_MONITORIZADAS) {
    try {
      const actos = await client.borme.getActos({ empresaNif: nif })
      const actosHoy = actos.filter(a =>
        a.fechaPublicacion.startsWith(hoy)
      )

      if (actosHoy.length > 0) {
        log.push({ nif, alias, actos: actosHoy })
        console.log(`⚠️  ${alias} (${nif}): ${actosHoy.length} acto(s) nuevos hoy`)
        actosHoy.forEach(a => console.log(`   → ${a.tipoActo}`))
      }
    } catch (err) {
      console.error(`Error consultando ${alias}:`, err.message)
    }
  }

  if (log.length > 0) {
    await fs.writeFile(`borme-log-${hoy}.json`, JSON.stringify(log, null, 2))
  }

  console.log(`✅ Revisión completada — ${log.length} empresa(s) con cambios`)
}

revisarCambios()

Puedes ejecutar este script con un cron job diario (crontab -e):

30 10 * * 1-5 node /ruta/tu-script.js >> /var/log/borme-monitor.log 2>&1

Recibir alertas automáticas con webhooks

Si no quieres ejecutar un script, el plan Pro incluye webhooks. Apispain te notifica con un HTTP POST cada vez que se publique un acto del BORME para una empresa concreta:

// Crear un webhook para monitorizar una empresa
const webhook = await client.webhooks.create({
  url: 'https://tu-servidor.com/webhook/borme',
  secret: 'tu-secreto-para-verificar',
  eventos: ['borme.acto'],
  filtros: { empresaNif: 'A28015865' },
})

console.log('Webhook creado:', webhook.id)

Tu endpoint recibirá un POST con el acto cada vez que se publique:

// Express handler de ejemplo
app.post('/webhook/borme', (req, res) => {
  const { evento, payload } = req.body
  console.log(`Nuevo acto en BORME: ${payload.tipoActo} — ${payload.empresaNif}`)
  // Envía un email, crea una tarea en tu CRM, actualiza tu BD...
  res.sendStatus(200)
})

Próximos pasos

  • Explora la documentación completa con todos los parámetros disponibles
  • Si necesitas también datos de subvenciones o licitaciones, el mismo cliente te da acceso: client.bdns, client.place
  • Para volúmenes altos, el plan Pro tiene requests ilimitados — ver precios
Empieza gratis en 2 minutos

20 requests/mes gratis, sin tarjeta de crédito. API key lista al momento.

Ver documentación