# Portal para desarrolladores y agentes

> Todo lo que esta web publica sobre mí está también disponible como JSON, como OpenAPI y como markdown. Sin claves, sin registro y con CORS abierto.

Portal para desarrolladores de sgomez.dev: API REST pública y sin autenticación, especificación OpenAPI 3.1, errores en JSON, negociación de contenido en markdown y ficheros de instrucciones para agentes.

Canonical URL: https://sgomez.dev/developers

## Quickstart

Tres llamadas y ya tienes el mapa completo: comprueba que la API responde, léela desde su especificación y pide el perfil.

```bash
curl -s https://sgomez.dev/api/v1/health
curl -s https://sgomez.dev/openapi.json
curl -s https://sgomez.dev/api/v1/profile
```

No hay sandbox aparte ni claves de prueba: la API es de solo lectura y todo su contenido ya es público, así que el entorno de producción ES el entorno de pruebas. No hay nada que puedas romper con un GET.

## Endpoints

| Método y ruta | operationId | Qué devuelve |
| --- | --- | --- |
| GET /api/v1/health | getHealth | Estado del servicio y enlaces de entrada. |
| GET /api/v1/profile | getProfile | Identidad, rol, ubicación, contacto y disponibilidad. |
| GET /api/v1/about | getAbout | Biografía larga y cronología por años. |
| GET /api/v1/projects | listProjects | Proyectos publicados, con stack y enlace. |
| GET /api/v1/projects/{slug} | getProject | Un proyecto concreto por su slug. |
| GET /api/v1/experience | listExperience | Puestos, organizaciones y periodos. |
| GET /api/v1/skills | listSkills | Tecnologías por categoría, con años de uso. |
| GET /api/v1/certifications | listCertifications | Certificaciones con enlace al credencial. |
| GET /api/v1/education | listEducation | Formación reglada. |
| GET /api/v1/recommendations | listRecommendations | Recomendaciones escritas por colegas y clientes. |
| GET /api/v1/search?q= | searchContent | Búsqueda por palabras clave sobre todo lo anterior. |

Las colecciones aceptan `limit` (1–100) y `offset` (0–1000). `search` acepta `q` (obligatorio) y `limit` (1–50). Toda respuesta correcta va envuelta en `{ "data": …, "meta": … }`, y `meta` incluye `count`, `total`, `self` y `documentation_url`.

## Errores

Los errores también son JSON, con el mismo sobre siempre. `code` es estable y se puede usar en un `switch`; `hint` dice qué hacer para arreglarlo, que es lo que a un agente le falta cuando recibe un 404 vacío.

```json
{
  "error": {
    "status": 404,
    "code": "not_found",
    "message": "No project with slug \"nope\".",
    "hint": "Known slugs: nudaui, sortlab, … List them with GET /api/v1/projects.",
    "documentation_url": "https://sgomez.dev/developers"
  }
}
```

- `400 invalid_parameter` — un parámetro falta o está fuera de rango.
- `404 not_found` — el recurso o el endpoint no existe. Cualquier ruta desconocida bajo /api responde JSON, nunca HTML.
- `405 method_not_allowed` — la API es de solo lectura; la respuesta incluye la cabecera `Allow`.

## Autenticación y límites

No hay autenticación ni claves de API: no existe ningún dato privado detrás, así que una clave solo sería un trámite. Tampoco hay límite de peticiones por cliente más allá de la protección ordinaria de la CDN. A cambio, las respuestas se sirven cacheadas (`Cache-Control: public, max-age=300, s-maxage=3600`): si necesitas el catálogo entero, una llamada por colección basta, y repetir la misma llamada en bucle no te dará datos más frescos.

CORS está abierto a cualquier origen (`Access-Control-Allow-Origin: *`) para GET, HEAD y OPTIONS, así que la API se puede llamar desde el navegador. Los datos se publican bajo licencia CC BY 4.0: úsalos citando la fuente.

## Especificación OpenAPI

La especificación es OpenAPI 3.1 y se genera desde el mismo código que sirve los endpoints, así que no puede describir una ruta que ya no existe. Cada operación tiene `operationId` único, `summary`, `description`, parámetros tipados y un esquema de respuesta por código, que es justo lo que necesita un cliente de function calling para convertirla en herramientas.

- [/openapi.json](https://sgomez.dev/openapi.json) — Ubicación canónica.
- [/api/openapi.json](https://sgomez.dev/api/openapi.json) — El mismo documento bajo /api.
- [/api/openapi.yaml](https://sgomez.dev/api/openapi.yaml) — El mismo documento en YAML.

## Markdown para agentes

Las páginas de contenido se sirven en markdown cuando la petición lo pide, siguiendo la convención de acceptmarkdown.com. La URL canónica no cambia y la respuesta lleva `Vary: Accept`, para que una CDN no le dé a un agente la variante HTML que guardó para un navegador.

```bash
curl -s -H "Accept: text/markdown" https://sgomez.dev/about

# o, si prefieres una URL explícita:
curl -s https://sgomez.dev/about.md
```

Funciona en `/`, `/about`, `/contact`, `/privacy`, `/developers` y `/lab`. Las rutas que ya son markdown (`/llms.txt`, `/agents.md`) se sirven tal cual. Una ruta que no existe devuelve 404 con un cuerpo markdown que dice a dónde ir, en vez de una página de error que un agente no sabe leer.

## Ficheros para agentes

- [/llms.txt](https://sgomez.dev/llms.txt) — Resumen factual del sitio, con la sección «when to use this».
- [/agents.md](https://sgomez.dev/agents.md) — Instrucciones de uso: para qué sirve este sitio y cómo llamarlo.
- [/sitemap.xml](https://sgomez.dev/sitemap.xml) — Todas las URLs publicadas.
- [/robots.txt](https://sgomez.dev/robots.txt) — Crawlers de IA explícitamente permitidos.
- [/manifest.webmanifest](https://sgomez.dev/manifest.webmanifest) — Manifiesto de la aplicación web.

## Versionado

La versión va en la ruta (`/api/v1`). Dentro de v1 solo se añaden campos y endpoints: quitar un campo o renombrar un `operationId` sería un cambio incompatible y saldría en `/api/v2`. Los `code` de error forman parte del contrato y no se renombran.

---

Más formatos legibles por máquina: [llms.txt](https://sgomez.dev/llms.txt), [agents.md](https://sgomez.dev/agents.md), [OpenAPI](https://sgomez.dev/openapi.json), [sitemap](https://sgomez.dev/sitemap.xml).
