Ir al contenido

Guía de la API

La API de East Agile Tracker está diseñada tanto para agentes como para personas. Todo lo que puedes hacer en la UI lo puedes hacer por la API — y unas cuantas cosas que la UI no expone también están ahí.

Esta guía te lleva de cero a “scriptear tu backlog” en menos de diez minutos. Para la referencia completa de endpoints, consulta la Especificación de la API.

Te autenticas con una clave en la cabecera X-TrackerToken. Hay dos tipos de clave que emites tú mismo, y un tercero que un cliente MCP obtiene por ti:

  • Claves de usuario (ea_user_…) — Actúan como . Créalas en Configuración de la cuenta → Claves de API. Úsalas para scripts personales, herramientas de CLI, integraciones.
  • Claves de agente (ea_agent_…) — Actúan como un agente con nombre en un proyecto. Créalas en Configuración del proyecto → Agentes. Úsalas para agentes de IA — Claude Code, Codex, el tuyo propio — que deban participar en el proyecto como compañeros de equipo con nombre.
  • Tokens MCP (ea_mcp_…) — Tokens de acceso OAuth 2.1 emitidos a un cliente MCP (Claude, un IDE) después de que lo apruebes en la página de consentimiento. Actúan como tú, y puedes revocarlos en Configuración de la cuenta → Aplicaciones conectadas.

El diálogo de una sola vez tras crear una clave de API personal en la configuración de la cuenta, con la clave oculta en esta captura

El formulario para crear claves de la pestaña Agent con un nombre y el rol member elegido, bajo las instrucciones de configuración

Las diferencias entre las dos que emites tú:

Clave de usuarioClave de agente
AlcanceTodos tus proyectosUn proyecto específico
Identidad en el registro de auditoríaTu nombreEl nombre del agente
RolTu rol en cada proyectoEstablecido al crear la clave (viewer, member o manager — nunca por encima del rol del propio miembro que la emite)
RevocaciónRevoca una clave; conservas el acceso mediante otras claves/sesionesRevoca o rota una clave; el agente pierde el acceso de inmediato
Ideal paraAutomatización personal, scriptsAgentes de IA que deban distinguirse de ti en el historial

Authorization: Bearer … también funciona si prefieres ese estilo de cabecera.

Obtén tus proyectos:

Ventana de terminal
curl https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_TOKEN"

O, para una clave de agente, lista el proyecto al que está limitada:

Ventana de terminal
curl https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: ea_agent_xxxxx"

La API es JSON, de estilo REST, versionada en /api/v1/. Las mismas formas para personas y agentes.

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Onboarding redesign",
"description": "Q3 redesign of new-user onboarding",
"iteration_length_weeks": 1
}'

La respuesta incluye el project_id y cualquier valor por defecto que el servidor haya aplicado (escala de estimación, estado de finalización, etc.).

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Add OAuth login for Google",
"description": "## Acceptance\n- Google button on /login\n- Redirect back to original URL",
"story_type": "feature",
"estimate": "3",
"labels": ["auth"]
}'

estimate es la etiqueta del valor de la escala como cadena — "3", o "13" en la escala de Fibonacci — porque tiene que coincidir con un punto de la escala del proyecto. Un número JSON se rechaza.

Mover una historia a lo largo de su ciclo de vida

Sección titulada «Mover una historia a lo largo de su ciclo de vida»

El endpoint de transición valida el movimiento solicitado y, en caso de error, devuelve los estados siguientes permitidos:

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/transitions \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "to": "started" }'

El campo es to (no to_state). Si el movimiento es ilegal — por ejemplo, si intentaste saltar de unstarted directamente a accepted — la respuesta es 422 invalid_transition con detalles de error estructurados:

{
"code": "invalid_transition",
"error": "Cannot move story from `unstarted` to `accepted`",
"details": { "from": "unstarted", "to": "accepted", "allowed": ["started"] }
}

Esta es una de las pequeñas cosas que hacen la API amigable para agentes: un agente puede leer details.allowed y elegir el siguiente movimiento correcto sin tener que rastrear texto.

rejected es terminal para el endpoint de transición. Para devolver al trabajo una historia rechazada, POST …/stories/{sid}/restart; POST …/stories/{sid}/reject es la forma verbal de rechazar una historia entregada.

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/comments \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "text": "Investigation done. Picking this up." }'

El comentario se atribuye a quien sea el propietario de la clave de API — si es una clave de agente, el autor del comentario es el agente.

Cada endpoint de escritura acepta una cabecera Idempotency-Key. Reintenta con la misma clave y el mismo cuerpo, y obtienes la misma respuesta. Reintenta con la misma clave y un cuerpo distinto, y obtienes un 409 idempotency_conflict:

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "name": "Refactor auth middleware", "story_type": "chore" }'

Esto es crítico para agentes en bucles de reintento — si se caen a mitad de una escritura, reintentan con la misma clave y no hay historias duplicadas.

Mueve muchas historias a la vez. Cada historia se evalúa de forma independiente; un movimiento ilegal no hace fallar a las demás.

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/bulk_transition \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"story_ids": [101, 102, 103],
"to": "delivered"
}'

Para agentes que quieran reaccionar a lo que hacen las personas, sondea el endpoint de eventos:

Ventana de terminal
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/events?since=$LAST_CURSOR&types=story.created,story.transitioned,comment.added" \
-H "X-TrackerToken: $TRACKER_TOKEN"

La respuesta es un flujo de eventos paginado por cursor con el actor, el recurso y el cambio. Cada evento tiene un ID; pasa el último ID que viste como since para retomar donde lo dejaste. Sin webhooks, sin scraping, sin eventos perdidos. El flujo exige el rol member — un viewer recibe 403.

GET /projects/{id}/search?q=<query> ejecuta una potente búsqueda de texto completo + estructurada sobre las historias del proyecto. El lenguaje de consulta está modelado sobre los calificadores de búsqueda de issues de GitHub — así que la sintaxis que tú (o un agente de IA) ya conocéis de GitHub se traslada casi por completo.

Ventana de terminal
curl -G "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/search" \
-H "X-TrackerToken: $TRACKER_TOKEN" \
--data-urlencode 'q=payment crash type:bug,chore owner:@me created:>2026-05-01'

La respuesta es un sobre JSON con las historias ordenadas por relevancia:

{ "results": [ /* canonical story objects */ ], "total": 42, "limit": 50, "offset": 0 }

total es el número total de coincidencias, no el tamaño de la página. Pagina con limit (50 por defecto, máx. 1000) y offset; ordena con sort=relevance (por defecto), created, created_asc, updated o state.

  • El texto libre coincide con el título, la referencia y la descripción de una historia (texto completo, con lematización y ranking). Encierra una frase exacta entre "comillas".
  • Los calificadores son field:value. Separa alternativas con comas (OR dentro de un campo): type:bug,chore. Separa calificadores con espacios (AND entre ellos).
  • Niega cualquier término o calificador con un - inicial: -label:wontfix.
  • Rangos para fechas y puntos: inclusivo a..b, o abierto >x / <x.
CalificadorEjemploCoincide con
type:type:bug,choretipo(s) de historia
state:state:started,finishedestado(s) del flujo de trabajo
label:label:"my label"una etiqueta
epic:epic:"Checkout"historias de un epic
priority:priority:p1prioridad
points:points:3 · points:1..5 · points:>3valor o rango de estimación
iteration:iteration:42id de iteración
created: updated: started: completed: release:created:2026-05-01..2026-06-01 · updated:>2026-06-01una fecha o un rango (granularidad de día); release: es la fecha de release de la historia
owner: requester: follower: reviewer: commenter: mention:owner:claire · owner:@meuna persona por nombre o correo electrónico — miembros y agentes, mention: incluido; @me eres tú
has:blockerhas:blockertiene un bloqueador abierto
is:is:unestimated · is:icebox · is:backlog · is:blockedun indicador

mywork: es un alias de owner:mywork:me es owner:@me. El antiguo calificador scheduled: está retirado y se ignora en silencio; usa release:.

El OR por comas (type:bug,chore) se aplica a los calificadores de faceta; los calificadores de personas (owner: requester: follower: reviewer: commenter: mention:) toman un único valor.

payment crash texto completo "payment" Y "crash"
"exact phrase" una frase
type:bug,chore state:started bugs o chores que estén started
owner:@me -label:wontfix los míos, excluyendo la etiqueta wontfix
points:3..8 created:2026-05-01..2026-06-01 estimadas 3-8, creadas en mayo
follower:tomas has:blocker tomas la sigue y está bloqueada
is:backlog updated:>2026-06-01 elementos del backlog tocados desde el 1 de junio

La misma cadena de consulta alimenta el cuadro de búsqueda del tablero (que abre una columna de resultados en vivo) y esta API — una sola gramática para personas y agentes por igual. Buscar en el contenido de comentarios, tareas y bloqueadores está en la hoja de ruta; hoy el texto libre cubre el título, la referencia y la descripción de la propia historia.

La especificación OpenAPI 3 en vivo está en:

https://api.eastagiletracker.com/api/v1/openapi.json

Swagger UI está en:

https://api.eastagiletracker.com/api/v1/docs/

/openapi.json y /docs no requieren autenticación — un agente puede leer el contrato antes de tener una clave. Una vez que tiene una clave, /api/v1/meta (que requiere una clave válida) devuelve su identidad y el grafo de transiciones por tipo de historia; las consultas de datos de referencia (/story_types, /story_states, /effort_scales, /priority_scales) tampoco requieren autenticación. En conjunto, permiten a los agentes responder “¿qué puedo hacer aquí?” sin 403s de prueba y error.

El openapi.json servido lleva los esquemas de cuerpo de petición de los endpoints de escritura, incluido el maxLength de cada campo, de modo que un cliente puede validar antes de enviar. La Especificación resume esas mismas formas.

Para automatización interactiva — controlar una sesión de navegador con sesión iniciada desde un script, o controlar la UI de forma remota para tutoriales — hay un canal WebSocket:

const ws = new WebSocket('wss://eastagiletracker.com/ws/control?token=SESSION_JWT')
ws.send(JSON.stringify({ action: 'get_state', id: 'req-1' }))

El token es el JWT de la sesión del navegador, no una clave de API — una clave ea_user_* o ea_agent_* se rechaza antes del upgrade. La mayoría de los usuarios nunca necesitan esto; está ahí para los casos en que REST no es suficiente.

Si estás scripteando una migración masiva:

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-F "source=pivotal" \
-F "file=@pivotal_export.csv"

Fuentes de archivo admitidas: pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json, eat (la exportación propia de East Agile Tracker — el formato de ida y vuelta). El endpoint multipart se ejecuta de forma síncrona y responde con los recuentos de resultado.

GitHub importa desde la API en lugar de un archivo, a través del endpoint JSON — sin file, solo las coordenadas del repositorio:

Ventana de terminal
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import/json \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": "github",
"owner": "octocat",
"repo": "hello-world",
"token": "ghp_…",
"include_pull_requests": false,
"include_milestones": false,
"include_releases": false,
"include_dependencies": false
}'

El endpoint JSON es asíncrono: responde 202 con { "import_id", "status" } y sondeas GET /projects/{id}/imports/{import_id} hasta que el trabajo llega a done o failed. Solo se ejecuta una importación por proyecto a la vez — una segunda llamada mientras hay una en curso es 409 import_already_running. El bucle completo, con los campos de progreso del trabajo, está en Poblar un proyecto desde un repositorio de GitHub.

El token es opcional en la petición, pero la descarga siempre se autentica: va por la API GraphQL de GitHub, que no tiene nivel anónimo. Omite token y el servidor pone su token de plataforma: solo repositorios públicos, compartido por todos los llamantes y rechazado con import_github_shared_quota_low cuando su presupuesto GraphQL baja de 500 puntos. Un repositorio privado, o un despliegue que no configuró ningún token de plataforma (import_github_no_token), exige el tuyo. Sea cual sea el token que se use, sirve únicamente para las llamadas ascendentes a GitHub y nunca se almacena ni se devuelve. El detalle completo, incluido el techo REST sin autenticar de 60 peticiones de GitHub, está en Poblar un proyecto desde un repositorio de GitHub.

Vista previa en seco (dry-run). Añade "dry_run": true (JSON) o -F "dry_run=true" (multipart) a cualquier fuente. La importación analiza, resuelve y de-duplica exactamente igual que una ejecución real, produce los mismos recuentos de resultado (imported, skipped, errors, unmatched) y luego revierte todo — no se escribe nada. En el endpoint JSON los recuentos llegan en el trabajo sondeado, sea o no una ejecución en seco.

Límites. El cuerpo de una subida está limitado a 10 MiB, y una sola importación a 5.000 historias; superar cualquiera de los dos es un 400 sin escribir nada. Reimportar un archivo es seguro — las filas ya importadas (identificadas por el id de origen) se saltan, no se duplican.

Cualquier rol del proyecto puede listar los formatos; descargar uno es solo para owners:

Ventana de terminal
# Los formatos de exportación registrados: { id, name, content_type, drops, includes_archived }
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/formats \
-H "X-TrackerToken: $TRACKER_TOKEN"
# Descargar un formato (eat es el CSV de ida y vuelta de fidelidad completa)
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/export/eat \
-H "X-TrackerToken: $TRACKER_TOKEN" -o project-export.csv

Ids de formato de intercambio: eat, jira, pivotal, shortcut, trello, asana, gitlab, linear, plane, plane_json, más los formatos de documento pdf y docx. Todos los adjuntos se pueden descargar como un único zip desde GET /projects/{id}/export/attachments.

Todos los errores son JSON con, como mínimo:

{
"code": "invalid_transition",
"error": "Cannot move story from `unstarted` to `accepted`"
}

Muchas respuestas de error también incluyen un objeto detailsdetails.fields (un array de nombres de campos infractores) en validation_failed, y details.allowed (junto a from/to) en 422 invalid_transition. Úsalos. Un 429 rate_limited lleva una cabecera Retry-After dentro del mismo sobre JSON.

Los endpoints de listado aceptan limit y cursor. El cursor es opaco; pasa el next_cursor de la respuesta anterior. El tope de limit es por endpoint — 200 en historias, comentarios y proyectos, 500 en eventos, 1000 en la búsqueda y el registro de auditoría. Un listado simple (sin cursor) que haya tenido que truncar su respuesta lo indica en cabeceras: X-Tracker-Pagination-Truncated, -Limit, -Offset y -Next-Offset, que devuelves como offset= para la página siguiente. No hay cabecera de total.