Saltar al contenido principal
Referencia completa v1

Documentacion API

REST + JSON. Sin autenticacion. CORS abierto. Base URL: https://openmercantil.es

Especificación machine-readable

OpenAPI 3.1

Toda la API está descrita en un fichero OpenAPI 3.1 consumible directamente por Swagger Editor, Postman, Insomnia, Stoplight, generadores de clientes (openapi-generator) y agregadores de catálogos (DCAT-AP, data.europa.eu, etc.).

Probar en /docs (Swagger UI) /openapi.json /api/openapi.json (alias) /catalog.rdf (DCAT-AP) Abrir en Swagger Editor →

También disponible vía Accept: application/json o sufijo .json. CORS abierto (Access-Control-Allow-Origin: *) para tooling externo. Catálogo DCAT-AP-ES en /catalog.rdf (RDF/XML).

Empezar en 30 segundos

Copia cualquiera de estos comandos. No necesitas clave de API.

1. Buscar una empresa

curl "https://openmercantil.es/api/v1/search?q=mercadona&limit=5"

2. Obtener ficha completa de empresa

curl "https://openmercantil.es/api/v1/company/mercadona-sa-a46103834"

3. Estado del sistema

curl "https://openmercantil.es/api/v1/health"

Rate limiting

Free: 60 req/min y 200 req/día por IP. Planes superiores (Profesional 5.000 req/día, MAX 50.000 req/día, Enterprise 500.000+ req/día) según cuenta y API key.

PlanPor minutoPor díaAcceso
Free60200Anónimo, por IP
Profesional1205.000API key personal
MAX60050.000API key personal
Enterprisea convenir500.000+Contrato

Las respuestas incluyen estas cabeceras (RFC draft-ietf-httpapi-ratelimit-headers):

CabeceraDescripción
X-RateLimit-LimitCuota diaria del plan actual (ej. 200 en Free).
X-RateLimit-RemainingPeticiones restantes en la ventana diaria.
X-RateLimit-ResetTimestamp Unix en que se reinicia el contador.
X-OpenMercantil-PlanEtiqueta del plan resuelto (Free, Profesional, MAX, Enterprise).
Retry-AfterSegundos a esperar (solo en respuestas 429).

Para cargas masivas usa los datasets descargables en lugar de recorrer la API en bucle.

Errores

CódigoSignificadoCausa habitual
200 OKExitoPeticion correcta con resultados.
400 Bad RequestParametro invalidoFalta q, formato de fecha incorrecto, etc.
404 Not FoundRecurso inexistenteSlug de empresa o persona desconocido.
429 Too Many RequestsRate limit superadoMás de 60 req/min o 200 req/día desde la misma IP en Free.
500 Internal Server ErrorError internoArtefacto corrupto o fallo de proceso.

Ejemplo de respuesta de error:

{
  "error": "not_found",
  "message": "Company slug not found",
  "status": 404
}

Paginacion

La API usa dos esquemas según el endpoint:

EndpointParametrosNotas
Búsqueda (/search)limit + offsetDesplazamiento clasico. Max limit=100.
Eventos empresa (/events)page + page_sizePaginacion por número de pagina. Default page_size=50.

La respuesta siempre incluye total o count para calcular el número de paginas.

Bulk downloads

Si necesitas miles de registros, descarga los datasets completos desde /descargas en lugar de llamar la API en bucle. Estan disponibles:

  • Indice de empresas en JSON (comprimido .gz)
  • Indice de personas en JSON
  • Dataset completo de eventos en CSV por ano
  • Snapshots mensuales de cargos vigentes

Usa la API para consultas puntuales y los datasets para analisis masivo, ETL o entrenamiento de modelos.

GET

Ficha completa de empresa

/api/v1/company/{slug}

Devuelve el informe completo de una empresa: datos registrales, KPIs, timeline de actividad, cargos y lista de actos.

Parametros

NombreTipoRequeridoDefaultDescripción
slugstringsiIdentificador slug de la empresa (nombre-cif). Ej: inditex-sa-a15075062.

Respuesta

CampoTipoDescripción
company.namestringNombre oficial.
company.cifstringCIF/NIF registral.
company.statusstringEstado actual: ACTIVA, EXTINGUIDA, DISOLUCION, etc.
company.company_typestringTipo societario (SA, SL, etc.).
company.aliasesarrayNombres anteriores o variaciones.
company.addressstringDomicilio social.
company.capitalstringCapital social declarado.
company.websitestringSitio web si consta en BORME.
company.workersintNum. de trabajadores si consta.
company.date_creationstringFecha de constitucion.
kpis.acts_countintTotal de actos registrados.
kpis.first_seenstringPrimera fecha en el sistema.
kpis.last_seenstringÚltima fecha en el sistema.
timelinearrayArray {period, count} mensual.
top_event_typesarrayTipos de acto mas frecuentes.
top_provincesarrayProvincias de actividad.
eventsarrayActos recientes (max 50 por defecto).
officers.currentarrayCargos vigentes.
officers.historicalarrayCargos anteriores.
summary_textstringResumen en lenguaje natural.
curl "https://openmercantil.es/api/v1/company/inditex-sa-a15075062"
import requests
slug = "inditex-sa-a15075062"
r = requests.get(f"https://openmercantil.es/api/v1/company/{slug}")
data = r.json()
print(data["kpis"]["acts_count"])
const slug = "inditex-sa-a15075062";
const res = await fetch(`https://openmercantil.es/api/v1/company/${slug}`);
const { company, kpis } = await res.json();
console.log(company.name, kpis.last_seen);
GET

Eventos paginados de empresa

/api/v1/company/{slug}/events

Devuelve los actos registrales de una empresa para un ano concreto, paginados para respuestas ligeras.

Parametros

NombreTipoRequeridoDefaultDescripción
slugstringsiSlug de la empresa.
yearintnoAno a filtrar (YYYY). Sin valor, devuelve todos.
pageintno1Número de pagina (base 1).
page_sizeintno50Resultados por pagina.

Respuesta

CampoTipoDescripción
slugstringSlug de la empresa.
yearintAno filtrado.
pageintPagina actual.
page_sizeintResultados por pagina.
totalintTotal de eventos para el ano/filtro.
eventsarrayArray de actos: {id, date, type, province, description}.
curl "https://openmercantil.es/api/v1/company/inditex-sa-a15075062/events?year=2025&page=1&page_size=20"
import requests
r = requests.get("https://openmercantil.es/api/v1/company/inditex-sa-a15075062/events",
    params={"year":2025,"page":1,"page_size":20})
print(r.json()["total"])
const res = await fetch(
  "https://openmercantil.es/api/v1/company/inditex-sa-a15075062/events?year=2025&page=1"
);
const { events, total } = await res.json();
GET

Cargos de empresa

/api/v1/company/{slug}/officers

Devuelve administradores, apoderados y otros cargos, separados en vigentes e historicos.

Parametros

NombreTipoRequeridoDefaultDescripción
slugstringsiSlug de la empresa.

Respuesta

CampoTipoDescripción
slugstringSlug de la empresa.
officers.currentarrayCargos vigentes: {name, role, person_slug, date_from}.
officers.historicalarrayCargos anteriores: {name, role, person_slug, date_from, date_to}.
curl "https://openmercantil.es/api/v1/company/inditex-sa-a15075062/officers"
import requests
r = requests.get("https://openmercantil.es/api/v1/company/inditex-sa-a15075062/officers")
for c in r.json()["officers"]["current"]:
    print(c["name"], c["role"])
const res = await fetch("https://openmercantil.es/api/v1/company/inditex-sa-a15075062/officers");
const { officers } = await res.json();
officers.current.forEach(c => console.log(c.name, c.role));
GET

Exportar empresa (JSON adjunto)

/api/v1/company/{slug}/export

Devuelve el informe completo como fichero descargable con Content-Disposition: attachment.

Parametros

NombreTipoRequeridoDefaultDescripción
slugstringsiSlug de la empresa.
formatstringnojsonFormato de exportacion (actualmente solo json).

Respuesta

CampoTipoDescripción
application/jsonMismo esquema que /company/{slug} pero con cabecera de descarga.
curl -O -J "https://openmercantil.es/api/v1/company/inditex-sa-a15075062/export?format=json"
import requests
r = requests.get("https://openmercantil.es/api/v1/company/inditex-sa-a15075062/export?format=json")
with open("informe.json","wb") as f:
    f.write(r.content)
const res = await fetch("https://openmercantil.es/api/v1/company/inditex-sa-a15075062/export?format=json");
const blob = await res.blob();
const url = URL.createObjectURL(blob);
// asignar a un <a download="informe.json">
GET

Ficha de persona

/api/v1/person/{slug}

Devuelve el perfil completo de una persona: cargos activos, historicos y empresas vinculadas.

Parametros

NombreTipoRequeridoDefaultDescripción
slugstringsiSlug normalizado de la persona.

Respuesta

CampoTipoDescripción
slugstringSlug de la persona.
namestringNombre completo.
first_seenstringPrimera aparicion en BORME.
last_seenstringÚltima aparicion en BORME.
companies_countintTotal de empresas en las que ha tenido cargo.
active_positionsarrayCargos vigentes: {company_name, slug, role, date_from}.
inactive_positionsarrayCargos anteriores: {company_name, slug, role, date_from, date_to}.
curl "https://openmercantil.es/api/v1/person/amancio-ortega-gaona"
import requests
r = requests.get("https://openmercantil.es/api/v1/person/amancio-ortega-gaona")
p = r.json()
print(p["name"], "—", p["companies_count"], "empresas")
const res = await fetch("https://openmercantil.es/api/v1/person/amancio-ortega-gaona");
const person = await res.json();
console.log(person.active_positions);
GET

Sumario diario BORME

/api/v1/daily/{YYYY-MM-DD}

Devuelve todos los actos publicados en el BORME para una fecha, agrupados por seccion y provincia. Alias: /api/v1/summary/date/{YYYY-MM-DD}.

Parametros

NombreTipoRequeridoDefaultDescripción
YYYY-MM-DDstringsiFecha en formato ISO 8601. Ej: 2026-04-17.

Respuesta

CampoTipoDescripción
datestringFecha consultada.
sectionsobjectObjeto con secciones BORME (1=SA/SL, 2=otros, 3=concursal). Cada seccion es un objeto provincia → [{id, company, type, slug}].
curl "https://openmercantil.es/api/v1/daily/2026-04-17"
import requests
r = requests.get("https://openmercantil.es/api/v1/daily/2026-04-17")
data = r.json()
for prov, actos in data["sections"]["1"].items():
    print(prov, len(actos), "actos")
const res = await fetch("https://openmercantil.es/api/v1/daily/2026-04-17");
const { date, sections } = await res.json();
const seccion1 = sections["1"];
console.log(Object.keys(seccion1)); // provincias
GET

Health check

/api/v1/health

Devuelve el estado operativo del sistema, la edad de los artefactos y metricas de volumen.

Parametros

NombreTipoRequeridoDefaultDescripción

Respuesta

CampoTipoDescripción
statusstringok o degraded.
servicestringNombre del servicio.
versionstringVersion de la API.
artifacts_age_hoursfloatHoras desde la última actualizacion de artefactos.
artifacts_last_modifiedstringFecha ISO del último artefacto.
latest_borme_processedstringÚltima fecha de BORME procesada.
companies_indexed_approxintEmpresas indexadas aproximadas.
total_persons_approxintPersonas indexadas aproximadas.
total_events_approxintEventos totales aproximados.
csv_size_mbfloatTamano del CSV principal en MB.
timestampstringFecha/hora de la respuesta en ISO 8601.
curl "https://openmercantil.es/api/v1/health"
import requests
r = requests.get("https://openmercantil.es/api/v1/health")
h = r.json()
print(h["status"], "—", h["companies_indexed_approx"], "empresas")
const res = await fetch("https://openmercantil.es/api/v1/health");
const health = await res.json();
console.log(health.status, health.latest_borme_processed);
GET

Export de eventos en CSV

/api/v1/export/events

Streaming CSV de todos los eventos, opcionalmente filtrado por ano. Util para analisis de datos y ETL.

Parametros

NombreTipoRequeridoDefaultDescripción
yearintnoAno a filtrar (YYYY). Sin valor, devuelve todos.
formatstringnocsvSolo csv por ahora.

Respuesta

CampoTipoDescripción
text/csvFichero CSV con cabecera: id, date, company_slug, company_name, type, province, description.
curl -O "https://openmercantil.es/api/v1/export/events?year=2025&format=csv"
import requests
r = requests.get("https://openmercantil.es/api/v1/export/events", params={"year":2025,"format":"csv"}, stream=True)
with open("eventos_2025.csv","wb") as f:
    for chunk in r.iter_content(chunk_size=8192):
        f.write(chunk)
const res = await fetch("https://openmercantil.es/api/v1/export/events?year=2025&format=csv");
const text = await res.text();
// parsear con PapaParse u otro parser CSV
GET

Export CSV directo

/export

Endpoint legado de exportacion CSV. Acepta empresa, persona o búsqueda libre.

Parametros

NombreTipoRequeridoDefaultDescripción
formatstringsicsvDebe ser csv.
empresastringnoSlug de empresa.
personastringnoSlug de persona.
qstringnoTexto de búsqueda para exportar resultados.

Respuesta

CampoTipoDescripción
text/csvCSV de los actos de la empresa/persona o resultados de búsqueda.
# Por empresa
curl -O "https://openmercantil.es/export?format=csv&empresa=inditex-sa-a15075062"

# Por persona
curl -O "https://openmercantil.es/export?format=csv&persona=amancio-ortega-gaona"

# Por búsqueda
curl -O "https://openmercantil.es/export?format=csv&q=mercadona"
import requests
r = requests.get("https://openmercantil.es/export",
    params={"format":"csv","empresa":"inditex-sa-a15075062"})
with open("empresa.csv","wb") as f:
    f.write(r.content)
const res = await fetch("https://openmercantil.es/export?format=csv&empresa=inditex-sa-a15075062");
const blob = await res.blob();
const url = URL.createObjectURL(blob);

Endpoints v1.1 — Sectores, Score, Fuentes externas

Endpoints añadidos en abril 2026 para navegación CNAE, score de actividad, gadgets visuales y datos de fuentes externas.

EndpointDescripción
GET /api/v1/cnae/tree Árbol jerárquico CNAE 2009 (21 secciones + 88 divisiones) con conteos.
GET /api/v1/cnae/{code} Info de un código CNAE (ej. J o 62).
GET /api/v1/sector/{code}/companies Empresas del sector. Params: limit, offset, sort, province.
GET /api/v1/sector/{code}/ratios Ratios financieros sectoriales (ROE, ROA, margen) — fuente BdE.
GET /api/v1/company/{slug}/score Score 0-100 de actividad + breakdown (volume, recency, diversity, officers).
GET /api/v1/company/{slug}/activity Timeseries mensual de actos para gráficos.
GET /api/v1/company/{slug}/similar Empresas similares (mismo CNAE × misma provincia). Param: limit.
GET /api/v1/company/{slug}/geocode Coordenadas lat/lng del domicilio social (cache Nominatim).
GET /api/v1/company/{slug}/grants Subvenciones públicas recibidas por NIF (fuente BDNS).
GET /api/v1/company/{slug}/sanctions Cruce con listas Open Sanctions (PEP / sanciones internacionales).
GET /api/v1/company/{slug}/cnmv Datos de cotización + hechos relevantes (si la empresa cotiza).
GET /api/v1/sources/status Estado de cada fuente externa: última sincronización, items count.
POST /api/v1/checkout Crear sesión Stripe Checkout (suscripción Pro/Business/Agency). Auth requerida.
POST /api/v1/donation Crear sesión Stripe one-time (donación). Anónima permitida. Body: {amount_cents: 500-100000}.

Ejemplo: empresas TI en Madrid ordenadas por actividad

curl "https://openmercantil.es/api/v1/sector/62/companies?province=madrid&sort=acts&limit=10"

Ejemplo: score + similares de una empresa

curl "https://openmercantil.es/api/v1/company/inditex-sa-a15075062/score" | jq
curl "https://openmercantil.es/api/v1/company/inditex-sa-a15075062/similar?limit=5" | jq

🆕 Endpoints v1.4 (mayo 2026)

Cruce abierto BORME × CNMV × OEPM × PLACSP × BOE × sanciones. Sin API key, rate-limit suave, cache 1h.

Trust Score (educativo)

GET /api/v1/company/{slug}/trust-score

Score 0-100 basado en datos públicos. NO es scoring crediticio. Devuelve {score, band, label, factors[], disclaimer}. Cache 24h.

Sociograma de cargos

GET /api/v1/company/{slug}/network

Bipartite graph: empresa central → admins → otras empresas con admins comunes. Renderizable con vis-network o D3.js. Limit 12 personas × 4 empresas.

Embargos AEAT/TGSS (BOE)

GET /api/v1/company/{slug}/embargoes

Diligencias de embargo + subastas + liberaciones publicadas en BOE Sección V-B. Devuelve {count, summary, items[]} con tipo, importe, expediente, organismo, fecha y URL al anuncio oficial.

Contratos PLACSP (persona)

GET /api/v1/persona/{slug}/contracts

Contratos públicos adjudicados a empresas que esta persona administra(ba). Solo cuenta contratos firmados durante el período del cargo. Devuelve {count, total_eur, by_company[], top[], by_cpv[]}.

Top empresas por licitaciones

GET /api/v1/contracts/top-companies?limit=50&province=madrid&cnae=F
GET /api/v1/contracts/top-companies.csv?limit=100  # Excel-friendly UTF-8 BOM

Filtros opcionales: province (slug), cnae (sección A-U), limit (1-500).

Top personas por licitaciones

GET /api/v1/contracts/top-persons?limit=30
GET /api/v1/contracts/top-persons.csv?limit=100

Personas administradoras con más contratos públicos en empresas que dirigen. Período del cargo se respeta.

Estadísticas sectoriales (CNAE)

GET /api/v1/sectores/stats        # JSON
GET /api/v1/sectores/stats.csv    # Excel

Por sección CNAE: total empresas, activas/extintas/concurso, capital total inscrito, contratos PLACSP. Cache 24h.

Estadísticas por CCAA

GET /api/v1/ccaa/stats            # 18 CCAA + Ceuta + Melilla

Distribución geográfica por Comunidad Autónoma. Cruce automático provincia → CCAA.

Geocode + mapa

GET /api/v1/company/{slug}/geocode[?force=1]

Devuelve {lat, lng, address, source}. Cache hit instantáneo. Cache miss: live Nominatim OSM (rate-limit 1 req/sec). force=1 bypassa cache.

⚠️ Nota legal: Trust Score es educativo (NO scoring crediticio profesional). Embargos pueden no incluir resoluciones posteriores. Contratos PLACSP no incluyen modificaciones contractuales. Para due diligence consulta fuentes oficiales o proveedores acreditados.

Changelog

VersionFechaCambios
v1.4 2026-05-05 NEW: /company/{slug}/trust-score, /company/{slug}/embargoes, /company/{slug}/network, /persona/{slug}/contracts, /contracts/top-companies + top-persons (.csv export), /sectores/stats, /ccaa/stats (.csv/.json). Geocode con fallback Nominatim live (sin pipeline previo).
v1.2 2026-04-27 Endpoints fuentes externas: /grants (BDNS), /sanctions (OpenSanctions), /cnmv, /geocode. Endpoint /sources/status con frescura por fuente.
v1.1 2026-04-27 Endpoints CNAE: árbol jerárquico, info por código, listado por sector. Endpoints empresa: score, activity timeseries, similares. Endpoint sector: ratios financieros (BdE). Stripe: POST /checkout, POST /donation.
v1.0 2026-04-17 Release inicial. Endpoints de búsqueda, ficha empresa/persona, sumario diario, exportacion CSV, health check y documentacion pública.
Datasets descargables Volver a API Uso intensivo o soporte