Skip to content

API Guide

The East Agile Tracker API is designed for agents as much as for humans. Everything you can do in the UI, you can do over the API — and a few things the UI doesn’t expose are there too.

This guide gets you from zero to “scripting your backlog” in under ten minutes. For the full endpoint reference, see API Specification.

You authenticate with an API key in the X-TrackerToken header. There are two kinds:

  • User keys (ea_user_…) — Act as you. Create them in Account Settings → API Keys. Use these for personal scripts, CLI tools, integrations.
  • Agent keys (ea_agent_…) — Act as a named agent in one project. Create them as a project owner in Project Settings → Agents. Use these for AI agents — Claude Code, Codex, your own — that should participate in the project as named teammates.

The differences:

User keyAgent key
ScopeAll your projectsOne specific project
Identity in audit logYour nameThe agent’s name
RoleYour role in each projectSet at key creation (viewer or member)
RevocationRevoke a key; you keep access via other keys/sessionsRevoke a key; the agent loses access immediately
Best forPersonal automation, scriptsAI agents that should be distinguishable from you in the history

Authorization: Bearer … also works if you prefer that header style.

Get your projects:

Terminal window
curl https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_TOKEN"

Or for an agent key, list the project it’s scoped to:

Terminal window
curl https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: ea_agent_xxxxx"

The API is JSON, REST-ish, versioned at /api/v1/. Same shapes for humans and agents.

Terminal window
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
}'

The response includes the project_id and any defaults the server applied (estimate scale, done state, etc.).

Terminal window
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"]
}'

The transition endpoint validates the requested move and returns the allowed next states on error:

Terminal window
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" }'

The field is to (not to_state). If the move is illegal — say you tried to skip from unstarted straight to accepted — the response is 422 invalid_transition with structured error details:

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

This is one of the small things that makes the API agent-friendly: an agent can read details.allowed and choose the right next move without scraping prose.

Terminal window
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." }'

The comment is attributed to whoever owns the API key — if it’s an agent key, the comment’s author is the agent.

Every write endpoint accepts an Idempotency-Key header. Retry the same key with the same body, get the same response back. Retry the same key with a different body, get a 409 idempotency_conflict:

Terminal window
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" }'

This is critical for agents in retry loops — crash mid-write, retry with the same key, no duplicate stories.

Move many stories at once. Each story is judged independently; one illegal move doesn’t fail the others.

Terminal window
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"
}'

For agents that want to react to what humans do, poll the events endpoint:

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

Response is a cursor-paginated stream of events with the actor, the resource, and the change. Each event has an ID; pass the last ID you saw as since to resume where you left off. No webhooks, no scraping, no missed events.

Terminal window
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/search?query=type:feature%20state:started%20label:mvp" \
-H "X-TrackerToken: $TRACKER_TOKEN"

Available filters:

FilterExampleDescription
type:type:featureFilter by story type
state:state:startedFilter by state
label:label:"my label"Filter by label
owner:owner:claireFilter by owner
requester:requester:tomasFilter by requestor
has:has:blockerStories with blockers
is:is:unestimatedUnestimated features

Free text matches the title and description. Combine filters by space-separating them — they’re AND’d.

The live OpenAPI 3 spec is at:

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

Swagger UI is at:

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

/openapi.json and /docs are unauthenticated — an agent can read the contract before it has a key. Once it holds a key, /api/v1/meta (which requires a valid key) returns its identity and the per-story-type transition graph; the reference-data lookups (/story_types, /story_states, /effort_scales) are also unauthenticated. Together they let agents answer “what can I do here?” without trial-and-error 403s.

Note: the served openapi.json lists paths but currently ships empty request bodies — use the field shapes in the Specification for writes.

For interactive automation — driving a logged-in browser session from a script, or remote-controlling the UI for tutorials — there’s a WebSocket channel:

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

Most users never need this; it’s there for the cases where REST isn’t enough.

If you’re scripting a bulk migration:

Terminal window
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"

Supported sources: pivotal, jira, asana, gitlab, shortcut, trello, linear, plane, plane_json.

All errors are JSON with at minimum:

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

Many error responses also include a details object — details.fields (an array of offending field names) on validation_failed, and details.allowed (alongside from/to) on 422 invalid_transition. Use them.

List endpoints accept limit and cursor. Cursor is opaque; pass the next_cursor from the previous response. Response headers also include X-Tracker-Pagination-Total for total counts where cheap to compute.