API de licitaciones públicas de España

Todas las licitaciones que publica el sector público español, normalizadas, desde tu programa, tu CRM o un agente de IA. Incluida en la suscripción Pro; las claves se crean en tu panel.

Qué puedes hacer

RutaPara qué
GET /api/public/v1/contractsBuscar licitaciones con texto y filtros (CPV, provincia, comunidad, estado, tipo, procedimiento, presupuesto, fechas, solo abiertas).
GET /api/public/v1/contracts/{id o slug}Una licitación con adjudicaciones por lote, documentos y cronología.
GET /api/public/v1/contracts/{id o slug}/documentsPliegos, anuncios y actas.
GET /api/public/v1/changes?since=…Lo que cambió desde una fecha: para mantener tu propia copia al día.
GET /api/public/v1/organizations/{NIF o id}Un organismo contratante.
/api/public/v1/alertsTus alertas: listar, crear, cambiar, borrar y ver sus coincidencias.
/api/public/v1/followsTus seguimientos de licitaciones concretas.

Autenticación

Cada petición lleva tu clave, que empieza por dl_live_, en una de estas dos cabeceras:

Authorization: Bearer dl_live_…
X-API-Key: dl_live_…

Trátala como una contraseña: no la pongas en código que se publica ni en el navegador. Si se filtra, revócala en el panel y crea otra. Una clave de solo lectura no puede crear ni cambiar alertas o seguimientos; al crearla eliges si le das escritura.

Límites

Por clave: 60 peticiones por minuto y 10.000 al día (el día cuenta en UTC). Hasta 5 claves activas por cuenta. Cada respuesta dice cuánto te queda:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-Quota-Limit: 10000
X-Quota-Remaining: 9431

Si te pasas, recibes un 429 con Retry-After en segundos.

Errores

Siempre con la misma forma, y un code estable para que tu programa decida qué hacer:

{"error": {"code": "plan_required", "message": "…", "upgrade_url": "https://donlicitacion.es/pro?origen=api"}}
HTTPcodeQué pasa
400invalid_parameter / invalid_cursorUn filtro con un valor que no existe, o un cursor alterado.
401missing_api_keyNo viene clave.
401invalid_api_keyLa clave no existe o está mal copiada.
401revoked_api_keyLa clave se revocó.
403plan_requiredLa cuenta no es Pro. La clave se conserva y vuelve a funcionar al contratar.
403insufficient_scopeEscritura con una clave de solo lectura.
404not_foundNo existe esa licitación u organismo.
429rate_limitedDemasiadas peticiones por minuto. Espera lo que diga `Retry-After`.
429quota_exceededCuota diaria agotada. Se renueva a las 00:00 UTC.
503api_not_configuredLa API no está disponible en este momento.
503query_timeoutLa búsqueda tardó demasiado: añade un texto o acota por fechas o provincia.

Si dejas de ser Pro, tus claves no se borran: responden plan_required y vuelven a funcionar en cuanto contratas de nuevo.

Paginación

Los listados devuelven {"data": […], "meta": {"siguiente_cursor": "…", "page_size": 25}}. Para la página siguiente, repite la llamada con cursor= y el valor de siguiente_cursor, tal cual. Cuando viene null, no hay más. No hay números de página: el cursor no se salta ni repite resultados aunque entren licitaciones nuevas mientras paginas. page_size va de 1 a 100.

Ejemplos

curl

curl -H "Authorization: Bearer $DL_API_KEY" \
  "https://donlicitacion.es/api/public/v1/contracts?cpv=45&provincia=Madrid&solo_abiertas=true&page_size=50"

Python

import os, httpx

cliente = httpx.Client(
    base_url="https://donlicitacion.es/api/public/v1",
    headers={"Authorization": f"Bearer {os.environ['DL_API_KEY']}"},
)
cursor = None
while True:
    r = cliente.get("/contracts", params={"q": "limpieza", "solo_abiertas": True, "cursor": cursor})
    r.raise_for_status()
    cuerpo = r.json()
    for lic in cuerpo["data"]:
        print(lic["fecha_limite"], lic["titulo"], lic["url"])
    cursor = cuerpo["meta"]["siguiente_cursor"]
    if not cursor:
        break

JavaScript

const r = await fetch(
  "https://donlicitacion.es/api/public/v1/changes?since=2026-09-24T00:00:00Z",
  { headers: { Authorization: `Bearer ${process.env.DL_API_KEY}` } },
);
const { data, meta } = await r.json();

Crear una alerta (clave con escritura)

curl -X POST -H "Authorization: Bearer $DL_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Limpieza en Madrid", "filter_text": "limpieza", "filter_provincia": ["Madrid"]}' \
  https://donlicitacion.es/api/public/v1/alerts

Con un agente de IA

Dale al agente la URL del OpenAPI (/api/public/v1/openapi.json) y tu clave como secreto: cada ruta y cada campo llevan su descripción en castellano. Los estados, tipos y procedimientos vienen como {"codigo", "etiqueta"}: el código para filtrar, la etiqueta para contar. abierta ya tiene en cuenta el plazo: no hace falta compararlo con la fecha.

Conectar tu IA por MCP

Si usas Claude, Cursor, VS Code u otro asistente compatible con MCP, puedes conectarlo directamente a las licitaciones con tu misma clave, sin escribir código: servidor MCP de Don Licitación.

Fuentes y licencias

Los datos vienen de plataformas oficiales, y cada una exige que se la cite. Por eso cada licitación lleva un objeto fuente con el titular, la licencia y el texto de atribución: si reutilizas o publicas un registro, conserva ese texto. Los datos de Galicia se publican con licencia CC BY-SA 4.0: puedes redistribuirlos, con la misma licencia.

TitularLicencia
Ministerio de Hacienda, Plataforma de Contratación del Sector PúblicoES-RISP-AGE
Generalitat de Catalunya, Departament d'Economia i FinancesLOUI-CAT
Gobierno Vasco, Open Data Euskadi (KontratazioA)CC-BY-4.0
Xunta de Galicia, Contratos Públicos de GaliciaCC-BY-SA-4.0
Junta de AndalucíaCC-BY-3.0
Gobierno de Navarra, Gobierno Abierto de NavarraCC-BY-4.0

Ninguno de estos organismos participa en este servicio, lo patrocina ni lo respalda.

Cambios en la API

  • v1 (24 de septiembre de 2026): primera versión.