# lead-platform — API de captura de leads

> Endpoint público para registrar un lead (correo + consentimiento) desde una
> herramienta externa. Cada herramienta es una "fuente" con su propia API key.
> La seguridad está en la API key, el consentimiento y el rate limit — no en
> ocultar el endpoint.

Base URL: `https://leadboard.aurora33.dev`

## Autenticación

Toda petición lleva el header `x-api-key` con la API key de tu fuente (te la
entrega el administrador del panel; se muestra una sola vez al crearla).

- La key identifica la fuente y determina qué campos puedes enviar.
- Si la key no existe o la fuente está desactivada → `401`.
- Nunca incluyas la key en URLs, logs ni repos públicos.

## Endpoint

```
POST https://leadboard.aurora33.dev/api/capture
```

### Headers

| Header         | Requerido | Valor                  |
| -------------- | --------- | ---------------------- |
| `x-api-key`    | sí        | API key de la fuente   |
| `Content-Type` | sí        | `application/json`     |

### Body (JSON)

| Campo          | Tipo    | Requerido | Notas |
| -------------- | ------- | --------- | ----- |
| `email`        | string  | sí        | Se normaliza (minúsculas + trim). Debe ser un correo válido. |
| `consent`      | boolean | sí        | Debe ser exactamente `true`. Si es `false` u otro → `422`. |
| `consent_text` | string  | no        | Texto exacto del consentimiento aceptado. Se guarda como evidencia. |
| `name`         | string  | depende   | Solo si el `schema` de tu fuente lo permite. |
| `metadata`     | object  | no        | Objeto libre con datos extra de tu campaña. |

Cada fuente declara un `schema` (campos `required` / `optional`). Claves que no
estén en ese conjunto ni en `{email, consent, consent_text, metadata}` se
**rechazan** (`422`) — minimización de datos.

### Respuestas

| Código | Significado |
| ------ | ----------- |
| `201` | Lead creado. Body: `{"ok":true,"created":true}` |
| `200` | El lead ya existía (idempotente por email+fuente). Body: `{"ok":true,"created":false}` |
| `400` | JSON inválido. |
| `401` | Falta `x-api-key`, key inválida o fuente inactiva. |
| `422` | Validación fallida o `consent` no es `true`. Body incluye `error` y a veces `detail`. |
| `429` | Rate limit excedido (10 req/min por IP). Header `Retry-After`. |
| `500` | Error interno. |

La respuesta nunca devuelve datos de otros leads.

## Idempotencia

Reenviar el mismo `email` para la misma fuente no crea duplicados: la segunda
vez responde `200` con `created:false`. Seguro reintentar.

## Rate limit

10 peticiones por minuto por IP. Al exceder → `429` con `Retry-After` (segundos).

## CORS

Solo se aceptan peticiones de navegador desde orígenes en la allowlist de la
fuente. Las peticiones servidor-a-servidor (sin header `Origin`) pasan, siempre
con API key válida.

## Ejemplos

### Captura exitosa (201)

```bash
curl -i -X POST https://leadboard.aurora33.dev/api/capture \
  -H "Content-Type: application/json" \
  -H "x-api-key: lp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -d '{
    "email": "ana@example.com",
    "name": "Ana",
    "consent": true,
    "consent_text": "Acepto recibir comunicaciones de Roastr.",
    "metadata": { "campaña": "verano" }
  }'
# 201  {"ok":true,"created":true}
# (repetir la misma → 200 {"ok":true,"created":false})
```

### Sin consentimiento (422)

```bash
curl -i -X POST https://leadboard.aurora33.dev/api/capture \
  -H "Content-Type: application/json" \
  -H "x-api-key: lp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -d '{ "email": "ana@example.com", "consent": false }'
# 422  {"error":"El consentimiento es obligatorio: \"consent\" debe ser true."}
```

### API key inválida (401)

```bash
curl -i -X POST https://leadboard.aurora33.dev/api/capture \
  -H "Content-Type: application/json" \
  -H "x-api-key: lp_invalida" \
  -d '{ "email": "ana@example.com", "consent": true }'
# 401  {"error":"API key inválida o fuente inactiva"}
```

## Para LLMs / agentes

- Spec machine-readable: `https://leadboard.aurora33.dev/openapi.json` (OpenAPI 3.1).
- Este documento: `https://leadboard.aurora33.dev/llms.txt` · descargable: `https://leadboard.aurora33.dev/api.md`.
- Para integrar: pide al usuario su API key, arma el body con `email` + `consent:true`,
  haz `POST` al endpoint con el header `x-api-key`, y trata `201`/`200` como éxito.
