The issues timeline returns the history of status, assignee, sprint, estimates and other Agile fields of issues: the initial state, every change with its time and author, and the final state. Use it to calculate cycle time, lead time, throughput, cumulative flow, sprint scope changes or velocity in your own report. This is a PRO feature. The same data is available to AI clients, see Agile plugin and AI Agent integration.
The request needs the View issues permission. Only visible issues from projects with the Agile module enabled are returned. History is recorded since the Agile plugin 1.7.1 was installed; earlier changes are not restored, and changes made without a journal (direct SQL, imports) are not tracked.
Request
GET /agile/issues_timeline.json?issue_ids[]=45854&fields[status_id]=all&fields[assigned_to_id]=all GET /agile/issues_timeline.xml?issue_ids[]=45854
| Parameter | Description |
|---|---|
issue_ids[] |
up to 100 issue ids; invisible ids are skipped |
fields[NAME] |
fields to track: all, or a list of values (see below). Allowed: status_id, assigned_to_id, agile_sprint_id, story_points, estimated_hours, done_ratio, fixed_version_id, tracker_id, priority_id, category_id, parent_id, start_date, due_date. Default: status_id and assigned_to_id |
from, to |
window, dates in UTC; to defaults to today. Events are returned only inside the window, initial is the state at from |
mode |
events (default) or durations |
count_only |
1: only the total and the number of events per issue |
include[] |
sections of the answer, see below; by default all sections of the mode |
limit, offset |
paging over issues, default 20, maximum 100 |
Instead of issue_ids you can take every issue that was ever in a sprint: fields[agile_sprint_id][values][]=15. Only the sprint field supports this.
Events mode
Each journal is one event, all fields changed by it are inside. Times are in UTC. Ids are used in events, names are listed once in refs.
GET /agile/issues_timeline.json?issue_ids[]=45854&fields[status_id]=all&fields[assigned_to_id]=all&fields[agile_sprint_id]=all
{
"issues_timeline": {
"window": {"from": null, "to": "2026-10-15T09:00:00Z"},
"total": 1,
"has_more": false,
"refs": {
"statuses": [{"id": 1, "name": "New"}, {"id": 2, "name": "In Progress"}],
"users": [{"id": 4, "name": "Kirill Bezrukov"}],
"sprints": [{"id": 1, "name": "Sprint #1 (Oct 13 - Oct 16)"}]
},
"issues": [{
"id": 45854,
"created_on": "2026-10-14T18:30:11Z",
"initial": {"status_id": 1, "assigned_to": null, "sprint_id": null},
"events": [
{"at": "2026-10-14T20:26:20Z", "journal_id": 278915, "by": 4,
"sprint_id": {"from": null, "to": 1}},
{"at": "2026-10-15T06:06:40Z", "journal_id": 278964, "by": 4,
"status_id": {"from": 1, "to": 2}}
],
"final": {"status_id": 2, "assigned_to": {"id": 4, "type": "User"}, "sprint_id": 1}
}]
}
}
assigned_tois a user or a group (typeisUserorGroup); a group is never expanded to its members.sprint_idis the sprint of the issue. Withfields[agile_sprint_id][values][]you getsprint_memberinstead, with eventsenteredandleft.- The creation of an issue is not an event: its state is in
initial. nullmeans no value.
Durations mode
mode=durations returns seconds instead of events, in calendar time.
{
"id": 45854,
"span": {"from": "2026-10-14T18:30:11Z", "to": "2026-10-15T09:00:00Z", "seconds": 52189},
"in_status": [{"status_id": 1, "seconds": 41789}, {"status_id": 2, "seconds": 10400}],
"by_assignee": [{"seconds": 6882}, {"id": 4, "type": "User", "seconds": 45307}],
"in_status_by_assignee": [
{"status_id": 1, "seconds": 6882},
{"status_id": 1, "assignee": {"id": 4, "type": "User"}, "seconds": 34907},
{"status_id": 2, "assignee": {"id": 4, "type": "User"}, "seconds": 10400}
],
"transitions": [{"status_id": 1, "count": 0}, {"status_id": 2, "count": 1}],
"sprint_enters": 1
}
in_status,by_assigneeandin_status_by_assigneeeach add up tospan.seconds. An entry withoutidandtype(or withoutassignee) is time with nobody assigned.transitionscounts entries into each status inside the window.- There are no percentiles: take P50 or P85 over the per-issue values in your report.
Choosing sections
include[] trims the answer. Sections of events mode: initial, events, final, refs. Sections of durations mode: initial, span, in_status, by_assignee, in_status_by_assignee, transitions, sprint_enters, final, refs. Issue id, created_on, window, total, has_more and next_offset are always present. A section of the other mode, an unknown section or include together with count_only is an error.
Count only
GET /agile/issues_timeline.json?issue_ids[]=45854&count_only=1
{"issues_timeline": {"total": 1, "issues": [{"id": 45854, "events": 3}]}}
Limits and errors
- 20 issues per page by default, 100 at most. Use
has_moreandnext_offsetfor the next page. - The number of events in one response is capped; the response stops at an issue boundary and sets
has_more. Narrow the window or the selection if you get the error "narrow the window or the selection". - A wrong argument gives
422 Unprocessable Entitywith{"errors": ["message"]}.
See also REST API Agile Sprint and REST API Agile data.