Saltar al contenido

Documentación · v1

Introducción

La API de Divr sirve los datos de las cotizadas españolas: dividendos, calendario, resultados, cuentas anuales y ratios, leídos de la CNMV y de BME. Es REST: todo es GET, responde JSON en UTF-8 y pide una clave en la cabecera.

URL base https://api-production-2a50.up.railway.app

Tu primera petición

  1. Pide tu clave gratis aquí abajo. Sale al momento: 100 peticiones al día, sin tarjeta.
  2. Mándala en la cabecera Authorization: Bearer de cada petición a /v1/….
  3. Empieza por el catálogo: de /v1/issuers salen los identificadores del resto. O prueba sin escribir código en el explorador.
curl https://api-production-2a50.up.railway.app/v1/issuers/TEF.MC/dividends \
  -H "Authorization: Bearer $DIVR_API_KEY"

Clave gratis

Sale al momento, aquí mismo: 100 peticiones al día y sin tarjeta. Se enseña una sola vez.

Autenticación y convenciones

La clave va en la cabecera, nunca en la URL: una URL acaba en logs, historiales y proxies. Sin clave, o con una que no vale, la respuesta es 401 unauthorized con WWW-Authenticate: Bearer.

QuéCómo
AuthorizationBearer bmef_… en cada petición a /v1/.
CupoPlan gratuito: 100 peticiones al día, con el contador a cero a las 00:00 UTC. Cada respuesta lleva X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset (segundos Unix); al pasarte, 429 rate_limited con Retry-After.
CachéLas respuestas buenas llevan Cache-Control: private, max-age=86400; los errores, no-store.
CifrasNunca un escalar: {"value", "origin", …} o {"value": null, "reason"}.
VersiónAñadir campos o códigos no rompe /v1. Un consumidor debe ignorar lo que no conozca.
curl -H "Authorization: Bearer $CLAVE" \
     https://api-production-2a50.up.railway.app/v1/issuers

La respuesta lleva la procedencia dentro

Una cifra no puede existir sin decir de dónde sale. O apunta al hecho del que salió, o declara la fórmula, o dice por qué está vacía. En la vista de tabla del explorador, pulsa cualquier cifra para verlo.

Reportada

"revenue": {
  "value": 41315000000,
  "origin": "reported",
  "doc": 1,
  "concept": "I1010"
}

Apunta al documento y al concepto exactos. Se puede abrir el XBRL y verlo.

Hueco con motivo

"gross_profit": {
  "value": null,
  "reason": "no_existe_en_taxonomia"
}

Lista cerrada: no_existe_en_taxonomia, no_reportado, no_aplica_al_emisor, error_de_parseo. Un parser roto y una cifra que España no publica no son el mismo hueco.

Derivada

"ebitda": {
  "value": 13100000000,
  "origin": "derived",
  "formula": "operating_income
              + depreciation"
}

Si se calculó, dice con qué. Nada aparece sin explicar cómo llegó ahí.

Errores que dicen qué hacer

Dos 404 distintos, porque permanente y transitorio no se reintentan igual. Todos llegan con la misma forma: {"error": {"code", "message", "ticker"}}.

CódigoHTTPQué significa¿Reintentar?
issuer_unknown404Ese identificador no es de ningún emisor conocido.No
issuer_no_source404Se sabe quién es y nunca tendrá datos aquí. Permanente.Nunca
issuer_not_ingested404Conocido, con fuente, aún sin cargar. Transitorio.Sí, más tarde
events_not_scanned404El registro de comunicaciones aún no se ha recorrido.Sí, más tarde
bad_request400Un parámetro no se entiende: fechas mal escritas, ventana de más de 400 días o falta symbol.Corrige la petición
unauthorized401Falta la clave o no vale.Con otra clave
rate_limited429Has gastado las 100 peticiones de hoy del plan gratuito. X-RateLimit-Reset dice cuándo vuelve a cero (00:00 UTC).Sí, tras el reinicio
plan_not_allowed403Ruta de uso interno que el plan gratuito no incluye.No
not_found404Esa ruta no existe en /v1.Corrige la ruta
method_not_allowed405La API sólo responde a GET.Usa GET
not_implemented501Ruta reservada: los hechos crudos aún no se sirven.No
internal_error500Falló. Nunca un 200 parcial.Sí

Catálogo de emisores

GET/v1/issuers

Todos los valores del continuo, también los que no se sirven, con el motivo. Es el punto de partida: de aquí salen los id del resto.

Parámetros

Ninguno.

Respuesta

issuers[]Un emisor por fila: ticker, isin, nif, lei, name.
issuers[].ingestionloaded, not_ingested, identity_unverified o no_source.
issuers[].coveragefrom, to, missing, source_ends_after, mixed_perimeter.
generated_atCuándo se derivó la serie, con derivation_version.
{
  "generated_at": "2026-03-02T06:00:00Z",
  "issuers": [{
    "ticker": "EJE.MC", "isin": "ES0000000001",
    "ingestion": "loaded",
    "coverage": { "from": 2016, "to": 2025,
                  "missing": [] }
  }]
}

Probar en el explorador →

Serie anual

GET/v1/issuers/{id}/annual

Las cuentas anuales de un emisor, un objeto por ejercicio, desde el XBRL que deposita en la CNMV. Cada cifra dice si es reportada, derivada o un hueco con motivo.

Parámetros

NombreDóndeQué
idruta · obligatorioTicker (TEF.MC), ISIN o NIF.

Respuesta

issuer · coverageQuién es y qué ejercicios hay de verdad.
years[]year, perimeter, taxonomy, currency, sources[].
years[].fieldsrevenue, ebitda, net_income, eps_basic, total_debt, free_cash_flow, dividend_per_share…
"ebitda": {
  "value": 13100000000,
  "origin": "derived",
  "formula": "operating_income + depreciation",
  "inputs": ["operating_income", "depreciation"]
}

Probar en el explorador →

Resultados por periodo

GET/v1/issuers/{id}/results

Lo que la empresa presentó en cada periodo: primer semestre (H1), segundo (H2, la resta del ejercicio menos el primero) y ejercicio (FY). Si hay trimestres, Q1…Q4.

Parámetros

NombreDóndeQué
idruta · obligatorioTicker, ISIN o NIF.

Respuesta

years[].periods[]period, period_start, period_end, perimeter, currency, source, fields.
source{url, filed}, o null en un periodo que es una resta: sus campos lo dicen uno a uno.
quarters{available, reason}: si hay trimestres y de dónde salen, o por qué no.
{
  "period": "H2",
  "period_start": "2025-07-01",
  "period_end": "2025-12-31",
  "source": null,
  "fields": {
    "revenue": {
      "value": 19900000000,
      "origin": "derived",
      "formula": "h2_fy_menos_h1_v1",
      "inputs": ["FY.revenue", "H1.revenue"]
    }
  }
}

Probar en el explorador →

Ratios

GET/v1/issuers/{id}/ratios

Márgenes, rentabilidad, deuda, dividendo y crecimiento de cada ejercicio, calculados al vuelo con las cifras de /annual. Cada ratio lleva su formula y sus inputs: se rehace a mano con la serie anual.

Un ratio vacío dice por qué: hereda el motivo de la entrada que falta, o es denominador_cero, denominador_negativo (un ROE sobre patrimonio negativo no significa nada), sin_ejercicio_anterior o cambio_de_perimetro. Los de valoración (PER, rentabilidad por dividendo) llegarán con el precio.

Parámetros

NombreDóndeQué
idruta · obligatorioTicker, ISIN o NIF.

Respuesta

ratios_versionVersión del conjunto de fórmulas. Sube si cambia una.
years[].ratios.{ratio}value, unit (fraction: 0,12 = 12 %; currency: importe), formula, inputs, o value null con reason.
Ratiosoperating_margin, ebitda_margin, net_margin, fcf_margin, roe, roa, net_debt, net_debt_to_ebitda, debt_to_equity, liabilities_to_assets, payout_ratio, fcf_payout_ratio, capex_to_operating_cash_flow, revenue_growth, net_income_growth, eps_growth, dividend_per_share_growth.
{
  "year": 2025,
  "ratios": {
    "net_debt_to_ebitda": {
      "value": 2.6412,
      "unit": "fraction",
      "formula": "net_debt_to_ebitda_v1: (total_debt - cash) / ebitda",
      "inputs": ["total_debt", "cash", "ebitda"]
    },
    "roe": {
      "value": null,
      "unit": "fraction",
      "formula": "roe_v1: net_income / total_equity (cierre)",
      "inputs": ["net_income", "total_equity"],
      "reason": "denominador_negativo"
    }
  }
}

Probar en el explorador →

Dividendos de un emisor

GET/v1/issuers/{id}/dividends

Tres bloques que no se mezclan: lo anunciado a la CNMV (con la frase de la que sale cada fecha), lo que publica el mercado (BME) y lo estimado a partir de años anteriores, que da ventana y no fecha.

Parámetros

NombreDóndeQué
idruta · obligatorioTicker, ISIN o NIF.

Respuesta

coveragescanned_through: hasta qué día se ha leído la CNMV; stale si lleva más de 48 h.
events[]kind, status, amount_gross, ex_date, record_date, payment_date, confirmed_by_bme, source.
market[] · market_coverageEl calendario de BME y hasta dónde llega (served_through).
estimates[]payment_window {from, to, expected}, amount_gross, basis_years, dispersion_days.
"payment_date": {
  "value": "2026-06-18",
  "origin": "reported",
  "quote": "se abonará el 18 de junio de 2026"
}

Probar en el explorador →

Calendario de dividendos

GET/v1/events

Qué se paga entre dos fechas, en todos los emisores españoles, en una sola petición. Mismos bloques que los dividendos de un emisor; security.isin dice de quién es cada fila.

Parámetros

NombreDóndeQué
fromquery · opcionalPrimer día. Por defecto, hoy.
toquery · opcionalÚltimo día. Por defecto, hoy + 90. La ventana no pasa de 400 días.

Respuesta

events[] · market[] · estimates[]Lo anunciado, lo publicado por BME y lo estimado, como en los dividendos de un emisor.
bonus_issues[]Ampliaciones liberadas (scrip) cuyo periodo de derechos toca la ventana: rights_from, rights_to, admission_date, new_shares.
results_dates[]Presentaciones de resultados anunciadas por la empresa: date, fiscal_year, period y la frase de la que sale (quote, source). Sólo anunciadas, nunca estimadas.
GET /v1/events?from=2026-10-01&to=2026-12-31

Probar en el explorador →

Hechos relevantes

GET/v1/filings GET/v1/issuers/{id}/filings

Cada comunicación de las cotizadas en los dos registros de la CNMV: Otra Información Relevante y Información Privilegiada. Es lo que en EE. UU. sería el 8-K: dividendos, resultados, juntas, cambios en el consejo, recompras… con el epígrafe oficial, los temas que deja ver el asunto y el enlace al documento.

La primera ruta es el mercado entero entre dos fechas (por defecto, la última semana); la segunda, la serie de un emisor (por defecto, el último año). Se leen cada hora en días laborables.

Parámetros

NombreDóndeQué
idruta, o query en /v1/filingsTicker, ISIN o NIF del emisor.
from · toquery · opcionalDías de publicación. Máximo 400 días.
topicquery · opcionaldividendo, resultados, junta, consejo o recompra.
registerquery · opcionaloir o ip. Sin él, los dos.
limitquery · opcionalDe 1 a 500. Por defecto, 100, las más recientes primero.

Respuesta

filings[]register, registro (el número de la CNMV, para citarla), published_at, issuer (nif, name, ticker; null si la entidad no cotiza en el continuo), entity, title, category, topics[], url.
coveragestored_from: antes de ese día no hay nada guardado, que no es lo mismo que «no se publicó nada». scanned_through y stale, como en los dividendos.
truncatedtrue si había más filas que limit: estrecha la ventana o sube el límite.
GET /v1/filings?topic=dividendo&from=2026-10-01

{
  "filings": [{
    "register": "oir",
    "registro": "00000",
    "published_at": "2026-10-21T16:30:00Z",
    "issuer": { "nif": "A00000001",
                "name": "Ejemplo Energía, S.A.",
                "ticker": "EJE.MC" },
    "title": "Pago de dividendo a cuenta",
    "category": "Sobre dividendos",
    "topics": ["dividendo"],
    "url": "…"
  }],
  "truncated": false
}

Probar en el explorador →

Calendario de USA

GET/v1/us/dividends

El calendario de dividendos de Nasdaq, por ex-date y por símbolo. Sólo trae el bloque market: en USA aún no se leen anuncios ni se proyecta. La divisa va a null con motivo, porque la fuente no la declara.

Parámetros

NombreDóndeQué
symbolquery · opcionalFiltra a un valor (KO). Sin él, todo el calendario.
fromquery · opcionalPrimer ex-date. Por defecto, hoy.
toquery · opcionalÚltimo ex-date. Por defecto, hoy + 45. Máximo 400 días.

Respuesta

coveragefetched_at, read_from, read_through, days_failed, stale.
market[]symbol, company, amount, annual_dividend, ex_date, record_date, payment_date, announced_on, source.
"amount": {
  "value": 0.51,
  "currency": null,
  "currency_reason": "nasdaq_no_declara_divisa",
  "origin": "nasdaq_calendar"
}

Probar en el explorador →

Dividendos de cualquier valor

GET/v1/market/dividends

Lo que el calendario de Nasdaq no cubre: NYSE, Londres y cualquier mercado que Yahoo conozca. Se lee bajo demanda y se guarda medio día. Para un símbolo de USA se juntan las dos fuentes por ex-date y cada fila dice de cuál sale.

Parámetros

NombreDóndeQué
symbolquery · obligatorioKHC, DGE.L… Con sufijo fuera de USA.
fromquery · opcionalPor defecto, hace 30 días.
toquery · opcionalPor defecto, dentro de un año. Máximo 400 días.

Respuesta

coveragesource (yahoo o yahoo+nasdaq), fetched_at, stale, last_error.
market[]La misma forma que en el calendario de USA.
GET /v1/market/dividends?symbol=DGE.L

Probar en el explorador →

Hechos crudos

GET/v1/issuers/{id}/facts

Reservada. Responde 501 not_implemented hasta que exista, para que no se confunda con un emisor que no existe.