Saltar al contenido
Volver al blog
Ingeniería

Por qué construimos Projekt como API-first

El contrato OpenAPI es la fuente de verdad de Projekt. El panel, los SDKs y hasta los agentes de IA hablan exactamente el mismo idioma que la API.

Equipo Projekt

Autor

Cuando empezamos a diseñar Projekt tuvimos que decidir algo que parece técnico pero que en realidad es una apuesta de producto: ¿qué es la fuente de verdad? ¿el panel web, la base de datos, o la API? Elegimos la API. Todo lo demás —el panel, los SDKs, la app móvil, incluso los agentes de IA que hoy hablan con Projekt— es un cliente más de ese mismo contrato.

El contrato OpenAPI como fuente de verdad

Antes de escribir una sola línea de FastAPI, describimos el endpoint a mano en OpenAPI: la ruta, los parámetros, el esquema de entrada y el de salida, los códigos de error. Ese fichero vive en el repo, en packages/api-contract, y es lo primero que se revisa en cualquier pull request que toque la API. El backend no "decide" cómo responde; tiene que conformar ese contrato, y lo comprobamos con un check automático en cada build.

Esto invierte el orden habitual. En muchos productos la API es un efecto secundario del panel: alguien construye una pantalla, necesita un dato, y añade un endpoint ad hoc para traerlo. Con el tiempo eso genera decenas de rutas que solo sirven a una pantalla concreta, con formas de respuesta distintas y ningún criterio común. Nosotros hacemos el camino inverso: primero el recurso, con su forma estable y sus verbos HTTP correctos, y después la pantalla que lo consume.

Un panel que es exactamente la API

La consecuencia más visible para quien usa Projekt es que el panel no sabe nada que la API no sepa. Cada pantalla —proyectos, finanzas, CRM, personas— llama a los mismos endpoints que están documentados públicamente. No hay una ruta interna privilegiada ni un atajo que salte las reglas multi-tenant. Si algo es posible desde el panel, es posible con una llamada HTTP autenticada, y viceversa.

Esto tiene una ventaja práctica: cuando encontramos un caso raro en el panel, casi siempre es un síntoma de que el contrato tiene un hueco, no de que falte un parche en el frontend. Arreglamos el contrato, regeneramos el cliente, y el frontend se actualiza con tipos correctos automáticamente.

SDKs generados, no mantenidos a mano

Del contrato OpenAPI generamos un SDK en TypeScript con tipos exactos para cada recurso. Nuestro propio panel lo usa —no hacemos fetch manual en ningún sitio—, así que cualquier cambio incompatible en la API rompe el build del frontend antes de llegar a producción, no en tiempo de ejecución delante de un cliente real.

Esto también significa que quien construye sobre Projekt tiene acceso al mismo nivel de tipado que nuestro propio equipo. No existe una "API interna mejor" y una "API pública de segunda": es la misma.

Tokens personales y agentes: pjk_live_

Para integraciones, scripts o agentes de IA, cada organización puede emitir Personal Access Tokens con el prefijo pjk_live_. Se autentican con una cabecera Authorization: Bearer estándar y respetan exactamente los mismos roles y límites multi-tenant que un usuario humano con sesión iniciada:

curl https://api.projekt.3xa.es/api/v1/projects \
  -H "Authorization: Bearer pjk_live_xxxxxxxxxxxxxxxxxxxx"

MCP: que tu IA hable con Projekt

La consecuencia más reciente de esta apuesta es Projekt MCP: un servidor que expone la API como herramientas para agentes de IA. No es una integración paralela con su propia lógica de negocio: es el mismo contrato, empaquetado para que un agente pueda crear una tarea, consultar el estado de un sprint o registrar tiempo sin que nadie tenga que escribir un conector a medida.

Ser API-first no es una decisión que se tome una vez. Es una disciplina que se repite en cada pull request: si algo no está en el contrato, no existe. Nos obliga a diseñar los recursos con cuidado desde el principio, pero a cambio el panel, los SDKs, las integraciones y los agentes de IA nunca se desincronizan entre sí, porque literalmente no pueden: todos leen del mismo sitio.

Algunas cosas que esa disciplina nos ha dado, en la práctica:

  • Cero endpoints "fantasma" que solo existen para alimentar una pantalla concreta.
  • Errores con una forma predecible en todas las rutas, nunca un stacktrace filtrado al cliente.
  • Un SDK tipado que hace imposible llamar a un endpoint que ya no existe sin que el build lo detecte.
  • La misma autorización multi-tenant para el panel, los scripts con PAT y los agentes de IA.
  • Documentación que nunca se desactualiza, porque es literalmente el contrato que ejecuta el backend.

Si alguna vez te preguntas por qué Projekt tarda un poco más en enviar una función nueva, normalmente es esto: primero el contrato, después todo lo demás.