# Sincronizar las licitaciones de Sondeva con su base de datos

Un script de ejemplo, en Python y sin dependencias (solo `psycopg` si usa Postgres), que deja en su base
todas las licitaciones públicas de España y las mantiene al día. Puede usarlo tal cual o como guía para
escribir el suyo en su lenguaje.

- Script: <https://api.sondeva.es/ejemplos/sincronizar.py>
- Descripción OpenAPI de la API: <https://api.sondeva.es/v1/openapi.json>
- Documentación: <https://sondeva.es/api-de-licitaciones/>

## Cómo se usa

```bash
export SONDEVA_LLAVE=sdl_...                      # su llave: nunca en la línea de órdenes
python3 sincronizar.py --sqlite licitaciones.db   # en un fichero SQLite
python3 sincronizar.py --postgres "postgresql://usuario@servidor/base"
```

Para Postgres: `pip install "psycopg[binary]"`. La llave también puede ir en un fichero:
`--llave-en llave.txt`.

Láncelo cada hora o cada noche (cron, un programador de tareas…): retoma solo donde lo dejó.

## Qué hace

1. **La primera vez, la foto completa por ficheros.** Pide `/v1/ficheros`, baja cada parte, comprueba
   su huella SHA-256 y la carga. Después carga los ficheros de cambios que van detrás. Con una llave de
   prueba, que no incluye los ficheros, empieza por la API desde `--desde` (por omisión, hace 7 días).
2. **Después, los cambios por la API.** Pide `/v1/licitaciones?desde=...` y sigue página a página con
   el cursor.
3. **Cada licitación se guarda por su `id`.** Si ya estaba, gana la que tenga el `cambiada_en` más
   reciente. Da igual el orden en que lleguen o que alguna llegue dos veces.
4. **Guarda dónde se quedó** (el `cambiada_en` más reciente) en la tabla `sondeva_estado`, después de
   cada página.

## Las tablas

| Tabla | Columnas |
|---|---|
| `licitaciones` | `id` (clave), `cambiada_en`, `registro` (la licitación entera, en JSON; `jsonb` en Postgres) |
| `sondeva_estado` | `clave`, `valor` (aquí guarda `desde`) |

Los campos del registro están descritos en la documentación y en la descripción OpenAPI.

## Límites

Cada respuesta trae sus cupos en las cabeceras `X-Cupo-Filas-Dia`, `X-Cupo-Filas-Restantes` y
`X-Cupo-Peticiones-Minuto`, y `/v1/uso` dice lo gastado hoy. El script respeta los límites: ante un 429
espera lo que diga `Retry-After` y sigue; si se acaba el cupo del día, para y guarda, y la vez siguiente
sigue donde lo dejó. Ante un 503 reintenta unas veces.

## Si quiere que le avisemos

Si su sistema puede recibir un aviso, le mandamos un `POST` firmado cuando hay cambios nuevos (una vez al
día, tras la pasada de la noche), y entonces lanza el script. Pídalo en contacto@sondeva.es.
