Work items
- File a work item
- Find the work items you need
- See one work item
- Track your own work
- Change a work item
- Assign someone
- Define the labels a team uses
- Put a label on a work item
- Plan a milestone
- Put work in a milestone and track it
- Break work down into a hierarchy
- See how an epic is tracking
- Record that one item blocks another
- Close a work item
- Reopen a work item
- Move a work item to another repository or group
- Delete a work item
- Change the statuses and automation a container uses
- Go back to inheriting
Overview
A work item is one piece of work — a bug, a story, a task, an epic — filed against a repository or a group, tracked through a status you name, and connected to the code that changes it. You file items, triage them into a status, assign them to people, group them under an epic, label them, put them in a milestone, and close them when the work lands. Because the tracker lives in the same place as the code, an item can be closed by a commit, moved by a merge, and reopened when the test that proved it fixed goes red again.
Everything on this page is available three ways: in the web app, from the gitmoap command line, and over the API — so a triage rota, a backlog import or a bot that files an item per alert is a script, not a browser session.
Quick start
File an issue
Start at Issues in the side navigation.
Choose New issue.
Pick a type, give it a title, and describe the work. Assignees, labels and a milestone are optional.
Choose Create issue. It opens at its number, which a commit message can name as
#followed by that number.
Define your labels
Start at Labels in the side navigation.
Choose New label.
Give it a key and a colour. A key like
priority::highmakes a scoped label — an issue carries at most one label per prefix.Choose Create label, then apply it from any issue's side panel.
Plan a milestone
Start at Milestones in the side navigation.
Choose New milestone.
Give it a title and a due date.
Choose Create milestone, then put issues in it from their side panel. Its progress fills in as they close.
Before you start
- A repository or a group you can read.Reading work items follows the container's visibility: a public repository answers anyone, an internal one answers anyone signed in, and a private one answers only members at Reporter or above. A private container answers
404rather than403, so its existence stays private. - Reporter access to file and comment.Filing is deliberately the cheapest thing a member can do. It is not covered by the public-read shortcut: someone who can read a public repository but is not a member of it cannot file on it. A container can opt into public filing, which lets any signed-in person file on it — and only on a container whose visibility is Public.
- Developer access to change work that is not yours.Setting a status, assigning, labelling, reparenting and relating are Developer. The one exception is the item's own reporter, who may edit and close their own item at Reporter — and anybody may unassign themselves at Reporter.
- Maintainer access to delete or move an item, and to mint labels, milestones and workflow settings. Deleting destroys a discussion and an activity trail, so it sits a level above closing.
- A token with the right scopes, if you are scripting:
issue:readto read work items, labels and milestones,issue:createto file,issue:updateto change one,issue:deleteto delete or move,label:manageandmilestone:manageto define the vocabulary, andissue_settings:read/issue_settings:managefor the workflow. A token carries the scopes you chose when you minted it and they cannot be added afterwards. - A milestone or label must exist before you can apply it.Both are defined per container; a work item may only take a milestone its own container defines, and a label its container or an ancestor group defines. Defining either is Maintainer; applying one is Developer.
How it works
One shape, eight types
There is one kind of thing here — a work item — and its type decides where it may live, what it may contain, and which fields apply to it. An epic is not a separate product with its own screens; it is a work item whose type is epic.
Every type takes a title, a description, assignees, labels and relations. All but an epic also take acceptance criteria; all but a sub-task also take a milestone. The rest is the type table:
| Type | Lives in | May hold | Can it have a parent? | Fields on top of the common set |
|---|---|---|---|---|
epic | a group | epic, story, bug, task, incident | yes | — |
story | a repository | task | yes | points, code anchors |
bug | a repository | task | yes | severity, code anchors |
task | a repository | — | yes | — |
spike | a repository | — | no | — |
chore | a repository | — | no | — |
incident | a repository or a group | task | yes | severity |
sub_task | a repository | — | no | — |
Three consequences catch people out. An epic can only live in a group, which is exactly why it can gather work from several repositories under it. A field the type does not declare is refused, not ignored — setting points on a bug is a 400 rather than a value silently dropped, so a broken script fails on its first call instead of on the day someone notices the number never arrived. And hierarchy is checked from both ends: spike, chore and sub_task are leaves that sit outside the tree entirely, so they take no children and cannot be given a parent.
Where an item lives, and what it is called
An item lives in a container: a repository or a group. Every task below therefore has two forms — one under /repositories/{repo_id}/… and a twin under /groups/{group_id}/… — and they behave identically apart from which types are legal there.
Its name is a number that counts within that container: #412 in one repository and #412 in another are different items, and &17 in a group is an epic. Numbers are allocated in order but gaps are normal — a deleted item leaves its number behind, so #412 never means "the 412th item filed". Moving an item to another container re-numbers it there; the response tells you the old and new names.
Status: the name you choose, the category we understand
A status has a name, which your team owns, and a category, which the platform owns. There are seven categories and they never change:
| Category | Open? | What it means |
|---|---|---|
triage | yes | filed, awaiting acceptance — where new items land by default |
todo | yes | accepted, not started |
in_progress | yes | being worked; where a branch naming the item moves it |
in_review | yes | under review; where an open merge request naming the item moves it |
blocked | yes | a human's assertion that this is stuck |
done | no | completed |
cancelled | no | closed without completing — won't fix, duplicate, obsolete |
Rename "In Review" to "Ready for QA" and nothing breaks: boards still column it, a merge still drives it, and a rollup still counts it as not-done, because the platform reads the category and never the name. done and cancelled both close an item and only done completes it — a backlog cleared by mass-cancelling stale tickets must not look like a backlog cleared by doing the work.
A container may also constrain which categories may follow which. By default any status may move to any status, which is the setting most teams should keep.
Hierarchy and relations are different things
Hierarchy is containment — an epic contains stories, a story contains tasks. One parent, nesting capped at five levels, and cycles are impossible because the check walks the real parent links every time rather than a cached copy of them. Detaching has nothing structural to check, because it can only reduce depth.
Relations are dependencies and cross-references between peers — blocks, blocked_by, relates_to, duplicates. A relation is written on both items at once, so it can never half-exist, and it may cross containers freely. Nothing checks a relation for cycles: A blocks B blocks C blocks A is a real transient state during a refactor, so it is accepted. Be aware of what that costs while the blocker gate is on — two items that block each other cannot both be completed, and you break the deadlock by cancelling one, removing the relation, or turning the gate off for the container.
blocked the status and blocked_by the relation are deliberately not kept in sync. One is a human saying "I am stuck"; the other is a structural fact about which item has to land first.
Every change carries the version you read
A work item is edited by people and by the platform at the same time — a merge moves its status, a pipeline verifies its criteria, a commit message closes it. So an update names the version you read, and a mismatch is a 409 carrying the current state instead of a silently clobbered field. Re-read, re-apply, retry.
Settings are inherited from the group chain
Statuses, transitions, automation rules and defaults are configured per container and inherited field by field: for each setting, the nearest ancestor group that sets it wins, and anything nobody sets falls back to the platform default. A repository's own saved values count only while its Override group settings switch is on — with it off, the whole policy comes from the groups above, and the values the repository has stored sit dormant. The switch cuts the other way too: a group that turns its own switch on ends the walk there, so nothing below it can override what it sets.
Reading a repository's issue settings gives you the resolved answer; reading a group's gives you what that group itself stores. Removing a container's settings puts it back to full inheritance rather than resetting it to platform defaults.
How to
File a work item
Give it a title and a type. Everything else is optional: a description, a status, assignees, labels, a milestone, points, a severity, and a parent. Leave the type out and the container's configured default type is used, which starts life as Task; leave the status out and it lands in the status the container marks as the default for new work, which starts life as Triage.
Open the repository and choose Issues in the side navigation, then New issue. Pick a type from the selector at the top — the choices are the ones legal in a repository — give it a title, and write the description in the markdown editor. The right-hand panel sets assignees, labels, a milestone and, where the type declares them, points and severity. Create opens the new item at its number.
gitmoap issues create --repo-id <id> --title <title>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "<string>" }'The title is 1–255 characters and cannot be blank; the description is markdown up to 128 KiB. The milestone must already exist in this container, and every label you name must already be defined here or in a group above it — a key nothing defines is dropped on the way in, so although the create response echoes it back the item comes back without it on the very next read. Define the label first. If you name a parent, the parent's type has to accept this type and this type has to be one that takes a parent at all: an epic accepts almost anything, a story or a bug accepts tasks, and a spike, a chore and a sub-task neither hold children nor hang under anything.
Filing in a group works the same way and is where epics go:
Open the group and choose Issues, then New issue. The type selector offers the group-legal types — Epic and Incident. An epic filed here can then adopt work from any repository beneath the group.
gitmoap issues create-group --group-id <id> --title <title>curl -X POST https://api.gitmoap.example/groups/{group_id}/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "<string>" }'Find the work items you need
The listing is newest-updated first and filters on status category, named status, type, assignee, label, milestone and free text. The filters combine, and the free-text search matches words in the title and the description as well as substrings of the title. Paging is by cursor: keep handing the next_token you were given back. A cursor is a position in the ordering, not a saved query — it carries no memory of the filters that produced it, so changing a filter mid-walk resumes at that position under the new filter rather than failing, and quietly skips whatever the new filter would have matched earlier. Start again from the first page instead.
Open the repository and choose Issues. The filter bar across the top carries the status, type, assignee, label and milestone pickers and a search box; the state of the bar is in the page URL, so a filtered view is a link you can send to somebody. Switch between the compact list and the card view with the toggle at the right.
gitmoap issues list --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN"The card view returns the same items enriched for display — the author and assignees with their avatars, the labels with their colours, the milestone, the comment count, the child counts and points, the verification state, and how many open items are blocking each one. Cards cost more per row, but they page exactly as the plain listing does: twenty at a time to a maximum of a hundred. The four filtered work-item listings — a repository's, a group's and the two personal ones — each have a card twin taking exactly the same filters. Reach for the plain form when you are scripting and the card form when you are drawing a board or a backlog.
The Board and Backlog views of a repository's Issues page are the card listing. Each card carries the assignees, the labels in their colours, the milestone, the points, the child progress and a blocked marker, so a triage session needs no drilling in.
gitmoap issues list-cards --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/issues/cards \ -H "Authorization: Bearer $GITMOAP_TOKEN"A group listing spans the group's whole subtree — the items the group itself holds plus the work items of every repository and subgroup beneath it — and is the view to reach for when you want "every open bug in the org". Ask for scope=own instead to see only what the group itself holds.
Open the group and choose Issues. The list spans every repository and subgroup beneath this group, with each row labelled by where it came from; the This group only toggle narrows it to the items the group itself holds. Rows from repositories you cannot read are not shown at all.
gitmoap issues list-group --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN"See one work item
Open Issues and choose a row, or go straight to the item by typing its number into the search box. The item page shows the description and discussion on the left, and status, assignees, labels, milestone, parent, relations and points on the right.
gitmoap issues get --repo-id <id> --issue-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Track your own work
Two self-scoped listings need no container at all: what is assigned to you, and what you filed. Both span every repository and group you can reach, and both take the same status, type, label, milestone and free-text filters a container listing does. Both need a signed-in credential — they are keyed on who you are, so there is no anonymous form of them even for public repositories.
The My work entry in the top navigation opens the items assigned to you across everything, newest-updated first. Both have card views.
gitmoap issues list-mycurl -X GET https://api.gitmoap.example/user/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN"The Reported by me tab beside My work is everything you filed, wherever you filed it. It is the list to check before filing again, and the one that shows what happened to a report you made months ago in a repository you have since stopped watching.
gitmoap issues list-my-reportedcurl -X GET https://api.gitmoap.example/user/reported-issues \ -H "Authorization: Bearer $GITMOAP_TOKEN"Rows are checked one repository at a time, not one container at a time. If your access to a repository is removed, its items leave these lists on the next read even though the assignment row is still there — which is the behaviour you want, and the reason a listing that spans containers is never trusted to the container's own verdict.
Change a work item
Send only the fields you are changing, plus the version you read — the version is not optional, and a body with no field in it at all is a 400. A title, description, status, milestone, points, severity and type can all move in one call. Assignees, labels, the parent and relations are not part of this call; each has its own action below.
Open the item. Title and description edit in place with the pencil icon; status, milestone, points and severity are pickers in the right-hand panel and save as you change them. The page reloads the item if somebody else has changed it while you were typing, and tells you so rather than overwriting them.
gitmoap issues update --repo-id <id> --issue-id <id> --version <n>curl -X PATCH https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "version": "<int64>" }'Changing the type is not a rename. It re-checks everything the type governs: the container it is allowed in, the fields it declares, the parent it has, and the children it holds. Retyping a task that holds sub-tasks into a spike is refused, because a spike can hold nothing — detach the children first, then retype. Clearing a field is always allowed, so a type change can shed a field the new type does not have.
Changing the status is subject to whatever transition constraints the container declares. By default there are none.
Assign someone
Assignees are users or service accounts, and they must be members of the container — assigning somebody who is not is a 409, because work assigned to a person who cannot open it presents as a person ignoring their queue. Reading a public repository is not enough; real membership is what the check asks for. A work item carries at most five assignees, and the sixth is refused with a 400 rather than silently dropped. Assigning somebody who is already on the item changes nothing and is not an error.
Open the item and use the Assignees picker in the right-hand panel. It searches the container's members; picking one assigns immediately.
gitmoap issues add-assignee \ --repo-id <id> \ --issue-id <id> \ --principal-id <principal id>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/assignees \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "principal_id": "<uuid>" }'Unassigning is the mirror, and it is the one write anybody can do to themselves without Developer access: if a work item lands on you and is not yours, you can take yourself off it.
Open the item, open the Assignees picker, and clear the person from the list. Your own name always has a Remove me action, whatever your access level.
gitmoap issues remove-assignee \ --repo-id <id> \ --issue-id <id> \ --principal-id <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/assignees/{principal_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Define the labels a team uses
A label is defined once per container and applied many times. The key is its identity and is fixed; the colour and description are the only two things an edit can change. A key is 1–64 characters of lowercase letters, digits and hyphens, starts with a letter or a digit, and may carry one :: separator — and that separator is the useful part. The colour is a six-digit hex triple such as #d73a4a.
A key with a :: is scoped: priority::low, priority::medium, priority::high all share the prefix priority, and a work item may carry at most one label per prefix. Applying priority::high to an item already carrying priority::low replaces it in one step; the item is never briefly unprioritised and never carries two. That turns a bag of free-form strings into a field with a domain, without anybody configuring a custom field.
Open the repository, choose Issues then Labels, and use New label. Give it a key, pick a colour and add a description. Use area::payments style keys when you want the label to behave like a single-choice field.
gitmoap issues create-label --repo-id <id> --color <color> --key <key>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/labels \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "color": "<string>", "key": "<string>" }'Labels defined on a group are visible to every repository beneath it, so an org-wide priority::high is defined once at the top. A repository may define the same key to override its colour locally — the nearer definition wins when the label is applied. A key that already exists in the same container is a 409; edit that one instead.
Open Issues then Labels. The list is the labels this container itself defines, ordered by key — a group's labels are read from the group, not echoed here, so check the group's own Labels page for the inherited vocabulary. The search box narrows by key and description.
gitmoap issues list-labels --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/labels \ -H "Authorization: Bearer $GITMOAP_TOKEN"Changing how a label looks is one edit and touches nothing else:
Open Issues then Labels, and choose the pencil on the label's row. Colour and description are editable; the key is shown but fixed, because it is what every work item carrying the label refers to.
gitmoap issues update-label --repo-id <id> --label-key <id>curl -X PATCH https://api.gitmoap.example/repositories/{repo_id}/labels/{label_key} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Warning
Deleting a label takes it off every work item that carries it, everywhere in the container and — for a group label — in every repository beneath it. Nothing is archived and nothing can be undone from Gitmoap: re-creating a label with the same key gives you an empty label, not the items back. There is no way to hide a label without deleting it, so retire an unwanted one by agreeing to stop applying it rather than by removing it from live work.
Open Issues then Labels, and choose the bin on the label's row. Confirm the deletion; the label comes off every item that carries it.
gitmoap issues delete-label --repo-id <id> --label-key <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/labels/{label_key} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Every work item carrying one of a container's own labels is one call, and a key the container does not itself define answers 404 rather than an empty list, so a typo does not read as an unused label:
Choose a label chip anywhere it appears, or open Issues then Labels and choose the label's row. To do the same for a group label, ask the group that defines it rather than a repository beneath it.
gitmoap issues list-by-label --repo-id <id> --label-key <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/labels/{label_key}/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN"Put a label on a work item
Open the item and use the Labels picker in the right-hand panel. It offers the container's labels plus the inherited ones; choosing a scoped label swaps out whichever sibling was there.
gitmoap issues add-label --repo-id <id> --issue-id <id> --key <key>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/labels \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "key": "<string>" }'A work item carries at most ten labels. The label has to be defined in the container or in a group above it — an undefined key is a 400, not a new label, because minting label vocabulary is a Maintainer's decision and applying it is a Developer's.
Open the item and clear the chip from the Labels picker, or use the small × on the label chip itself.
gitmoap issues remove-label --repo-id <id> --issue-id <id> --label-key <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/labels/{label_key} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Taking off a label the item does not carry is not an error — the item comes back unchanged — so a cleanup script does not have to read the item first to know whether the call is safe.
Plan a milestone
A milestone is a dated commitment inside one container: a title, an optional description and an optional due date, which is a calendar day such as 2026-09-23 with no time or time zone. Titles are unique within the container, so a second milestone called "Q3" in the same repository is a 409.
Open the repository, choose Issues then Milestones, and use New milestone. Give it a title and a due date. A group milestone is created the same way from the group's own Milestones page.
gitmoap issues create-milestone --repo-id <id> --title <title>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/milestones \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "<string>" }'The container's milestones are one call, newest created first, open and closed alike, with a search fragment that matches the title and the description:
Open Issues then Milestones. Closed milestones stay on the list, so what shipped in the last one is still readable.
gitmoap issues list-milestones --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/milestones \ -H "Authorization: Bearer $GITMOAP_TOKEN"Closing a milestone is an ordinary edit — set it closed — and it does not touch the work items in it. What it does do is stop new work being added: putting an item into a closed milestone is refused.
Open Issues then Milestones and choose the milestone. Title, description and due date edit in place; Close milestone at the bottom of the panel sets its state without moving any of its work.
gitmoap issues update-milestone --repo-id <id> --milestone-id <id>curl -X PATCH https://api.gitmoap.example/repositories/{repo_id}/milestones/{milestone_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Warning
Deleting a milestone takes every work item out of it. The items themselves survive — only the association is destroyed, and there is no undo. Close the milestone instead when you want it out of the way but still want to be able to read what shipped in it.
Open Issues then Milestones, and choose the bin on the milestone's row, then confirm. Every item in the milestone is taken out of it as part of the delete.
gitmoap issues delete-milestone --repo-id <id> --milestone-id <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/milestones/{milestone_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Put work in a milestone and track it
A work item may only join a milestone its own container defines — a repository item takes a repository milestone, a group epic takes that group's milestone. Naming a milestone from somewhere else answers 404, because a milestone that could not read its own members would report progress that was quietly missing them. A sub-task takes no milestone at all.
Open the item and use the Milestone picker in the right-hand panel. Only the current container's open milestones are offered.
gitmoap issues set-milestone \ --repo-id <id> \ --issue-id <id> \ --milestone-id <milestone id>curl -X PUT https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/milestone \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "milestone_id": "<uuid>" }'Open the item and clear the Milestone picker.
gitmoap issues remove-milestone --repo-id <id> --issue-id <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/milestone \ -H "Authorization: Bearer $GITMOAP_TOKEN"Reading a milestone gives you its progress computed from the live work items in it, not from a stored counter: the total, how many are open, how many completed and how many cancelled, and the points completed against the points total. There is no snapshot to go stale, and two people with different access legitimately see different numbers, because the figures only count the items each of them may see.
Open Issues then Milestones and choose the milestone. The header carries the counts and the points figure; the list below it is its work items.
gitmoap issues get-milestone --repo-id <id> --milestone-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/milestones/{milestone_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"The milestone's work items are also a listing of their own. It takes no filters and no paging — it returns every item in the milestone in one response, so a milestone holding thousands of items answers with a large body. To filter, order or page them, use the milestone filter on the ordinary work-item listing instead.
The work items in a milestone are the list on the milestone's own page, and the Milestone filter on the main Issues list gives you the same set inside the filter bar you already know.
gitmoap issues list-milestone --repo-id <id> --milestone-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/milestones/{milestone_id}/issues \ -H "Authorization: Bearer $GITMOAP_TOKEN"Break work down into a hierarchy
Set a parent and the item becomes its child. The parent may be in another container — an epic in a group adopting a story in a repository is the whole reason the hierarchy is shaped this way — and you need Developer access on both ends, because the write touches both.
Open the item and use Parent in the right-hand panel. The picker searches epics in the groups above this repository as well as the parentable items in the repository itself. From the other direction, an epic's page has an Add child action that does the same thing.
gitmoap issues set-parent \ --repo-id <id> \ --issue-id <id> \ --parent-ref '<json>'curl -X PUT https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/parent \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "parent_ref.iid": "<int64>", "parent_ref.scope": "<object>" }'Four rules govern the move, and each of them is checked against what is really there:
- The child's type has to take a parent at all.
spike,choreandsub_taskdo not, and asking is a400before anything else is looked at. - The parent's type must accept the child's type. The matrix is a property of the parent, so it is asymmetric: an epic parents nearly everything, a story or a bug parents tasks, an incident parents tasks, and a task, spike, chore or sub-task parents nothing.
- Nesting is capped at five levels, and the cap has to hold for the deepest item in the subtree you are moving, not just the one you named — a three-deep subtree cannot go under a three-deep parent.
- No cycles. An item cannot become its own ancestor.
Setting the parent an item already has changes nothing and is not an error. Detaching has no structural rule to satisfy — it can only reduce depth — so it is never refused on those grounds, though it still needs Developer access in the old parent's container, because it writes there too. The subtree comes with the item, and a subtree of more than 1,000 items is refused as a conflict rather than moved in pieces; move its branches separately.
Open the item and clear Parent in the right-hand panel, or use Detach on the child's row in the parent's children list.
gitmoap issues remove-parent --repo-id <id> --issue-id <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/parent \ -H "Authorization: Bearer $GITMOAP_TOKEN"See how an epic is tracking
A rollup counts an item's direct children — not the whole subtree beneath it: how many there are, how many are open, completed and cancelled, and how many points are done against the total. Completed means done only — cancelled work closes without completing, and folding the two together is what turns a delivery metric into a lie. The same figures ride every card, so a backlog view already shows them without a second call.
Open a story or a bug that holds tasks. The Progress panel at the top of the page is the rollup: a bar of done against total, the points figure, and the children listed with their status underneath.
gitmoap issues get-rollup --repo-id <id> --issue-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/rollup \ -H "Authorization: Bearer $GITMOAP_TOKEN"An epic lives in a group, so an epic's rollup is the group form — and it is the interesting one, because its children are spread across the repositories beneath the group rather than sitting in one of them:
Open the epic from the group's Issues page. The Progress panel names each child's repository beside its status, so a cross-team epic reads as one bar without anyone assembling it.
gitmoap issues get-group-rollup --group-id <id> --issue-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/issues/{issue_id}/rollup \ -H "Authorization: Bearer $GITMOAP_TOKEN"A rollup only counts the children you can see. If an epic in a public group has children in a private repository, someone outside that repository sees a smaller total — and no "hidden" count, because a hidden count is itself the disclosure.
Record that one item blocks another
There are four kinds of relation: blocks and its mirror blocked_by, and the self-mirroring relates_to and duplicates. You name one direction and both rows are written together, so the far item shows the connection immediately and the pair can never half-exist.
Open the item and use Linked items in the right-hand panel. Pick the kind of link, then search for the other item — the search reaches across repositories and groups you can read.
gitmoap issues add-relation \ --repo-id <id> \ --issue-id <id> \ --kind blocks|blocked_by|relates_to|duplicates \ --target '<json>'curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/relations \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "kind": "<one of blocked_by | blocks | duplicates | relates_to>", "target.iid": "<int64>", "target.scope": "<object>" }'You need Developer access on both items, not just on the one in the URL, because the write puts a row on each. An item cannot be related to itself, and adding a relation that is already there is a 409, so read the item before retrying rather than treating the error as a failure to write.
The blocked_by relation has teeth, and this is the one completion gate that is on by default: a work item with an open blocker cannot be completed. Cancelling it is deliberately still allowed — "this is blocked" and "we are not doing this" are not in conflict, and a gate that made you unblock work before you could abandon it would only teach people to delete the relation.
Open the item. Linked items lists every relation grouped by kind, each row showing the other item's title and current status. A relation whose far item you cannot read is not listed at all.
gitmoap issues list-relations --repo-id <id> --issue-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/relations \ -H "Authorization: Bearer $GITMOAP_TOKEN"Open the item, find the row in Linked items, and use the × at the end of it. Both directions go together.
gitmoap issues remove-relation \ --repo-id <id> \ --issue-id <id> \ --kind <kind> \ --target <target>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/relations/{kind}/{target} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Close a work item
Closing takes an optional status: leave it out and the container's default completed status is used, or name a status yourself to distinguish "we did it" from "we are not doing it". The status you name has to be a closed one — an open status is a 400, because closing into In Progress is not a thing anybody means.
Open the item and use Close at the bottom of the discussion. The split button beside it lets you pick the closing status — Done or Cancelled by default, or whatever your container calls them.
gitmoap issues close --repo-id <id> --issue-id <id>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/close \ -H "Authorization: Bearer $GITMOAP_TOKEN"Two gates can refuse a completion, and both are container settings. Open blockers is on unless a container turns it off: an open blocked_by refuses the completion. Acceptance criteria is off unless a container turns it on: with it on, an item with a required criterion that is not satisfied will not complete. Both gates apply to completing, never to cancelling. Both are also skipped by an ordinary update that happens to set a closed status, so use the close action when you want them enforced.
Work items also close themselves, unless the container turns the commit keyword off. A commit message saying Closes #412 on the default branch closes the item, and so does merging a merge request that says the same thing in its own title or description. Merely naming a work item never closes it — a merge request that references #412 without a closing keyword moves it into the review category when it opens, and no further. If that commit later turns out to be in no branch at all — force-pushed away, or on a branch deleted unmerged — the item comes back to the status the commit found it in, because a fix that is not in the product is not a fix.
Reopen a work item
Open a closed item and use Reopen at the bottom of the discussion. The split button picks which open status it returns to.
gitmoap issues reopen --repo-id <id> --issue-id <id>curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/reopen \ -H "Authorization: Bearer $GITMOAP_TOKEN"Leave the status out and the item returns to the container's default status for new work; name one yourself and it has to be an open status, because a reopen into Done is not a reopen. Reopening puts the item back into the container's open-item count, so it can be refused if the container is at its limit, and it is subject to the same transition constraints an ordinary status change is. A closed item whose bound test regresses on the default branch also reopens itself, carrying the range of commits that broke it.
Move a work item to another repository or group
A move is a re-key, not a copy: the item keeps its discussion, its activity, its children, its parent, its relations and its criteria, and arrives with a new number in the destination. The response names the old reference and the new one. Naming the container it is already in is a 400, not a no-op.
Open the item, choose More actions then Move, and pick the destination repository or group. The confirmation names the new number the item will take and lists what will not survive the move.
gitmoap issues move --repo-id <id> --issue-id <id> --destination '<json>'curl -X POST https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id}/move \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "destination": "<object>" }'Three things do not come along, and the response tells you about each:
- The milestone. A milestone belongs to one container and cannot follow the item out of it.
- Any label neither the destination nor a group above it defines. A label the destination inherits from an ancestor group survives the move; one that exists only in the container the item is leaving does not.
- The number.
#412becomes something else, and links to the old number do not follow.
You need Maintainer at the source — the item is leaving, and its number is retired — and Reporter at the destination, because arriving is a create there. The destination has to accept the item's type, and it has to have room under its own open-item limit.
Delete a work item
Warning
Deleting a work item destroys everything attached to it: its whole discussion, its activity history, its acceptance criteria, its code anchors, its assignee and label records, and both halves of every relation it took part in. It cannot be undone, and there is no author exception — the reporter's recourse is to close the item, which keeps the record. Cancel it instead when the answer is "we are not doing this"; delete only when the item should never have existed at all.
An item that still has children is refused, and the refusal says how many there are. Reparent or delete them first, so that orphaning a subtree is a decision somebody makes rather than a side effect of somebody else's delete.
Open the item, choose More actions then Delete, and confirm. The dialog names what goes with the item.
gitmoap issues delete --repo-id <id> --issue-id <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issues/{issue_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Change the statuses and automation a container uses
Issue settings carry the status set, the transition constraints, the type a create defaults to, whether commit keywords close work and on which branches, whether a public container accepts filings from non-members, the automation that git events drive, and the gates that guard completion. The write is a merge, not a replacement: a field you leave out of the body is left alone, and a field you send as null is cleared so it inherits again. A body with no field in it at all is a 400.
Open the repository, choose Settings then Issues. Statuses edits the set — add a status, rename one, recolour it, choose which one new work lands in, and archive one that is no longer used. Automation carries the on-branch, on-merge-request-opened, on-merge-request-merged and on-merge-request-closed rules, along with the commit-keyword switch and the extra branches beyond the default one that may close work. Completion carries the criteria and blocker gates. Filing carries the type a new item defaults to and whether non-members may file. Turn Override group settings on to make this repository's saved values authoritative; with it off, the whole policy comes from the groups above.
gitmoap issues update-repo-settings --repo-id <id>curl -X PUT https://api.gitmoap.example/repositories/{repo_id}/issue-settings \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "statuses[].category": "<one of blocked | cancelled | done | in_progress | in_review | todo | triage>", "statuses[].name": "<string>", "statuses[].status_id": "<string>" }'The same settings body carries three groups of fields this page does not cover, because they belong to the features they configure: what a TODO: marker in the code becomes and which paths the scanner skips, what happens when the code under a work item's anchor changes beyond recognition, and whether green acceptance criteria close an item on their own. Those are in Linking work to code and Proof of Done. They are all one merge into the same body, so a script that sets a status set and a TODO policy sends one call.
Set the same policy on a group and every container beneath it inherits it, which is how an org-wide status set or completion gate is defined once. Turn the group's own Override group settings on and the containers below it can no longer override the fields the group sets — that is what makes the policy enforceable rather than advisory.
Open the group, choose Settings then Issues. The form is the repository form; what changes is the reach — every repository and subgroup beneath this one inherits whatever you set here and does not set itself.
gitmoap issues update-group-settings --group-id <id>curl -X PUT https://api.gitmoap.example/groups/{group_id}/issue-settings \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "statuses[].category": "<one of blocked | cancelled | done | in_progress | in_review | todo | triage>", "statuses[].name": "<string>", "statuses[].status_id": "<string>" }'Two rules shape what you can do to a status set:
- A status's category cannot change once the status exists. Add a new status in the category you want and archive the old one; work already in the archived status keeps rendering, sorting and rolling up correctly, and only disappears from the pickers.
- A set must stay usable. At least one unarchived completed status, at least one unarchived open one, exactly one unarchived status marked as the default for new work and that one open, unique ids, and between 1 and 30 statuses in a set.
Open Settings then Issues. The page shows the settings this repository will actually use — the resolved answer after inheritance, not the raw values it happens to store.
gitmoap issues get-repo-settings --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/issue-settings \ -H "Authorization: Bearer $GITMOAP_TOKEN"A group's settings read back what that group itself stores, unresolved, rather than an effective answer — a group is what the containers below it inherit from, so what it stores is the interesting question. A field this group leaves unset comes back empty here and is supplied by its own parent.
Open the group, choose Settings then Issues. Anything this group has not set itself is blank, and what a repository beneath it actually uses is best read from that repository's own settings page.
gitmoap issues get-group-settings --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/issue-settings \ -H "Authorization: Bearer $GITMOAP_TOKEN"Go back to inheriting
Removing a container's issue settings deletes what it stores and puts it back to full inheritance from the group chain. Nothing about the work items changes — an item in a status the inherited set does not name keeps that status and keeps behaving correctly, because its category is on the item.
Open Settings then Issues and use Reset to inherited at the bottom of the page, then confirm.
gitmoap issues delete-repo-settings --repo-id <id>curl -X DELETE https://api.gitmoap.example/repositories/{repo_id}/issue-settings \ -H "Authorization: Bearer $GITMOAP_TOKEN"The same action on a group hands the group back to its parent, and takes with it any lock the group was holding over the containers below.
Open the group, choose Settings then Issues, and use Reset to inherited. Anything a repository below was inheriting from this group now comes from further up instead.
gitmoap issues delete-group-settings --group-id <id>curl -X DELETE https://api.gitmoap.example/groups/{group_id}/issue-settings \ -H "Authorization: Bearer $GITMOAP_TOKEN"Reference
Almost every operation has a repository form and a group form, taking the same body and answering the same shape. Three differences are worth remembering, and each is explained in the task above that it belongs to: which work-item types a container accepts, how far a group listing reaches, and whether issue settings come back resolved or raw. The four personal listings are the exception — they belong to you rather than to a container, so they have neither form.
Work items in a repository
9 endpoints
POST/repositories/{repo_id}/issuesissue:create
File a work item in a repository
Token scope
issue:create
Counts against
open_issues_per_scope
Send
Path
- repo_iduuidRepository ID
Body
- descriptionobjectoptional
- milestone_idobjectoptional
- parent_refobjectoptional
- pointsint32optional
- severityobjectoptional
- status_idobjectoptional
- titlestring
- type_profileobjectoptional
- work_item_typeobjectoptional
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Caller may not file here404Repository not found409The parent's type may not parent this type429Open work-item limit reached
Receive
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/repositories/{repo_id}/issues/{issue_id}issue:read
Get one work item
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
- issue_idint64The per-scope iid — the work item's only identity
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found, or a private scope with no access
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/repositories/{repo_id}/issuesissue:read
List a repository's work items
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
Query
- status_categorystringoptionalStatus category — triage, todo, in_progress, in_review, blocked, done or cancelled
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- assigneestringoptionalAssigned principal
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 20, max 100)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Repository not found, or private with no access
Receive
items[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/repositories/{repo_id}/issues/cardsissue:read
List a repository's work items as cards
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
Query
- status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- assigneestringoptionalAssigned principal
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 10, max 25)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Repository not found, or private with no access
Receive
items[]object24 fields
authorobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- blocked_byint32How many open work items block this one. A count, never an identity: a blocker the caller cannot see still blocks, and naming it would leak the private item's existence.
childrenobject6 fields
- cancelledint32
- completedint32Children in the
donecategory only. A cancelled child is closed but not completed, and is counted incancelled. - openint32
- points_completedint32
- points_totalint32
- totalint32
- comments_countint32
- created_atstring
- iidint64
- milestoneobjectoptional
- pointsint32optional
- scopeobjectA group or a repository, whichever a setting belongs to.
- severityobjectoptional
- status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
- titlestring
- uiduuid
- updated_atstring
PATCH/repositories/{repo_id}/issues/{issue_id}issue:update
Update a work item
Token scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64The per-scope iid
Body
- descriptionobjectoptional
- milestone_idobjectoptional
- pointsint32optional
- severityobjectoptional
- status_idobjectoptional
- titleobjectoptional
- versionint64Required. The
versionyou last read; if the work item has changed since, the update is refused with a409rather than silently overwriting someone else's change. - work_item_typeobjectoptional
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Stale version, or a transition the workflow forbids
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/repositories/{repo_id}/issues/{issue_id}/closeissue:update
Close a work item
Token scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64The per-scope iid
Body
- status_idobjectoptional
Refuses
400The target status is not a completed or cancelled one401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Already closed, or a transition the workflow forbids
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/repositories/{repo_id}/issues/{issue_id}/reopenissue:update
Reopen a work item
Token scope
issue:update
Counts against
open_issues_per_scope
Send
Path
- repo_iduuidRepository ID
- issue_idint64The per-scope iid
Body
- status_idobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Already open, or a transition the workflow forbids429Open work-item limit reached
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/repositories/{repo_id}/issues/{issue_id}/moveissue:delete
Move a repository work item to another scope
Token scope
issue:delete
Counts against
open_issues_per_scope
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Body
- destinationobjectA group or a repository, whichever a setting belongs to.
Refuses
400The destination does not accept this type, is the scope the work item is already in, or is in another organization401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The work item changed, or was already moved; reload and retry429The destination scope is at its open work-item limit
Receive
- dropped_milestoneobjectoptional
fromobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
issueobject21 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
DELETE/repositories/{repo_id}/issues/{issue_id}issue:delete
Delete a work item and everything under it
Token scope
issue:delete
Send
Path
- repo_iduuidRepository ID
- issue_idint64The per-scope iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Maintainer required — there is no author exception on delete404Not found409The work item still has children
Receive
No body.
Work items in a group
9 endpoints
POST/groups/{group_id}/issuesissue:create
File a work item in a group
Token scope
issue:create
Counts against
open_issues_per_scope
Send
Path
- group_iduuidGroup ID
Body
- descriptionobjectoptional
- milestone_idobjectoptional
- parent_refobjectoptional
- pointsint32optional
- severityobjectoptional
- status_idobjectoptional
- titlestring
- type_profileobjectoptional
- work_item_typeobjectoptional
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Caller may not file here404Group not found409The request conflicts with the resource's current state; `reason` says how429Open work-item limit reached
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/groups/{group_id}/issues/{issue_id}issue:read
Get one group-scoped work item
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
- issue_idint64The per-scope iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found, or a private scope with no access
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/groups/{group_id}/issuesissue:read
List the work items across a group
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
Query
- scopestringoptional
subtree(default) orown— the group's own epics only - status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- assigneestringoptionalAssigned principal
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 20, max 100)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Group not found, or private with no access
Receive
The same shape list_issues returns — 1 field. Go to it
Show it here
items[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/groups/{group_id}/issues/cardsissue:read
List a group subtree's work items as cards
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
Query
- scopestringoptional
subtree(default) orown - status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- assigneestringoptionalAssigned principal
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 10, max 25)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Group not found, or private with no access
Receive
The same shape list_issue_cards returns — 1 field. Go to it
Show it here
items[]object24 fields
authorobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- blocked_byint32How many open work items block this one. A count, never an identity: a blocker the caller cannot see still blocks, and naming it would leak the private item's existence.
childrenobject6 fields
- cancelledint32
- completedint32Children in the
donecategory only. A cancelled child is closed but not completed, and is counted incancelled. - openint32
- points_completedint32
- points_totalint32
- totalint32
- comments_countint32
- created_atstring
- iidint64
- milestoneobjectoptional
- pointsint32optional
- scopeobjectA group or a repository, whichever a setting belongs to.
- severityobjectoptional
- status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
- titlestring
- uiduuid
- updated_atstring
PATCH/groups/{group_id}/issues/{issue_id}issue:update
Update a group-scoped work item
Token scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64The per-scope iid
Body
- descriptionobjectoptional
- milestone_idobjectoptional
- pointsint32optional
- severityobjectoptional
- status_idobjectoptional
- titleobjectoptional
- versionint64Required. The
versionyou last read; if the work item has changed since, the update is refused with a409rather than silently overwriting someone else's change. - work_item_typeobjectoptional
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Stale version, or a transition the workflow forbids
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/groups/{group_id}/issues/{issue_id}/closeissue:update
Close a group-scoped work item
Token scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64The per-scope iid
Body
- status_idobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Already closed, or a transition the workflow forbids
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/groups/{group_id}/issues/{issue_id}/reopenissue:update
Reopen a group-scoped work item
Token scope
issue:update
Counts against
open_issues_per_scope
Send
Path
- group_iduuidGroup ID
- issue_idint64The per-scope iid
Body
- status_idobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Already open, or a transition the workflow forbids429Open work-item limit reached
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/groups/{group_id}/issues/{issue_id}/moveissue:delete
Move a group work item to another scope
Token scope
issue:delete
Counts against
open_issues_per_scope
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Body
- destinationobjectA group or a repository, whichever a setting belongs to.
Refuses
400The destination does not accept this type, is the scope the work item is already in, or is in another organization401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The work item changed, or was already moved; reload and retry429The destination scope is at its open work-item limit
Receive
The same shape move_issue returns — 3 fields. Go to it
Show it here
- dropped_milestoneobjectoptional
fromobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
issueobject21 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
DELETE/groups/{group_id}/issues/{issue_id}issue:delete
Delete a group-scoped work item and everything under it
Token scope
issue:delete
Send
Path
- group_iduuidGroup ID
- issue_idint64The per-scope iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Maintainer required404Not found409The work item still has children
Receive
No body.
Your own work
4 endpoints
GET/user/issuesissue:read
List the work items assigned to the caller
Token scope
issue:read
Send
Query
- status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 20, max 100)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
The same shape list_issues returns — 1 field. Go to it
Show it here
items[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/user/issues/cardsissue:read
List the work items assigned to the caller as cards
Token scope
issue:read
Send
Query
- status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 10, max 25)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
The same shape list_issue_cards returns — 1 field. Go to it
Show it here
items[]object24 fields
authorobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- blocked_byint32How many open work items block this one. A count, never an identity: a blocker the caller cannot see still blocks, and naming it would leak the private item's existence.
childrenobject6 fields
- cancelledint32
- completedint32Children in the
donecategory only. A cancelled child is closed but not completed, and is counted incancelled. - openint32
- points_completedint32
- points_totalint32
- totalint32
- comments_countint32
- created_atstring
- iidint64
- milestoneobjectoptional
- pointsint32optional
- scopeobjectA group or a repository, whichever a setting belongs to.
- severityobjectoptional
- status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
- titlestring
- uiduuid
- updated_atstring
GET/user/reported-issuesissue:read
List the work items the caller reported
Token scope
issue:read
Send
Query
- status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 20, max 100)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
The same shape list_issues returns — 1 field. Go to it
Show it here
items[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/user/reported-issues/cardsissue:read
List the work items the caller reported as cards
Token scope
issue:read
Send
Query
- status_categorystringoptionalStatus category
- status_idstringoptionalThe named status within its category
- typestringoptionalWork-item type
- labelstringoptionalLabel key
- milestonestringoptionalMilestone ID
- searchstringoptionalWords to find in the title or description, or part of the title
- limitint32optionalPage size (default 10, max 25)
- next_tokenstringoptionalPagination cursor
Refuses
400Invalid filter or cursor401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
The same shape list_issue_cards returns — 1 field. Go to it
Show it here
items[]object24 fields
authorobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- blocked_byint32How many open work items block this one. A count, never an identity: a blocker the caller cannot see still blocks, and naming it would leak the private item's existence.
childrenobject6 fields
- cancelledint32
- completedint32Children in the
donecategory only. A cancelled child is closed but not completed, and is counted incancelled. - openint32
- points_completedint32
- points_totalint32
- totalint32
- comments_countint32
- created_atstring
- iidint64
- milestoneobjectoptional
- pointsint32optional
- scopeobjectA group or a repository, whichever a setting belongs to.
- severityobjectoptional
- status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
- titlestring
- uiduuid
- updated_atstring
Assignees
4 endpoints
POST/repositories/{repo_id}/issues/{issue_id}/assigneesissue:update
Assign a principal to a work item in a repository
Token scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Body
- principal_iduuid
Refuses
400At the assignee cap, or the type takes no assignees401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The principal is not a member of the scope
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/repositories/{repo_id}/issues/{issue_id}/assignees/{principal_id}issue:update
Unassign a principal from a work item in a repository
remove_issue_assigneeDELETE /repositories/{repo_id}/issues/{issue_id}/assignees/{principal_id}Open in the API referenceToken scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
- principal_iduuidThe user or service account to unassign
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not assigned409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/groups/{group_id}/issues/{issue_id}/assigneesissue:update
Assign a principal to a work item in a group
add_group_issue_assigneePOST /groups/{group_id}/issues/{issue_id}/assigneesOpen in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Body
- principal_iduuid
Refuses
400At the assignee cap, or the type takes no assignees401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The principal is not a member of the scope
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/groups/{group_id}/issues/{issue_id}/assignees/{principal_id}issue:update
Unassign a principal from a work item in a group
remove_group_issue_assigneeDELETE /groups/{group_id}/issues/{issue_id}/assignees/{principal_id}Open in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
- principal_iduuidThe user or service account to unassign
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not assigned409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
Hierarchy
6 endpoints
PUT/repositories/{repo_id}/issues/{issue_id}/parentissue:update
Reparent a repository work item
Token scope
issue:update
Counts against
children_per_issue
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Body
parent_refobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
Refuses
400The move would exceed the depth cap401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The move would make a cycle, or the parent cannot adopt this type429The parent work item is at its child limit
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/repositories/{repo_id}/issues/{issue_id}/parentissue:update
Detach a repository work item from its parent
Token scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Work item not found409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/repositories/{repo_id}/issues/{issue_id}/rollupissue:read
Roll up a repository work item's children
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Work item not found
Receive
- cancelledint32
children[]object7 fields
child_refobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
- child_uiduuid
- linked_atstring
- pointsint32optional
- status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - work_item_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
- completedint32Children in the
donecategory only. A cancelled child is closed but not completed, and is counted incancelled. - openint32
- points_completedint32
- points_totalint32
- totalint32
PUT/groups/{group_id}/issues/{issue_id}/parentissue:update
Reparent a group work item
Token scope
issue:update
Counts against
children_per_issue
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Body
parent_refobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
Refuses
400The move would exceed the depth cap401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The move would make a cycle, or the parent cannot adopt this type429The parent work item is at its child limit
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/groups/{group_id}/issues/{issue_id}/parentissue:update
Detach a group work item from its parent
remove_group_issue_parentDELETE /groups/{group_id}/issues/{issue_id}/parentOpen in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Work item not found409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/groups/{group_id}/issues/{issue_id}/rollupissue:read
Roll up a group work item's children
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Work item not found
Receive
The same shape get_issue_rollup returns — 7 fields. Go to it
Show it here
- cancelledint32
children[]object7 fields
child_refobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
- child_uiduuid
- linked_atstring
- pointsint32optional
- status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - work_item_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
- completedint32Children in the
donecategory only. A cancelled child is closed but not completed, and is counted incancelled. - openint32
- points_completedint32
- points_totalint32
- totalint32
Relations
6 endpoints
POST/repositories/{repo_id}/issues/{issue_id}/relationsissue:update
Relate a repository work item to another
Token scope
issue:update
Counts against
relations_per_issue
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Body
- kindblocked_byblocksduplicatesrelates_toHow two work items relate. A relation is always visible from both ends:
blockson one item reads asblocked_byon the other, whilerelates_toandduplicatesread the same from either side. targetobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
Refuses
400Self-relation, or the type takes no relations401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Already related429Relation limit reached
Receive
[]object8 fields
- created_atstring
- kindblocked_byblocksduplicatesrelates_toHow two work items relate. A relation is always visible from both ends:
blockson one item reads asblocked_byon the other, whilerelates_toandduplicatesread the same from either side. - status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
targetobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
- titlestring
- work_item_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
GET/repositories/{repo_id}/issues/{issue_id}/relationsissue:read
List a repository work item's relations
list_issue_relationsGET /repositories/{repo_id}/issues/{issue_id}/relationsOpen in the API referenceToken scope
issue:read
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Work item not found
Receive
The same shape add_issue_relation returns — 1 field. Go to it
Show it here
[]object8 fields
- created_atstring
- kindblocked_byblocksduplicatesrelates_toHow two work items relate. A relation is always visible from both ends:
blockson one item reads asblocked_byon the other, whilerelates_toandduplicatesread the same from either side. - status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
targetobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
- titlestring
- work_item_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
DELETE/repositories/{repo_id}/issues/{issue_id}/relations/{kind}/{target}issue:update
Remove a relation from a repository work item
remove_issue_relationDELETE /repositories/{repo_id}/issues/{issue_id}/relations/{kind}/{target}Open in the API referenceToken scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
- kindblocked_byblocksduplicatesrelates_toRelation kind
- targetstringThe other end (
repo:{uuid}:{iid})
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Relation not found409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
POST/groups/{group_id}/issues/{issue_id}/relationsissue:update
Relate a group work item to another
add_group_issue_relationPOST /groups/{group_id}/issues/{issue_id}/relationsOpen in the API referenceToken scope
issue:update
Counts against
relations_per_issue
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Body
- kindblocked_byblocksduplicatesrelates_toHow two work items relate. A relation is always visible from both ends:
blockson one item reads asblocked_byon the other, whilerelates_toandduplicatesread the same from either side. targetobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
Refuses
400Self-relation, or the type takes no relations401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409Already related429Relation limit reached
Receive
The same shape add_issue_relation returns — 1 field. Go to it
Show it here
[]object8 fields
- created_atstring
- kindblocked_byblocksduplicatesrelates_toHow two work items relate. A relation is always visible from both ends:
blockson one item reads asblocked_byon the other, whilerelates_toandduplicatesread the same from either side. - status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
targetobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
- titlestring
- work_item_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
GET/groups/{group_id}/issues/{issue_id}/relationsissue:read
List a group work item's relations
list_group_issue_relationsGET /groups/{group_id}/issues/{issue_id}/relationsOpen in the API referenceToken scope
issue:read
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Work item not found
Receive
The same shape add_issue_relation returns — 1 field. Go to it
Show it here
[]object8 fields
- created_atstring
- kindblocked_byblocksduplicatesrelates_toHow two work items relate. A relation is always visible from both ends:
blockson one item reads asblocked_byon the other, whilerelates_toandduplicatesread the same from either side. - status_categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - status_idstring
targetobject2 fields
- iidint64
- scopeobjectA group or a repository, whichever a setting belongs to.
- titlestring
- work_item_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
DELETE/groups/{group_id}/issues/{issue_id}/relations/{kind}/{target}issue:update
Remove a relation from a group work item
remove_group_issue_relationDELETE /groups/{group_id}/issues/{issue_id}/relations/{kind}/{target}Open in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
- kindblocked_byblocksduplicatesrelates_toRelation kind
- targetstringThe other end (
repo:{uuid}:{iid})
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Relation not found409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
Labels
14 endpoints
POST/repositories/{repo_id}/labelslabel:manage
Define a label
Token scope
label:manage
Counts against
labels_per_scope
Send
Path
- repo_iduuidRepository ID
Body
- colorstring
- descriptionobjectoptional
- keystring
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409A label with this key already exists429Label limit reached
Receive
- colorstring
- created_atstring
- descriptionobjectoptional
- keystring
- scope_idstring
- scope_typegrouprepository
GET/repositories/{repo_id}/labelsissue:read
List the labels a scope defines
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
Query
- searchstringoptionalAutocomplete fragment — keeps labels whose key or description contains it, ignoring case
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent
Receive
[]object6 fields
- colorstring
- created_atstring
- descriptionobjectoptional
- keystring
- scope_idstring
- scope_typegrouprepository
PATCH/repositories/{repo_id}/labels/{label_key}label:manage
Update a label's colour or description
Token scope
label:manage
Send
Path
- repo_iduuidRepository ID
- label_keystringLabel key — may be
scoped::like-this
Body
- colorobjectoptional
- descriptionobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Label not found409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_label returns — 6 fields. Go to it
Show it here
- colorstring
- created_atstring
- descriptionobjectoptional
- keystring
- scope_idstring
- scope_typegrouprepository
DELETE/repositories/{repo_id}/labels/{label_key}label:manage
Delete a label, taking it off every work item that carries it
Token scope
label:manage
Send
Path
- repo_iduuidRepository ID
- label_keystringLabel key — may be
scoped::like-this
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Label not found409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
POST/repositories/{repo_id}/issues/{issue_id}/labelsissue:update
Apply a label to a repository work item
Token scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Body
- keystring
Refuses
400Undefined label, or at the per-item cap401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/repositories/{repo_id}/issues/{issue_id}/labels/{label_key}issue:update
Take a label off a repository work item
remove_issue_labelDELETE /repositories/{repo_id}/issues/{issue_id}/labels/{label_key}Open in the API referenceToken scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
- label_keystringLabel key
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/repositories/{repo_id}/labels/{label_key}/issuesissue:read
List the work items in this scope carrying a label
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
- label_keystringLabel key — may be
scoped::like-this
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent
Receive
[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/groups/{group_id}/labelslabel:manage
Define a label
Token scope
label:manage
Counts against
labels_per_scope
Send
Path
- group_iduuidGroup ID
Body
- colorstring
- descriptionobjectoptional
- keystring
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409A label with this key already exists429Label limit reached
Receive
The same shape create_label returns — 6 fields. Go to it
Show it here
- colorstring
- created_atstring
- descriptionobjectoptional
- keystring
- scope_idstring
- scope_typegrouprepository
GET/groups/{group_id}/labelsissue:read
List the labels a scope defines
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
Query
- searchstringoptionalAutocomplete fragment — keeps labels whose key or description contains it, ignoring case
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent
Receive
The same shape list_labels returns — 1 field. Go to it
Show it here
[]object6 fields
- colorstring
- created_atstring
- descriptionobjectoptional
- keystring
- scope_idstring
- scope_typegrouprepository
PATCH/groups/{group_id}/labels/{label_key}label:manage
Update a label's colour or description
Token scope
label:manage
Send
Path
- group_iduuidGroup ID
- label_keystringLabel key — may be
scoped::like-this
Body
- colorobjectoptional
- descriptionobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Label not found409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_label returns — 6 fields. Go to it
Show it here
- colorstring
- created_atstring
- descriptionobjectoptional
- keystring
- scope_idstring
- scope_typegrouprepository
DELETE/groups/{group_id}/labels/{label_key}label:manage
Delete a label, taking it off every work item that carries it
Token scope
label:manage
Send
Path
- group_iduuidGroup ID
- label_keystringLabel key — may be
scoped::like-this
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Label not found409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
POST/groups/{group_id}/issues/{issue_id}/labelsissue:update
Apply a label to a group work item
Token scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Body
- keystring
Refuses
400Undefined label, or at the per-item cap401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/groups/{group_id}/issues/{issue_id}/labels/{label_key}issue:update
Take a label off a group work item
remove_group_issue_labelDELETE /groups/{group_id}/issues/{issue_id}/labels/{label_key}Open in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
- label_keystringLabel key
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/groups/{group_id}/labels/{label_key}/issuesissue:read
List the work items in this scope carrying a label
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
- label_keystringLabel key — may be
scoped::like-this
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent
Receive
The same shape list_issues_by_label returns — 1 field. Go to it
Show it here
[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
Milestones
16 endpoints
POST/repositories/{repo_id}/milestonesmilestone:manage
Create a milestone
Token scope
milestone:manage
Counts against
milestones_per_scope
Send
Path
- repo_iduuidRepository ID
Body
- descriptionobjectoptional
- due_onobjectoptional
- titlestring
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how429Milestone limit reached
Receive
- closedbooleanoptional
- created_atstring
- descriptionobjectoptional
- due_onobjectoptional
- milestone_iduuid
- scope_idstring
- scope_typegrouprepository
- titlestring
- updated_atstring
GET/repositories/{repo_id}/milestonesissue:read
List a scope's milestones
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
Query
- searchstringoptionalAutocomplete fragment — keeps milestones whose title or description contains it, ignoring case
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent
Receive
[]object9 fields
- closedbooleanoptional
- created_atstring
- descriptionobjectoptional
- due_onobjectoptional
- milestone_iduuid
- scope_idstring
- scope_typegrouprepository
- titlestring
- updated_atstring
GET/repositories/{repo_id}/milestones/{milestone_id}issue:read
Get a milestone and its burndown
Token scope
issue:read
Send
Path
- repo_iduuidRepository ID
- milestone_iduuidMilestone ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found
Receive
No body.
PATCH/repositories/{repo_id}/milestones/{milestone_id}milestone:manage
Update a milestone
Token scope
milestone:manage
Send
Path
- repo_iduuidRepository ID
- milestone_iduuidMilestone ID
Body
- closedobjectoptionalClosing a milestone is an edit, not a separate verb: it changes one field and nothing else happens.
- descriptionobjectoptional
- due_onobjectoptional
- titleobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_milestone returns — 9 fields. Go to it
Show it here
- closedbooleanoptional
- created_atstring
- descriptionobjectoptional
- due_onobjectoptional
- milestone_iduuid
- scope_idstring
- scope_typegrouprepository
- titlestring
- updated_atstring
DELETE/repositories/{repo_id}/milestones/{milestone_id}milestone:manage
Delete a milestone, taking it off every work item in it
Token scope
milestone:manage
Send
Path
- repo_iduuidRepository ID
- milestone_iduuidMilestone ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
PUT/repositories/{repo_id}/issues/{issue_id}/milestoneissue:update
Put a repository work item into a milestone
Token scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Body
- milestone_iduuid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409That milestone is closed
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/repositories/{repo_id}/issues/{issue_id}/milestoneissue:update
Take a repository work item out of its milestone
remove_issue_milestoneDELETE /repositories/{repo_id}/issues/{issue_id}/milestoneOpen in the API referenceToken scope
issue:update
Send
Path
- repo_iduuidRepository ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The work item changed while it was being updated; retry
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/repositories/{repo_id}/milestones/{milestone_id}/issuesissue:read
List a milestone's work items
list_milestone_issuesGET /repositories/{repo_id}/milestones/{milestone_id}/issuesOpen in the API referenceToken scope
issue:read
Send
Path
- repo_iduuidRepository ID
- milestone_iduuidMilestone ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found
Receive
The same shape list_issues_by_label returns — 1 field. Go to it
Show it here
[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
POST/groups/{group_id}/milestonesmilestone:manage
Create a milestone
Token scope
milestone:manage
Counts against
milestones_per_scope
Send
Path
- group_iduuidGroup ID
Body
- descriptionobjectoptional
- due_onobjectoptional
- titlestring
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how429Milestone limit reached
Receive
The same shape create_milestone returns — 9 fields. Go to it
Show it here
- closedbooleanoptional
- created_atstring
- descriptionobjectoptional
- due_onobjectoptional
- milestone_iduuid
- scope_idstring
- scope_typegrouprepository
- titlestring
- updated_atstring
GET/groups/{group_id}/milestonesissue:read
List a scope's milestones
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
Query
- searchstringoptionalAutocomplete fragment — keeps milestones whose title or description contains it, ignoring case
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent
Receive
The same shape list_milestones returns — 1 field. Go to it
Show it here
[]object9 fields
- closedbooleanoptional
- created_atstring
- descriptionobjectoptional
- due_onobjectoptional
- milestone_iduuid
- scope_idstring
- scope_typegrouprepository
- titlestring
- updated_atstring
GET/groups/{group_id}/milestones/{milestone_id}issue:read
Get a milestone and its burndown
Token scope
issue:read
Send
Path
- group_iduuidGroup ID
- milestone_iduuidMilestone ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found
Receive
No body.
PATCH/groups/{group_id}/milestones/{milestone_id}milestone:manage
Update a milestone
Token scope
milestone:manage
Send
Path
- group_iduuidGroup ID
- milestone_iduuidMilestone ID
Body
- closedobjectoptionalClosing a milestone is an edit, not a separate verb: it changes one field and nothing else happens.
- descriptionobjectoptional
- due_onobjectoptional
- titleobjectoptional
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape create_milestone returns — 9 fields. Go to it
Show it here
- closedbooleanoptional
- created_atstring
- descriptionobjectoptional
- due_onobjectoptional
- milestone_iduuid
- scope_idstring
- scope_typegrouprepository
- titlestring
- updated_atstring
DELETE/groups/{group_id}/milestones/{milestone_id}milestone:manage
Delete a milestone, taking it off every work item in it
Token scope
milestone:manage
Send
Path
- group_iduuidGroup ID
- milestone_iduuidMilestone ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
PUT/groups/{group_id}/issues/{issue_id}/milestoneissue:update
Put a group work item into a milestone
set_group_issue_milestonePUT /groups/{group_id}/issues/{issue_id}/milestoneOpen in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Body
- milestone_iduuid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409That milestone is closed
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
DELETE/groups/{group_id}/issues/{issue_id}/milestoneissue:update
Take a group work item out of its milestone
remove_group_issue_milestoneDELETE /groups/{group_id}/issues/{issue_id}/milestoneOpen in the API referenceToken scope
issue:update
Send
Path
- group_iduuidGroup ID
- issue_idint64Work-item iid
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The work item changed while it was being updated; retry
Receive
The same shape create_issue returns — 21 fields. Go to it
Show it here
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
GET/groups/{group_id}/milestones/{milestone_id}/issuesissue:read
List a group milestone's work items
list_group_milestone_issuesGET /groups/{group_id}/milestones/{milestone_id}/issuesOpen in the API referenceToken scope
issue:read
Send
Path
- group_iduuidGroup ID
- milestone_iduuidMilestone ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Milestone not found
Receive
The same shape list_issues_by_label returns — 1 field. Go to it
Show it here
[]object24 fields
- author_can_pushobjectoptionalWhether the author can push to where this work item lives — its repository, or a group work item's group. False for a drive-by contributor's text. Absent where it was not computed.
- closed_atobjectoptional
- closed_byobjectoptional
- created_atstring
created_byobject4 fields
- avatar_urlobjectoptional
- emailstring
- idstring
- usernamestring
- descriptionobjectoptional
- iidint64
- milestone_idobjectoptional
- milestone_scope_idobjectoptional
- milestone_scope_typeobjectoptional
- parent_refobjectoptional
- parent_uidobjectoptional
- pointsint32optional
- regressed_atobjectoptional
- regressed_at_shaobjectoptional
- regressed_from_shaobjectoptional
- regressed_run_idobjectoptional
- root_scope_iduuid
- scope_idstring
- scope_typegrouprepository
- severityobjectoptional
Workflow settings
6 endpoints
GET/repositories/{repo_id}/issue-settingsissue_settings:read
Get a repository's effective issue settings, resolved through the group chain
Token scope
issue_settings:read
Send
Path
- repo_iduuidRepository ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Repository not found
Receive
- anchor_drift_actioncommentflagnoneWhat happens when an anchored region of code changes beyond recognition.
- auto_close_on_verifiedbooleanWhether a work item closes as soon as it is verified. Defaults to
false: passing criteria make an item verified, and merging the merge request that closes it makes it done. - auto_reopen_on_orphaned_closebooleanA closed item whose closing commit is in no branch any more reopens itself.
- auto_reopen_on_regressionboolean
- binding_change_resets_evidencebooleanReset a criterion's evidence when its binding changes. Default true.
- blocked_by_blocks_closeboolean
- close_on_commit_keywordboolean
- default_assignee_from_codeownersboolean
- default_issue_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
- on_branch_createdobjectWhere an automation moves a work item when its event happens: nowhere (
disabled), back to where it was (restore), or into a status category ({"to": "in_progress"}). - on_mr_closedobjectWhere an automation moves a work item when its event happens: nowhere (
disabled), back to where it was (restore), or into a status category ({"to": "in_progress"}). - on_mr_mergedobjectWhere an automation moves a work item when its event happens: nowhere (
disabled), back to where it was (restore), or into a status category ({"to": "in_progress"}). - on_mr_openedobjectWhere an automation moves a work item when its event happens: nowhere (
disabled), back to where it was (restore), or into a status category ({"to": "in_progress"}). - override_group_settingsboolean
- public_issue_filingboolean
- require_verified_criteria_to_closeboolean
statuses[]object6 fields
- archivedbooleanoptional
- categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - colorobjectoptional
- is_defaultbooleanoptionalThe status new issues land in. Exactly one status in a set carries it, and it must be open.
- namestring
- status_idstring
- todo_policyignoreindexpromoteWhat a bare
// TODO:in a push becomes. - todo_promote_typebugchoreepicincidentspikestorysub_tasktaskThe kind of work item. The type decides where an item may live (a group or a repository), which types it may have as children, and which fields it accepts.
PUT/repositories/{repo_id}/issue-settingsissue_settings:manage
Update a repository's issue settings
Token scope
issue_settings:manage
Send
Path
- repo_iduuidRepository ID
Body
- anchor_drift_actionobjectoptional
- auto_close_on_verifiedobjectoptional
- auto_reopen_on_orphaned_closeobjectoptional
- auto_reopen_on_regressionobjectoptional
- binding_change_resets_evidenceobjectoptional
- blocked_by_blocks_closeobjectoptional
- close_on_commit_keywordobjectoptional
- default_assignee_from_codeownersobjectoptional
- default_issue_typeobjectoptional
- on_branch_createdobjectoptional
- on_mr_closedobjectoptional
- on_mr_mergedobjectoptional
- on_mr_openedobjectoptional
- override_group_settingsobjectoptional
- public_issue_filingobjectoptional
- require_verified_criteria_to_closeobjectoptional
statuses[]object6 fields
- archivedbooleanoptional
- categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - colorobjectoptional
- is_defaultbooleanoptionalThe status new issues land in. Exactly one status in a set carries it, and it must be open.
- namestring
- status_idstring
- todo_policyobjectoptional
- todo_promote_typeobjectoptional
Refuses
400Empty body, or an invalid status set401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
- anchor_drift_actionobjectoptional
- auto_close_on_verifiedobjectoptional
- auto_reopen_on_orphaned_closeobjectoptional
- auto_reopen_on_regressionobjectoptional
- binding_change_resets_evidenceobjectoptional
- blocked_by_blocks_closeobjectoptional
- close_on_commit_keywordobjectoptional
- default_assignee_from_codeownersobjectoptional
- default_issue_typeobjectoptional
- on_branch_createdobjectoptional
- on_mr_closedobjectoptional
- on_mr_mergedobjectoptional
- on_mr_openedobjectoptional
- override_group_settingsobjectoptional
- public_issue_filingobjectoptional
- require_verified_criteria_to_closeobjectoptional
statuses[]object6 fields
- archivedbooleanoptional
- categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - colorobjectoptional
- is_defaultbooleanoptionalThe status new issues land in. Exactly one status in a set carries it, and it must be open.
- namestring
- status_idstring
- todo_policyobjectoptional
- todo_promote_typeobjectoptional
DELETE/repositories/{repo_id}/issue-settingsissue_settings:manage
Remove a repository's issue settings, returning it to full inheritance
Token scope
issue_settings:manage
Send
Path
- repo_iduuidRepository ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Maintainer required404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
GET/groups/{group_id}/issue-settingsissue_settings:read
Get the issue settings a group declares
Token scope
issue_settings:read
Send
Path
- group_iduuidGroup ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Group not found
Receive
The same shape update_repo_issue_settings returns — 19 fields. Go to it
Show it here
- anchor_drift_actionobjectoptional
- auto_close_on_verifiedobjectoptional
- auto_reopen_on_orphaned_closeobjectoptional
- auto_reopen_on_regressionobjectoptional
- binding_change_resets_evidenceobjectoptional
- blocked_by_blocks_closeobjectoptional
- close_on_commit_keywordobjectoptional
- default_assignee_from_codeownersobjectoptional
- default_issue_typeobjectoptional
- on_branch_createdobjectoptional
- on_mr_closedobjectoptional
- on_mr_mergedobjectoptional
- on_mr_openedobjectoptional
- override_group_settingsobjectoptional
- public_issue_filingobjectoptional
- require_verified_criteria_to_closeobjectoptional
statuses[]object6 fields
- archivedbooleanoptional
- categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - colorobjectoptional
- is_defaultbooleanoptionalThe status new issues land in. Exactly one status in a set carries it, and it must be open.
- namestring
- status_idstring
- todo_policyobjectoptional
- todo_promote_typeobjectoptional
PUT/groups/{group_id}/issue-settingsissue_settings:manage
Update a group's issue settings
Token scope
issue_settings:manage
Send
Path
- group_iduuidGroup ID
Body
- anchor_drift_actionobjectoptional
- auto_close_on_verifiedobjectoptional
- auto_reopen_on_orphaned_closeobjectoptional
- auto_reopen_on_regressionobjectoptional
- binding_change_resets_evidenceobjectoptional
- blocked_by_blocks_closeobjectoptional
- close_on_commit_keywordobjectoptional
- default_assignee_from_codeownersobjectoptional
- default_issue_typeobjectoptional
- on_branch_createdobjectoptional
- on_mr_closedobjectoptional
- on_mr_mergedobjectoptional
- on_mr_openedobjectoptional
- override_group_settingsobjectoptional
- public_issue_filingobjectoptional
- require_verified_criteria_to_closeobjectoptional
statuses[]object6 fields
- archivedbooleanoptional
- categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - colorobjectoptional
- is_defaultbooleanoptionalThe status new issues land in. Exactly one status in a set carries it, and it must be open.
- namestring
- status_idstring
- todo_policyobjectoptional
- todo_promote_typeobjectoptional
Refuses
400Empty body, or an invalid status set401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape update_repo_issue_settings returns — 19 fields. Go to it
Show it here
- anchor_drift_actionobjectoptional
- auto_close_on_verifiedobjectoptional
- auto_reopen_on_orphaned_closeobjectoptional
- auto_reopen_on_regressionobjectoptional
- binding_change_resets_evidenceobjectoptional
- blocked_by_blocks_closeobjectoptional
- close_on_commit_keywordobjectoptional
- default_assignee_from_codeownersobjectoptional
- default_issue_typeobjectoptional
- on_branch_createdobjectoptional
- on_mr_closedobjectoptional
- on_mr_mergedobjectoptional
- on_mr_openedobjectoptional
- override_group_settingsobjectoptional
- public_issue_filingobjectoptional
- require_verified_criteria_to_closeobjectoptional
statuses[]object6 fields
- archivedbooleanoptional
- categoryblockedcancelleddonein_progressin_reviewtodotriageThe fixed category behind a status. A status also has a name, which the team owns and may
rename freely; the category is the part the platform reasons about. A team can call a status
"Ready for QA" and the platform still knows it is
in_review— so a board can place it in a column, a merge can move it, and a progress rollup can count it as not done. - colorobjectoptional
- is_defaultbooleanoptionalThe status new issues land in. Exactly one status in a set carries it, and it must be open.
- namestring
- status_idstring
- todo_policyobjectoptional
- todo_promote_typeobjectoptional
DELETE/groups/{group_id}/issue-settingsissue_settings:manage
Remove a group's issue settings, returning it to full inheritance
Token scope
issue_settings:manage
Send
Path
- group_iduuidGroup ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Maintainer required404Not found — or found and private, which is masked as absent409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
Limits
Five limits on this page scale with your plan. Each is checked as part of the write, so a refused request creates nothing at all — there is no half-filed work item and no orphaned label.
| What is counted | Free | Pro | Team | Enterprise |
|---|---|---|---|---|
| Open work items in one repository or group | 5,000 | 20,000 | 100,000 | 500,000 |
| Label definitions in one repository or group | 200 | 500 | 2,000 | 5,000 |
| Milestones in one repository or group | 100 | 500 | 2,000 | 5,000 |
| Relations on one work item | 25 | 50 | 100 | 200 |
| Children under one work item | 200 | 500 | 2,000 | 5,000 |
The open work-item count is what its name says: open, not total. Closing or deleting an item gives the slot back immediately, so a repository at its ceiling is a repository with a real triage problem, and the fix is to close what is done rather than to buy a bigger number. Reopening an item takes a slot again, and moving an open one into another container takes a slot there — which is why both can be refused with 429 TOO_MANY_REQUESTS. The relation cap is checked at both ends, so a relation can be refused because the far item is full rather than the one you are working on.
Four further limits are the same on every plan, because they are product shape rather than capacity:
| What is counted | Limit |
|---|---|
| Assignees on one work item | 5 |
| Labels on one work item | 10 |
| Levels of nesting | 5 |
| Statuses in one status set | 30 |
Going over one of these is a 400 BAD_REQUEST and nothing is truncated silently — a cap that quietly drops the sixth assignee is a cap that has quietly stopped protecting anything. One further bound is a 409 CONFLICT rather than a 400: a single reparent refuses to move a subtree of more than 1,000 items, so move its branches separately.
To raise a plan limit, ask for a limit increase from the group's usage page. It goes to a person, who answers with the number they can give you.
Troubleshooting
400 BAD_REQUESTon any call, mentioning an id
- Cause
- A path parameter is not a well-formed value — usually a path like
my-group/my-repopasted where an id belongs, or a work-item number that is not a number - What to do
- Use the container's id and the item's numeric reference.
#412is written412in a URL
400 BAD_REQUESTon create, mentioning the title
- Cause
- The title is blank, is blank after trimming, or is longer than 255 characters
- What to do
- Shorten it and move the detail into the description, which takes markdown up to 128 KiB
400 BAD_REQUESTnaming a field the type does not support
- Cause
- You set a field the work-item type does not declare —
pointson a bug,severityon a task, a milestone on a sub-task, a parent on a spike, a chore or a sub-task - What to do
- Drop the field, or change the item's type first. Clearing a field is always allowed, so a type change can shed one on the way
400 BAD_REQUESTabout a type and its container
- Cause
- An epic was filed in a repository, or a repository-only type in a group
- What to do
- File epics in a group and stories, bugs, tasks, spikes, chores and sub-tasks in a repository.
incidentis the one type either takes
400 BAD_REQUESTnaming two labels that share a prefix
- Cause
- One request supplied
priority::highandpriority::lowtogether, which are mutually exclusive - What to do
- Send one. Applying a scoped label to an item already carrying a sibling replaces it, so you never need both in one call
400 BAD_REQUESTon adding a label, saying it is not defined
- Cause
- The key is defined neither in this container nor in any group above it
- What to do
- Define the label first — that needs Maintainer — then apply it. Check the spelling: keys are lowercase letters, digits and hyphens
400 BAD_REQUESTat 5 assignees or 10 labels
- Cause
- The per-item limits, which are refused rather than truncated
- What to do
- Remove one before adding another. These do not change with your plan
400 BAD_REQUESTon close, saying the status is open
- Cause
- You named a status whose category is open. Closing needs a completed or cancelled one
- What to do
- Leave the status out to take the container's default completed status, or name one of the closed statuses the container defines
400 BAD_REQUESTon reparenting, about depth
- Cause
- The move would put some item in the subtree past the fifth level. The cap has to hold for the deepest descendant, not just the item you named
- What to do
- Flatten part of the subtree first, or attach it higher up the tree
400 BAD_REQUESTon a listing, mentioning the cursor or a filter
- Cause
- The paging token is malformed, or it came from a different listing family, or a filter value is not a valid status category, type, assignee, label or milestone id
- What to do
- Pass back the exact
next_tokenthe previous page returned, and check the filter value against the enumerations the card names. A misspelled filter value is refused rather than ignored, on purpose
400 BAD_REQUESTon saving settings
- Cause
- The body named no field at all, or the status set is unusable — no unarchived completed status, no unarchived open status, no default, more than one default, a default that is closed, a duplicate id, more than 30 statuses, or a category changed on an existing status
- What to do
- Send at least one field, and fix the set against those rules. To move work into a different category, add a new status and archive the old one; a category is fixed once its status exists
401 UNAUTHORIZED
- Cause
- No credential was sent, or the one sent is invalid or expired
- What to do
- Sign in again, or mint a fresh token. The personal listings need a credential even for work in public repositories, because they are keyed on who you are
403 FORBIDDENon filing, in a repository you can read
- Cause
- Filing needs real Reporter membership, and the public-read shortcut deliberately does not extend to writes
- What to do
- Ask an Owner or Maintainer to add you to the repository or a group above it. For a public container that wants outside reports, a Maintainer can instead turn on public filing in its issue settings
403 FORBIDDENon updating somebody else's item
- Cause
- Changing an item is Developer. The author exception covers only your own items
- What to do
- Ask for Developer access, or comment on the item and ask its assignee to make the change
403 FORBIDDENon delete or move, where closing works
- Cause
- Deleting and moving need Maintainer, and there is no author exception on either
- What to do
- Close or cancel the item instead, or ask a Maintainer. Closing keeps the record, which is usually what you wanted
403 FORBIDDENon minting a label, milestone or workflow settings
- Cause
- Defining shared vocabulary is Maintainer even though applying it is Developer
- What to do
- Ask a Maintainer to define it once; after that anybody with Developer access can apply it
403 INSUFFICIENT_SCOPE
- Cause
- The token is valid but was minted without the scope this call needs
- What to do
- Mint a new token carrying the scope named in the response —
issue:create,issue:update,issue:delete,label:manage,milestone:manageorissue_settings:manage. Scopes are fixed at mint time
404 NOT_FOUNDon a repository or group you are sure exists
- Cause
- Either it is private and you are not a member, or the id is wrong
- What to do
- A private container answers
404rather than403so that its existence stays private. Check your membership, then check the id
404 NOT_FOUNDon a work-item number that is on your screen
- Cause
- The item has been moved to another container, or deleted. A move gives it a new number
- What to do
- Search for the title. A moved item's response named its new reference at the time of the move
404 NOT_FOUNDwhen setting a milestone that exists
- Cause
- The milestone belongs to a different container. A work item may only take a milestone its own container defines
- What to do
- Create the milestone in this container, or move the item to the container that owns the milestone
404 NOT_FOUNDon removing an assignee or a relation
- Cause
- That assignee or relation is not on the item — often because somebody else already removed it
- What to do
- Re-read the item. The state you wanted is the state you have. Removing a label or a milestone that is not there answers
200with the item unchanged, so only these two report the absence
409 CONFLICTon update, mentioning the version
- Cause
- Somebody — or something — changed the item after you read it. Merges, commit messages and pipeline results all write to the same item
- What to do
- Re-read the item, re-apply your change on top of the current version, and send it again
409 CONFLICTon close, about criteria or blockers
- Cause
- The container requires acceptance criteria to be verified before completion, or refuses to complete an item with an open
blocked_by - What to do
- Satisfy the failing criteria, or close the blocking item. Cancelling is exempt from both gates, so an abandoned item can always be closed
409 CONFLICTabout a transition
- Cause
- The container's workflow does not allow this category to move to that one. The response names the categories it does allow
- What to do
- Move through an allowed status, or relax the transition table in the container's issue settings
409 CONFLICTon close or reopen, saying already
- Cause
- The item is already in the state you asked for
- What to do
- Nothing to do. Re-read the item to see who got there first
409 CONFLICTon reparenting, about a cycle, a type or a subtree size
- Cause
- The proposed parent already sits beneath this item, or its type may not parent this type, or the subtree being moved is larger than 1,000 items
- What to do
- Detach first, then reparent; for a large subtree, move its branches one at a time. An epic parents nearly everything; a task, spike, chore or sub-task parents nothing
409 CONFLICTon retyping
- Cause
- The new type cannot sit under the parent the item has, or cannot hold the children it has
- What to do
- Detach the parent or the children, retype, then reattach whatever is still legal
409 CONFLICTon delete, about children
- Cause
- The item still has children, and orphaning a subtree is not something a delete does silently
- What to do
- Reparent or delete the children first, then delete the item
409 CONFLICTon adding a relation
- Cause
- That relation already exists between those two items
- What to do
- Re-read the item rather than retrying — a relation is written on both ends at once, so it is already visible from both
409 CONFLICTon setting a milestone
- Cause
- The milestone is closed
- What to do
- Reopen the milestone, or choose an open one
409 CONFLICTon assigning somebody
- Cause
- The person or service account is not a member of this container, so they could not open the item they were being given
- What to do
- Add them to the repository or a group above it at Reporter or higher, then assign. Being able to read a public repository is not membership
409 CONFLICTon creating a label or a milestone
- Cause
- A label with that key, or a milestone with that title, already exists in this container
- What to do
- Pick another key or title, or edit the existing one. Nothing about the existing one is changed
429 TOO_MANY_REQUESTSon filing, reopening or moving
- Cause
- The container is at its open work-item limit
- What to do
- Close what is finished — the count is of open items, so a slot comes back immediately — or ask for a limit increase from the group's usage page
429 TOO_MANY_REQUESTSon adding a relation
- Cause
- One of the two items is at its relation limit. The cap is checked at both ends, so the item that is full may be the far one rather than the one named in the URL
- What to do
- Read both items' linked-item lists and drop a relation neither needs.
relates_tolinks added for context are usually the ones to lose;blocksandblocked_byare the ones somebody is scheduling against
429 TOO_MANY_REQUESTSon setting a parent, or on filing an item under one
- Cause
- The new parent is at its child limit. The item you are moving does not count against it, so re-saving something already under that parent is never refused
- What to do
- Give the parent an intermediate child — an epic of stories rather than an epic of tasks — or move some children elsewhere. Nothing was reparented
429 TOO_MANY_REQUESTSon creating a label or milestone
- Cause
- The container is at its label or milestone limit
- What to do
- Delete the ones nobody uses, define shared vocabulary once on a group instead of once per repository, or ask for a limit increase
A work item closed itself and nobody closed it
- Cause
- A commit message said
Closes #412on the default branch or a closing branch, or a merge request that said the same thing merged into one of those branches - What to do
- Read the item's activity — every automatic change names what caused it. Turn the keyword off in the container's issue settings if it is not the behaviour you want, or narrow the closing branches so only the default one closes work
A closed work item reopened itself
- Cause
- Either the test bound to one of its criteria went red on the default branch, or the commit that closed it is no longer in any branch after a force-push or an unmerged branch delete
- What to do
- Read the activity, which names the run or the commit. Both behaviours are settings on the container and can be turned off
An item is missing from a group listing or a rollup total
- Cause
- It lives in a repository the caller cannot read. Cross-container listings authorize each row's own repository and drop the ones that fail
- What to do
- Join the repository, or read the listing from an account that is a member. A rollup deliberately reports no hidden count, so the totals two people see can legitimately differ
Labels stayed behind after a move
- Cause
- Neither the destination nor a group above it defines them, and a label is a definition local to the container that minted it
- What to do
- The move's response names every label and milestone that could not come along. Define those keys in the destination — or once on a group above both containers, which is what stops it happening again — then re-apply them to the item. Doing it in that order before the next move keeps them
An automatic status change did not happen on merge
- Cause
- The container's transition table has no legal edge from the item's current category to the one the automation wanted
- What to do
- Read the item's activity — the skipped transition is recorded with the reason. A workflow constraint never fails a merge; it only declines to move the item
FAQ
Why did the numbers skip?
A deleted work item leaves its number behind, and nothing reuses it. #412 is a name, not a count.
Can an epic hold work from several repositories?
Yes — that is why epics live in groups. Set the epic as the parent of items in any repository beneath it, and its rollup counts them all.
What is the difference between cancelling and deleting?
Cancelling closes the item without completing it, and keeps every word of the discussion and the whole activity trail. Deleting destroys them. Cancel by default.
Why can I not put a group's milestone on a repository's work item?
A milestone reads its members from the container it lives in, so a member from somewhere else would be invisible to its own progress figures. Create the milestone where the work is, or file the work where the milestone is.
Do labels have to be defined in every repository?
No. Define shared vocabulary once on a group and every repository beneath it can apply it. A repository may re-define the same key to change its colour locally.
Can I search work items with an arbitrary query?
The filters combine — status, category, type, assignee, label, milestone and free text — and every combination is fast because each one is anchored to a container or to you. There is no boolean query language over arbitrary fields. For finding something across everything you can read, use search.
Related
- Work item discussioncomments, threads, resolving and reactions on a work item
- Proof of Doneacceptance criteria a pipeline verifies, and the gates that read them
- Linking work to codecommit-message actions, links to commits and merge requests, code anchors and TODO markers
- Blueprintscustom work-item types for a repository or a group
- Merge requeststhe change that closes the work, and the gates that hold it
- Searchfinding a work item you cannot name, across everything you can read
- Groupsthe namespaces work items are inherited and filtered through, and where you ask for a limit increase
- Access tokensminting a token with the issue scopes a script needs