Your dashboard
- See what needs you
- Show the pending count
- Mark an item done
- Snooze an item until later
- Bookmark something to come back to
- Remove an item from your inbox
- Read your headline numbers in one request
- Review what you did
- Look at somebody else's activity
- Follow one repository's timeline
- Follow a whole group
- See where your time went
- Measure a repository's flow
- Read exact cycle times
- Compare repositories across a group
Overview
Your dashboard is the screen that tells you what to do next. It keeps an inbox of the things waiting on you — reviews you owe, work assigned to you, a deployment waiting on your approval — and most items leave on their own the moment the thing that put them there is settled, so an empty inbox means you are genuinely clear rather than that you stopped looking. Alongside it sit a timeline of what happened, a summary of your open work, and flow metrics for any repository or group you can see.
Everything here is a read except four small writes on the inbox itself: mark an item done, snooze it, bookmark something, or throw an item away. Nothing on this page changes a merge request, a work item or a pipeline — the dashboard points you at them and you act there.
Before you start
- A signed-in account for anything personal.Your inbox, your feed, your summary and your most-active list are all keyed to you and answer
401without a credential. A repository's activity, a group's activity and the insight reads are not: a public repository or group answers anyone, signed in or not. A profile feed answers anonymously too, showing whatever of that person's work is public. - Access to the thing you are reading.A repository's activity and its insights need Reporter on the repository, and a group's need Reporter on the group. Public and internal resources short-circuit that — anyone who can already see the resource can read both, without a membership. A private resource answers
404to a non-member rather than403, so its existence stays private. Bookmarking something needs enough access to view it, by the same rules. - Token scopes, if you are calling the API or the CLI.
These surfaces cross domains and none of the scopes implies another:
What you are reading or writing Scope your inbox, the badge, and your own activity feed attention:readmark done, snooze, bookmark, remove attention:writeyour summary counters and where you have been most active dashboard:readflow metrics and cycle times insights:reada repository's activity repo:reada group's activity group:readanother person's activity user:readinsights:readis deliberately separate fromrepo:read, so a token that clones your code does not thereby learn your team's review latency. - Something to have happened.Every surface here is built from events the platform has already recorded, so a brand-new account has an empty inbox, an empty feed and insights full of zeros. The recording happens after the request that caused it, so an item shows up a moment later rather than in the same response.
- Ids, not paths.The repository, group and user reads all take an id. If all you have is
acme/platform/checkout, resolve it to an id first. - A person, not a service account, for the personal reads.Your feed, your summary and your most-active list resolve visibility against a user, so a service-account token gets an honest answer rather than a wrong one: the most-active list comes back empty, the summary comes back as zeroes with no namespaces beside its own inbox count, and the feed shows public activity only. The inbox itself works the same for either.
How it works
The dashboard asks four questions at once, and each has its own surface with its own rules.
| Question | Surface | Keyed to |
|---|---|---|
| What needs me? | the attention inbox | you |
| What am I working on? | the summary counters and your most-active list | you |
| What happened? | four activity feeds | you, a person, a repository, or a group and everything under it |
| How are we doing? | insights and cycle time | a repository or a whole group |
An inbox item is a condition, not a message
An item is one row per thing that is true about you right now — "you have been asked to review this merge request", not "somebody asked you to review this merge request at 09:12". Two consequences follow, and together they are the whole design.
Repeats collapse. Being asked twice to review the same merge request is one item that moves back to the top, not two items, and being mentioned twice on the same work item is likewise one item. Some conditions are deliberately finer-grained: a rejected review is keyed per reviewer, because two people asking for changes are two things to address; a failed completion criterion is keyed per criterion, because two failing criteria are two things to fix; and a deployment gate is keyed per node, because two gated nodes in one run are two decisions.
Items leave on their own. When the condition clears, the item is marked done without you touching it. Approve the review and your item goes; merge the request and every reviewer's item goes with it. A bookmark is the one reason with no clearing condition at all — it waits until you clear it. A mention has none of its own either, and goes only when the work item it was left on closes.
a matching event ───► pending ──(you snooze)──► snoozed │ ▲ │ │ you mark it done, or │ └──(the snooze expires)──┘ │ the condition clears │ │ ▼ the condition clears │ done ◄──────────────────────────┘ │ └──(the condition genuinely recurs)──► pending removing an item deletes the row from any state; the next matching event creates it againDone and removed are different. Marking an item done says I have dealt with this, and only a later event for the same condition brings it back. Removing it says get this off my screen, and because nothing is left to compare against, the very next matching event — including a redelivery of the one that created it — puts it back. Removing a review request does not decline the review.
A snooze does not detach an item from its condition. Snooze a review request, then approve the merge request, and the item is done rather than waiting to reappear. Waking is not a scheduled job either: an item whose snooze time has passed simply reads as pending on your next request.
The platform never puts your own actions in your own inbox. Commenting on your own work item does not raise an item for you, and neither does mentioning yourself.
The inbox is a surface, not a delivery channel. Nothing in it is emailed or pushed to you; you read it, and it decays to empty on its own as the conditions behind it settle.
What puts an item in front of you
Each item carries a reason, which is what makes an inbox skimmable rather than a pile of links.
| Reason | What puts it there | What clears it on its own |
|---|---|---|
review_requested | you were added as a reviewer | you approve or reject, you are removed as a reviewer, or the merge request merges or closes |
changes_requested | a reviewer rejected your merge request | that same reviewer approves it, or the merge request merges or closes |
mr_ready_to_merge | every approval rule that applies to your merge request has the approvals it needs | it merges or closes, or a rule stops being satisfied |
mr_restack_required | your stacked merge request needs restacking | the merge request merges or closes |
assigned | a work item was assigned to you | you are unassigned from it, or it closes |
issue_commented | somebody else commented on a work item you wrote or are assigned | the work item closes |
criterion_failed | a completion criterion failed on a work item you wrote or are assigned | any criterion on that work item verifies, or the work item closes |
issue_regressed | a work item you are assigned regressed | it verifies again, or it closes |
mentioned | somebody @-mentioned you in a work-item comment | the work item closes |
deployment_approval_requested | a deployment is waiting on an approval, and its gate names you — directly, through a team you are on, or through a role you hold on the group or repository it names. A role you hold only through a group above that one does not raise an item | the gate is decided, or the run ends |
pipeline_not_started | a pipeline your push or merge should have started could not start — its definition names something that does not exist, a connection is missing, a limit is reached. The item points at the repository and names the pipeline and the reason | a run of that pipeline on that branch or tag starts, whoever starts it — including retrying the refusal once the reason is fixed |
access_granted | somebody gave you access to a group or repository — the item points at it — or put you on one of an organisation's teams, when it points at the organisation | nothing — mark it done once you have seen it |
access_expiring | access you hold, or access you gave somebody, ends within a week. Each of you gets the item once | nothing — the access ends on its own date |
marked | you bookmarked it yourself | nothing — it waits for you |
Marking an item done clears it sooner than any of that, and for a bookmark it is the only thing that ever will. A deployment gate that names no approvers raises no item at all — an unnamed gate is open to anyone with Developer on the repository, which is not a list to put anything in front of.
Five more values are accepted by the reason filter and match nothing, because no condition produces them: review_approved, mr_unmergeable, mr_commented, blocked_by_resolved and pipeline_failed. Filtering on one is a valid request that returns an empty page.
Access is checked on every read, not on a schedule
An item names its target and copies nothing from it — no title, no body, no snapshot of anybody's name. Who caused it is read live as well, through the account as it stands now. Every read of the inbox, including the badge count, re-checks that you can still see each item's target, so losing access to a repository takes its items out of your very next response with no sweep in between. Because nothing is copied, an item can never show you a stale title, and a renamed or moved target reads correctly when you open it.
Removal is the one deliberate exception. It matches on the item's id and your ownership alone, which is what lets you clear an item whose target you can no longer open.
Feeds are chronological by when things happened
An activity entry is stamped with the source event's own clock, so a delayed event lands in the feed where it belongs in time rather than at the top. Feeds keep 90 days; the daily counts behind insights are permanent, so activity that has aged out of the feed is still counted in every metric.
How to
See what needs you
The inbox comes back most-recently-touched first, and by default it shows only what is pending — including anything whose snooze has expired. Narrow it with state (pending, snoozed, done or all), with one or more reasons, and with the kind of thing an item points at (merge_request, issue, pipeline_run, repository or group). Unknown filter values are refused rather than quietly ignored, so a filter that returns rows is a filter the platform understood.
Open Home and read the Needs your attention panel, or choose Attention in the side navigation for the full list. Each row shows why it is there, what it points at, who caused it and when. The reason chips along the top filter the list; the Snoozed and Done tabs show the other two states, and All shows everything. Each row links straight through to the merge request, work item, pipeline run or repository it names.
gitmoap attention list-my-attention-itemscurl -X GET https://api.gitmoap.example/user/attention \ -H "Authorization: Bearer $GITMOAP_TOKEN"Show the pending count
The badge is a separate, cheap read: a total plus a breakdown by reason, so a navigation bar can render "7" and a tooltip saying which seven without loading the list. It counts to 100 and then stops — past that, truncated is true and the number is a floor.
The count appears on the Attention entry in the side navigation and refreshes with the page. Hover it for the by-reason breakdown. At a hundred or more it reads 99+.
gitmoap attention count-my-attention-itemscurl -X GET https://api.gitmoap.example/user/attention/count \ -H "Authorization: Bearer $GITMOAP_TOKEN"Mark an item done
Marking done is the ordinary way to empty the inbox of things nothing else is going to clear — a bookmark, a mention on a work item that is staying open, an item you have decided to handle later in some other system. Doing it twice is harmless and returns the same item.
Choose the tick at the end of the item's row, or open the item and choose Mark done. The row moves out of Pending and into the Done tab immediately; there is no confirmation, because the item comes back if the condition recurs.
gitmoap attention resolve-attention-item --attention-id <id>curl -X POST https://api.gitmoap.example/user/attention/{attention_id}/done \ -H "Authorization: Bearer $GITMOAP_TOKEN"Snooze an item until later
Snoozing hides an item until a time you choose, between one minute and 90 days from now, given as an RFC-3339 timestamp. Past ninety days you are not deferring the item, you are ignoring it, and marking it done is the honest way to say so.
Choose the clock at the end of the row and pick Later today, Tomorrow, Next week or a date and time of your own. The row disappears from Pending and reappears there by itself once the time passes — you do not need to reload anything on a schedule.
gitmoap attention snooze-attention-item --attention-id <id> --until <until>curl -X POST https://api.gitmoap.example/user/attention/{attention_id}/snooze \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "until": "<string>" }'A snoozed item still resolves automatically. If the merge request merges while the item is hidden, it goes to done rather than coming back.
Bookmark something to come back to
This is the one write where you choose the target: a merge request, a work item, a pipeline run, a repository or a group you can view, saved into your own inbox with the reason marked. The body carries the target's kind and the fields that kind needs, plus an optional note of up to 280 characters saying why you saved it — the only free text the inbox stores, and it is your own.
Choose Save to my inbox from the overflow menu on a merge request, work item, pipeline run or repository page. A short note field appears; fill it in or leave it empty and choose Save. The item shows up in your inbox straight away, tagged marked, and stays until you clear it.
gitmoap attention create-attention-bookmarkcurl -X POST https://api.gitmoap.example/user/attention \ -H "Authorization: Bearer $GITMOAP_TOKEN"Bookmarking the same thing twice is refused with 409 rather than creating a second copy, and a target you cannot view answers 404 — the same answer a target that does not exist gives, so nothing leaks.
Remove an item from your inbox
Warning
Removing an item deletes it outright, along with any note you wrote on a bookmark, and there is no undo. Removing a bookmark loses your note permanently. Removing an item the platform raised does not decline anything — it takes the row away, and the next matching event recreates it, so removing a review request neither declines the review nor stops the reminder returning. If you want an item gone for good, mark it done instead.
Removal is the escape hatch for an item you can no longer see: if you lost access to a repository, its items vanish from your listings but still occupy a slot against your inbox limit, and removing them by id is how you get that slot back.
Choose the bin icon at the end of the row, or Remove from the item's overflow menu. The confirmation names what the item points at. Removal is immediate.
gitmoap attention delete-attention-item --attention-id <id>curl -X DELETE https://api.gitmoap.example/user/attention/{attention_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Read your headline numbers in one request
The summary is the envelope a dashboard renders before any content arrives: your pending attention count and its breakdown, how many merge requests you have open, how many reviews are waiting on you, how many work items are assigned to you, how many pipeline runs failed in the last 7 days, your current contribution streak, whether your getting-started checklist is finished, and a line per namespace with its plan and storage use.
The badge and the four counters beside it stop at 100. The response names every one that reached the ceiling in a truncated list and echoes the ceiling itself as count_cap, so a client can render "100+" without hardcoding a number the platform owns. Your contribution streak is not one of the capped counters; it is measured over the trailing year. The response enumerates at most 10 namespaces, and truncated says so when there are more.
This is what fills the tiles across the top of Home: the attention badge, open merge requests, reviews waiting on you, assigned work items, recent pipeline failures and your streak, plus a storage bar per namespace you belong to. The tiles paint first and the panels beneath them fill in behind.
gitmoap dashboard get-my-dashboard-summarycurl -X GET https://api.gitmoap.example/user/dashboard/summary \ -H "Authorization: Bearer $GITMOAP_TOKEN"Review what you did
Your own feed spans every group you can reach and defaults to the trailing 30 days. Filter it by domain — merge_request, issue, repository, release or pipeline — and set an explicit window with from and to in RFC-3339. A window may span at most 366 days. The member domain is accepted and matches nothing, because membership changes raise no feed line.
Open Home and read the Your activity panel, or choose Activity in the side navigation. The domain chips filter it and the date range picker sets the window. Each line names what you did, what you did it to and which repository or group it happened in.
gitmoap activity list-my-activitycurl -X GET https://api.gitmoap.example/user/activity \ -H "Authorization: Bearer $GITMOAP_TOKEN"Entries carry a kind that says what happened: opened, merged, closed, reopened, reviewed, review_withdrawn, reviewer_added, reviewer_removed, retargeted and restacked on merge requests; opened, closed, reopened, assigned, unassigned, commented, criterion_failed, criterion_verified, regressed and verified on work items; pushed on repositories; created and published on releases; run_succeeded, run_failed, run_cancelled and run_timed_out on pipelines. One push is one entry however many branches it moved, with the branch detail in the entry's metadata.
Look at somebody else's activity
A profile feed shows what a person did, filtered by what you can see — so two people reading the same profile see different feeds, and neither sees anything they could not already open. A person whose work is all in repositories you cannot reach returns an empty page rather than a refusal; only an account that does not exist answers 404.
Open a person's profile and choose the Activity tab. The same domain filters and date range apply. Lines you cannot open are not there to begin with.
gitmoap activity list-user-activity --user-id <id>curl -X GET https://api.gitmoap.example/users/{user_id}/activity \ -H "Authorization: Bearer $GITMOAP_TOKEN"Your own feed and a profile feed are already one person's work, so the actor filter narrows nothing on either of them. It is the repository and group feeds where it earns its place.
Follow one repository's timeline
A repository's feed is every domain in one stream: merge requests, work items, pushes, releases and pipeline runs. Narrow it to one person with actor when you want to know what a single contributor did in one place.
Open the repository and choose Activity. The stream mixes every domain by default; the chips narrow it, and the actor filter narrows it to one person. Pushes show the branch and how many refs moved.
gitmoap activity list-repo-activity --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/activity \ -H "Authorization: Bearer $GITMOAP_TOKEN"Follow a whole group
A group's feed covers the group and every group and repository beneath it, however deep. A group routinely mixes public, internal and private repositories, so the feed is filtered per line: being a Reporter on the parent shows you the parent's activity, not the private repositories underneath it.
Open the group and choose Activity. The stream covers the whole subtree, with each line labelled by the repository or subgroup it came from. The same domain, actor and date filters apply.
gitmoap activity list-group-activity --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/activity \ -H "Authorization: Bearer $GITMOAP_TOKEN"See where your time went
Where you have been most active over a window, busiest first, each entry with the split behind the total: commits, merge requests, reviews, releases and work items. Most entries are repositories; a group appears when you have worked on something the group itself owns, such as a group-level work item. The default window is the trailing 30 days and the default page is the top 10, up to 25. Dates here are calendar days (YYYY-MM-DD), not timestamps, because the counts behind them are daily.
The Where you've been active panel on Home ranks your repositories for the chosen window and shows the breakdown as a stacked bar per row. Change the window with the range picker at the top of the panel.
gitmoap insights list-my-top-repositoriescurl -X GET https://api.gitmoap.example/user/top-repositories \ -H "Authorization: Bearer $GITMOAP_TOKEN"Measure a repository's flow
Repository insights answer how is work moving through here: merge requests opened, merged and closed; reviews submitted; work items opened and closed; pushes; releases published; pipeline runs total, succeeded and failed. You get a total per metric, a bucketed series you can plot at day, week or month, means for time-to-merge, time-to-first-review and run duration, and a count of distinct contributors. The window is calendar days, to is inclusive, and it defaults to the trailing 30 days.
Two DORA metrics come back under names that describe what was actually measured — release frequency per week, counting published, non-draft releases, and merge lead time, which is the median time from opening a merge request to merging it. Change failure rate and time to restore come back null, each with a machine-readable reason beside it in unavailable, because no honest number exists for them without a record of what was deployed. A confident wrong figure is worse than a gap.
Open the repository and choose Insights. The header carries the date range and the day/week/month toggle; below it are the throughput totals, the chart, the means and the DORA block. Metrics with no honest value render as a labelled gap rather than a zero.
gitmoap insights get-repo-insights --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/insights \ -H "Authorization: Bearer $GITMOAP_TOKEN"Read exact cycle times
Means hide their tails, so the percentiles are a separate read: p50 and p95 for time to merge, time to first review, work-item cycle time and pipeline duration, each with the number of samples behind it. n matters — a median of seven merge requests should be read differently from a median of twenty thousand — and truncated tells you when the window hit the 20 000-row sample ceiling, meaning the percentiles cover only the most recent 20 000 rows and n stops there.
A duration with nothing measurable in the window reports n of 0 and omits both percentiles rather than reporting them as zero — an absent p50 and a p50 of zero are deliberately different answers.
The Cycle time panel under a repository's Insights tab shows the four durations as p50 and p95 pairs, with the sample count under each. A duration with no samples in the window is shown as a dash.
gitmoap insights get-repo-cycle-time --repo-id <id>curl -X GET https://api.gitmoap.example/repositories/{repo_id}/insights/cycle-time \ -H "Authorization: Bearer $GITMOAP_TOKEN"Compare repositories across a group
Group insights roll the same metrics up over the group and everything beneath it, at any depth, filtered to the repositories you can see. Add breakdown=repository for a per-repository split of the totals, capped at the 25 busiest by merges, pushes and work items closed — the response sets breakdown_truncated when there were more, so a chart can say "the top 25 of 60" instead of presenting a slice as the whole.
The group read reports means and carries no merge lead time at all, because a median over a whole subtree means reading every merge request in it. When you want the median, ask a single repository for its cycle time.
Open the group and choose Insights. The totals, the chart and the DORA block read like a repository's, without the merge lead time; the Break down by repository toggle adds a per-repository split, and a banner tells you when only the busiest repositories are shown.
gitmoap insights get-group-insights --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/insights \ -H "Authorization: Bearer $GITMOAP_TOKEN"Reference
15 endpoints
GET/user/attentionattention:read
List the caller's attention inbox
Token scope
attention:read
Send
Query
- statestringoptionalpending (default) | snoozed | done | all
- reasonstringoptionalComma-separated attention reasons
- target_kindstringoptionalmerge_request | issue | pipeline_run | repository
- limitint32optionalPage size (1-50, default 20)
- next_tokenstringoptionalPagination cursor
Refuses
400Unknown filter value or malformed cursor401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
items[]object11 fields
- actorobjectoptional
- attention_iduuid
- created_atstring
- noteobjectoptionalYour own note, on a bookmark only.
- principal_iduuid
- reasonaccess_expiringaccess_grantedassignedblocked_by_resolvedchanges_requestedcriterion_faileddeployment_approval_requestedissue_commentedissue_regressedmarkedmentionedmr_commentedmr_ready_to_mergemr_restack_requiredmr_unmergeablepipeline_failedpipeline_not_startedreview_approvedreview_requestedWhy an item is in front of you.
- resolved_atobjectoptional
- snoozed_untilobjectoptional
- statedonependingsnoozedWhere an item is in its life.
- targetobjectThe thing an attention item points at.
kindsays which, and decides the other fields. - updated_atstring
- next_tokenobjectoptional
GET/user/attention/countattention:read
Count the caller's pending attention items, broken down by reason
Token scope
attention:read
Send
Nothing — the address is the whole request.
Refuses
401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
- by_reasonobjectReasons with at least one pending item, keyed by the wire name.
- pendingint64A capped count. When
truncated, this is the cap and the client renders "99+". - truncatedboolean
POST/user/attention/{attention_id}/doneattention:write
Mark an attention item done
Token scope
attention:write
Send
Path
- attention_iduuidAttention item ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Not authenticated403Forbidden — the caller's access level or token scope is insufficient404No such item for this caller409The request conflicts with the resource's current state; `reason` says how
Receive
- actorobjectoptional
- attention_iduuid
- created_atstring
- noteobjectoptionalYour own note, on a bookmark only.
- principal_iduuid
- reasonaccess_expiringaccess_grantedassignedblocked_by_resolvedchanges_requestedcriterion_faileddeployment_approval_requestedissue_commentedissue_regressedmarkedmentionedmr_commentedmr_ready_to_mergemr_restack_requiredmr_unmergeablepipeline_failedpipeline_not_startedreview_approvedreview_requestedWhy an item is in front of you.
- resolved_atobjectoptional
- snoozed_untilobjectoptional
- statedonependingsnoozedWhere an item is in its life.
- targetobjectThe thing an attention item points at.
kindsays which, and decides the other fields. - updated_atstring
POST/user/attention/{attention_id}/snoozeattention:write
Snooze an attention item until a chosen time
Token scope
attention:write
Send
Path
- attention_iduuidAttention item ID
Body
- untilstringWhen the item comes back, RFC 3339. Between one minute and ninety days from now.
Refuses
400`until` is in the past or beyond 90 days401Not authenticated403Forbidden — the caller's access level or token scope is insufficient404No such item for this caller409The request conflicts with the resource's current state; `reason` says how
Receive
The same shape resolve_attention_item returns — 11 fields. Go to it
Show it here
- actorobjectoptional
- attention_iduuid
- created_atstring
- noteobjectoptionalYour own note, on a bookmark only.
- principal_iduuid
- reasonaccess_expiringaccess_grantedassignedblocked_by_resolvedchanges_requestedcriterion_faileddeployment_approval_requestedissue_commentedissue_regressedmarkedmentionedmr_commentedmr_ready_to_mergemr_restack_requiredmr_unmergeablepipeline_failedpipeline_not_startedreview_approvedreview_requestedWhy an item is in front of you.
- resolved_atobjectoptional
- snoozed_untilobjectoptional
- statedonependingsnoozedWhere an item is in its life.
- targetobjectThe thing an attention item points at.
kindsays which, and decides the other fields. - updated_atstring
POST/user/attentionattention:write
Bookmark a merge request, work item, pipeline run or repository into your own inbox
Token scope
attention:write
Counts against
attention_items_per_principal
Send
Nothing — the address is the whole request.
Refuses
400Target fields do not match `kind`401Not authenticated403Forbidden — the caller's access level or token scope is insufficient404Target does not exist, or the caller cannot view it409Already bookmarked429Inbox is full
Receive
The same shape resolve_attention_item returns — 11 fields. Go to it
Show it here
- actorobjectoptional
- attention_iduuid
- created_atstring
- noteobjectoptionalYour own note, on a bookmark only.
- principal_iduuid
- reasonaccess_expiringaccess_grantedassignedblocked_by_resolvedchanges_requestedcriterion_faileddeployment_approval_requestedissue_commentedissue_regressedmarkedmentionedmr_commentedmr_ready_to_mergemr_restack_requiredmr_unmergeablepipeline_failedpipeline_not_startedreview_approvedreview_requestedWhy an item is in front of you.
- resolved_atobjectoptional
- snoozed_untilobjectoptional
- statedonependingsnoozedWhere an item is in its life.
- targetobjectThe thing an attention item points at.
kindsays which, and decides the other fields. - updated_atstring
DELETE/user/attention/{attention_id}attention:write
Remove an attention item
Token scope
attention:write
Send
Path
- attention_iduuidAttention item ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Not authenticated403Forbidden — the caller's access level or token scope is insufficient404No such item for this caller409The request conflicts with the resource's current state; `reason` says how
Receive
No body.
GET/user/dashboard/summarydashboard:read
Read the caller's dashboard summary counters
Token scope
dashboard:read
Send
Nothing — the address is the whole request.
Refuses
401Not authenticated403The token does not allow reading the dashboard
Receive
attentionobject3 fields
- by_reasonobjectReasons with at least one pending item, keyed by the wire name.
- pendingint64A capped count. When
truncated, this is the cap and the client renders "99+". - truncatedboolean
- authored_merge_requests_openint64
- contributions_current_streakint64
- count_capint64The ceiling each counter was computed under.
- issues_assigned_openint64
namespaces[]object6 fields
- full_pathstring
- plan_tierenterprisefreeproteamThe subscription plan an organization is on, which sets its resource limits. From smallest to
largest:
free,pro,team,enterprise. - root_group_iduuid
- storage_bytes_limitint64
- storage_bytes_usedint64
- storage_used_pctint32optionalStorage used as a percentage of the limit, rounded, at most 100. Absent when the plan has no storage limit, which is not the same as 0%.
- onboarding_completeboolean
- pipeline_runs_failed_7dint64
- review_requests_pendingint64
GET/user/activityattention:read
List the caller's own activity across every namespace they reach
Token scope
attention:read
Send
Query
- domainstringoptionalComma-separated: merge_request, issue, repository, release, pipeline, member
- fromstringoptionalRFC-3339 start of the window (default: 30 days ago)
- tostringoptionalRFC-3339 end of the window (default: now)
- limitint32optionalPage size (1-50, default 20; out-of-range values clamp)
- next_tokenstringoptionalPagination cursor
- actorstringoptionalIgnored here: this feed is already one person's activity
Refuses
400Unknown domain, malformed window, or bad cursor401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
items[]object10 fields
- actorobjectoptional
- domainstring
- event_iduuid
- kindstring
- metadataobjectBounded free-form detail; the shape varies by
kindand is documented per event. - occurred_atstringWhen it happened. A feed is ordered by this.
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
- subjectobjectoptional
- next_tokenobjectoptional
GET/users/{user_id}/activityuser:read
List another person's activity, filtered to what the caller can see
Token scope
user:read
Send
Path
- user_iduuidThe subject's user id
Query
- domainstringoptionalComma-separated activity domains
- fromstringoptionalRFC-3339 start of the window
- tostringoptionalRFC-3339 end of the window
- limitint32optionalPage size (1-50, default 20)
- next_tokenstringoptionalPagination cursor
- actorstringoptionalIgnored here: this feed is already one person's activity
Refuses
400Unknown domain or malformed window401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404No such user
Receive
The same shape list_my_activity returns — 2 fields. Go to it
Show it here
items[]object10 fields
- actorobjectoptional
- domainstring
- event_iduuid
- kindstring
- metadataobjectBounded free-form detail; the shape varies by
kindand is documented per event. - occurred_atstringWhen it happened. A feed is ordered by this.
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
- subjectobjectoptional
- next_tokenobjectoptional
GET/repositories/{repo_id}/activityrepo:read
List a repository's activity timeline
Token scope
repo:read
Send
Path
- repo_iduuidThe repository's id
Query
- actorstringoptionalNarrow to one principal
- domainstringoptionalComma-separated activity domains
- fromstringoptionalRFC-3339 start of the window
- tostringoptionalRFC-3339 end of the window
- limitint32optionalPage size (1-50, default 20)
- next_tokenstringoptionalPagination cursor
Refuses
400Unknown domain or malformed window401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404No such repository, or it is not visible to the caller
Receive
The same shape list_my_activity returns — 2 fields. Go to it
Show it here
items[]object10 fields
- actorobjectoptional
- domainstring
- event_iduuid
- kindstring
- metadataobjectBounded free-form detail; the shape varies by
kindand is documented per event. - occurred_atstringWhen it happened. A feed is ordered by this.
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
- subjectobjectoptional
- next_tokenobjectoptional
GET/groups/{group_id}/activitygroup:read
List a group subtree's activity timeline
Token scope
group:read
Send
Path
- group_iduuidThe group's id
Query
- actorstringoptionalNarrow to one principal
- domainstringoptionalComma-separated activity domains
- fromstringoptionalRFC-3339 start of the window
- tostringoptionalRFC-3339 end of the window
- limitint32optionalPage size (1-50, default 20)
- next_tokenstringoptionalPagination cursor
Refuses
400Unknown domain or malformed window401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404No such group, or it is not visible to the caller
Receive
The same shape list_my_activity returns — 2 fields. Go to it
Show it here
items[]object10 fields
- actorobjectoptional
- domainstring
- event_iduuid
- kindstring
- metadataobjectBounded free-form detail; the shape varies by
kindand is documented per event. - occurred_atstringWhen it happened. A feed is ordered by this.
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
- subjectobjectoptional
- next_tokenobjectoptional
GET/user/top-repositoriesdashboard:read
List where the caller has been most active
Token scope
dashboard:read
Send
Query
- fromstringoptionalYYYY-MM-DD start of the window (default: 30 days ago)
- tostringoptionalYYYY-MM-DD end, inclusive (default: today)
- limitint32optionalHow many scopes (1-25, default 10; out-of-range values clamp)
Refuses
400Malformed or oversized window401Not authenticated403Forbidden — the caller's access level or token scope is insufficient
Receive
- fromstring
items[]object9 fields
by_typeobject5 fields
- commitsint64
- issuesint64
- mrsint64
- releasesint64
- reviewsint64
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
- totalint64
- tostring
GET/repositories/{repo_id}/insightsinsights:read
Get one repository's flow metrics over a window
Token scope
insights:read
Send
Path
- repo_iduuidThe repository's id
Query
- fromstringoptionalYYYY-MM-DD start of the window
- tostringoptionalYYYY-MM-DD end, inclusive
- granularitystringoptionalday | week | month (default: day)
Refuses
400Malformed window or unknown granularity401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404No such repository, or it is not visible to the caller
Receive
- breakdown_truncatedbooleanoptionalWhether
by_repositorylists only the first 25 of the group's repositories. Absent when it lists them all. by_repository[]object12 fields
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
totalsobject9 fields
- active_contributorsint64How many different people and service accounts contributed in the window.
- issues_closedint64
- issues_openedint64
- mrs_closedint64
- mrs_mergedint64
- mrs_openedint64
- pushesint64
- releases_publishedint64
- reviews_submittedint64
doraobject5 fields
- change_failure_rateobjectoptional
- merge_lead_time_seconds_p50doubleoptionalThe median time from a merge request's creation to its merge, in seconds. Narrower than commit-to-production lead time.
- release_frequency_per_weekdoubleoptionalPublished, non-draft releases per week over the window.
- time_to_restore_secondsdoubleoptionalNot reported: it needs to know when service was degraded.
unavailablegives the reason. - unavailableobjectFor each metric above that is never reported, its field name and the reason — as opposed to a metric that is null only because this window had no data.
- fromstring
- granularitydaymonthweekHow a series is bucketed.
meansobject3 fields
- run_duration_secondsdoubleoptional
- time_to_first_review_secondsdoubleoptional
- time_to_merge_secondsdoubleoptional
scopeobject1 field
- full_pathstring
GET/repositories/{repo_id}/insights/cycle-timeinsights:read
Get exact p50 and p95 for a repository's four cycle-time durations
Token scope
insights:read
Send
Path
- repo_iduuidThe repository's id
Query
- fromstringoptionalYYYY-MM-DD start of the window
- tostringoptionalYYYY-MM-DD end, inclusive
Refuses
400Malformed or oversized window401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404No such repository, or it is not visible to the caller
Receive
- fromstring
issue_cycle_timeobject4 fields
- nint64
- p50_secondsdoubleoptionalThe median, in seconds. Absent when the window held nothing to measure — which is different from a median of zero.
- p95_secondsdoubleoptional
- truncatedbooleanWhether the window held more than 20,000 measurements, in which case the percentiles are
computed over 20,000 of them and
nis that limit rather than the full count.
pipeline_durationobject4 fields
- nint64
- p50_secondsdoubleoptionalThe median, in seconds. Absent when the window held nothing to measure — which is different from a median of zero.
- p95_secondsdoubleoptional
- truncatedbooleanWhether the window held more than 20,000 measurements, in which case the percentiles are
computed over 20,000 of them and
nis that limit rather than the full count.
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
time_to_first_reviewobject4 fields
- nint64
- p50_secondsdoubleoptionalThe median, in seconds. Absent when the window held nothing to measure — which is different from a median of zero.
- p95_secondsdoubleoptional
- truncatedbooleanWhether the window held more than 20,000 measurements, in which case the percentiles are
computed over 20,000 of them and
nis that limit rather than the full count.
time_to_mergeobject4 fields
- nint64
- p50_secondsdoubleoptionalThe median, in seconds. Absent when the window held nothing to measure — which is different from a median of zero.
- p95_secondsdoubleoptional
- truncatedbooleanWhether the window held more than 20,000 measurements, in which case the percentiles are
computed over 20,000 of them and
nis that limit rather than the full count.
- tostring
GET/groups/{group_id}/insightsinsights:read
Get a namespace's flow metrics across its whole subtree
Token scope
insights:read
Send
Path
- group_iduuidThe group's id
Query
- fromstringoptionalYYYY-MM-DD start of the window
- tostringoptionalYYYY-MM-DD end, inclusive
- granularitystringoptionalday | week | month (default: day)
- breakdownstringoptionalnone | repository (default: none)
Refuses
400Malformed window, unknown granularity, or unknown breakdown401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404No such group, or it is not visible to the caller
Receive
The same shape get_repo_insights returns — 7 fields. Go to it
Show it here
- breakdown_truncatedbooleanoptionalWhether
by_repositorylists only the first 25 of the group's repositories. Absent when it lists them all. by_repository[]object12 fields
scopeobject3 fields
- full_pathstring
- idstring
- typegrouprepository
totalsobject9 fields
- active_contributorsint64How many different people and service accounts contributed in the window.
- issues_closedint64
- issues_openedint64
- mrs_closedint64
- mrs_mergedint64
- mrs_openedint64
- pushesint64
- releases_publishedint64
- reviews_submittedint64
doraobject5 fields
- change_failure_rateobjectoptional
- merge_lead_time_seconds_p50doubleoptionalThe median time from a merge request's creation to its merge, in seconds. Narrower than commit-to-production lead time.
- release_frequency_per_weekdoubleoptionalPublished, non-draft releases per week over the window.
- time_to_restore_secondsdoubleoptionalNot reported: it needs to know when service was degraded.
unavailablegives the reason. - unavailableobjectFor each metric above that is never reported, its field name and the reason — as opposed to a metric that is null only because this window had no data.
- fromstring
- granularitydaymonthweekHow a series is bucketed.
meansobject3 fields
- run_duration_secondsdoubleoptional
- time_to_first_review_secondsdoubleoptional
- time_to_merge_secondsdoubleoptional
scopeobject1 field
- full_pathstring
Limits
Your inbox holds 2 000 items, counting every state — pending, snoozed and done alike. It is a flat platform limit and does not vary by plan, because an inbox belongs to a person rather than to a namespace and there is no tier to raise.
Only bookmarks are refused at the limit. At 2 000 items a bookmark returns 429 TOO_MANY_REQUESTS and nothing is created — there is no half-saved bookmark and no lost note. An item the platform raises makes room instead: it evicts your oldest already-done item, so an inbox full of things you have finished with never blocks new work reaching you. The single case where a platform item is dropped is an inbox where all 2 000 are still live, because nothing there is safe to evict.
To get room back, mark items done and remove the ones you no longer want. Items you can no longer see still hold a slot, so if you have lost access to a repository, remove its items by id — that is what removal is for.
The other bounds worth knowing, none of which varies by plan:
| Bound | Value | What happens at it |
|---|---|---|
| Inbox items per person | 2 000 | a bookmark is refused with 429; a platform item evicts your oldest done item, or is dropped when none is done |
| Bookmark note | 280 characters | refused with 400 |
| Snooze | 1 minute to 90 days from now | outside the range, refused with 400 |
@-mentions acted on in one comment | the first 25 distinct names | later names in the same comment raise no item |
| Inbox and feed page size | 1 to 50, default 20 | out-of-range values clamp rather than fail |
| Most-active page size | 1 to 25, default 10 | out-of-range values clamp |
| Inbox badge and the four counters beside it | 100 | the number is a floor, and truncated names each one that reached it |
| Namespaces in the summary | 10 | the rest are omitted, and truncated lists namespaces |
| Activity and insight window | 366 days, default 30 | a wider window is refused with 400 |
| Activity feed retention | 90 days | older activity is no longer listed, but is still counted in insights |
| Cycle-time sample | 20 000 rows per duration | truncated is true and n stops there |
| Per-repository breakdown | the 25 busiest | breakdown_truncated is true |
| Approvers told about one gated deployment | 25 | nobody past the first 25 gets an item |
Troubleshooting
400 BAD_REQUESTmentioning state, reason or target_kind
- Cause
- An inbox filter carried a value the platform does not recognise. Filters are refused rather than widened, so you never get an unfiltered page back believing it was filtered
- What to do
- Check the spelling against the reason table above.
stateis one ofpending,snoozed,done,all;target_kindis one ofmerge_request,issue,pipeline_run,repository,group
400 BAD_REQUESTmentioning domain
- Cause
- A feed filter named a domain outside
merge_request,issue,repository,release,pipeline,member - What to do
- Correct the value, or drop the filter to get every domain
400 BAD_REQUEST, "from must be earlier than to"
- Cause
- A feed window is inverted or zero-length
- What to do
- Swap the two values, and widen a zero-length window by at least an instant. On a feed both are RFC-3339 timestamps
400 BAD_REQUEST, "from must not be later than to"
- Cause
- An insight window is inverted
- What to do
- Swap them. On an insight read both are
YYYY-MM-DDcalendar days, not timestamps — a timestamp here is refused, and a single day is a legal window
400 BAD_REQUEST, "the window must span at most 366 days"
- Cause
- You asked for more than a year in one request
- What to do
- Split the request into consecutive windows, or read the daily series and add it up yourself
400 BAD_REQUESTon a cursor
- Cause
- The pagination token was edited or truncated, or it came from a different kind of listing
- What to do
- Start the listing again from the first page. Reusing a cursor across different filters does not fail — it silently resumes at the wrong place, so treat a cursor as belonging to the query that produced it
400 BAD_REQUESTon a bookmark, mentioning the target
- Cause
- The target fields do not match
kind— amerge_requestwithout an iid, or anissuesent withrepository_idwhere it wantsscope_id - What to do
- Send exactly the fields that kind needs and nothing else. A work item's
scope_idis the id of the repository or group that owns it
400 BAD_REQUESTon a bookmark, mentioning note
- Cause
- The note is over 280 characters
- What to do
- Shorten it. The note is a reminder to yourself, not a description
400 BAD_REQUESTon a snooze
- Cause
untilis not RFC-3339, is in the past, is under a minute away, or is more than 90 days out- What to do
- Send an RFC-3339 timestamp inside the range. If you want it gone for longer than ninety days, mark it done
400 BAD_REQUESTon a path parameter
- Cause
- The id in the URL is not a well-formed id — often a path like
acme/apipasted where a repository id belongs, or a truncated item id - What to do
- Use the id. Resolve a path to an id first if that is all you have
401 UNAUTHORIZED
- Cause
- No credential, an expired or malformed one, or an anonymous call to something that is not public
- What to do
- Sign in again, or refresh the token your script is using. An anonymous call reaches a repository's or group's activity and its insights only while the resource is public, and a profile feed only shows public work; everything keyed to you needs a credential
403 INSUFFICIENT_SCOPEon the inbox listing or the badge
- Cause
- The token was minted without
attention:read - What to do
- Mint a new token carrying it. Scopes are fixed when a token is created and cannot be added afterwards
403 INSUFFICIENT_SCOPEon your own activity feed
- Cause
- Your own feed takes
attention:read, notdashboard:read— the two are separate grants - What to do
- Add
attention:readto the token
403 INSUFFICIENT_SCOPEon done, snooze, bookmark or remove
- Cause
- The token has
attention:readbut notattention:write - What to do
- Mint a token with
attention:write. A script that only reads your inbox should keep only the read scope
403 INSUFFICIENT_SCOPEon the summary or the most-active list
- Cause
- Both take
dashboard:read - What to do
- Add
dashboard:read. It grants aggregate counts over your own work and nothing else
403 INSUFFICIENT_SCOPEon insights or cycle time
- Cause
- Insights take
insights:read, whichrepo:readdoes not imply - What to do
- Add
insights:read. Reading code and reading how a team works are separate grants on purpose
403 FORBIDDENon a repository or group read that works from the web app
- Cause
- The token is bound to one repository or group subtree, and you asked about something outside it
- What to do
- Use a token with no resource binding, or one bound to the resource you are reading. A binding is fixed when the token is created
404 NOT_FOUNDon done or snooze
- Cause
- The item is not yours, it no longer exists, or its target is one you can no longer view
- What to do
- Re-list your inbox and use an id from that page. Another person's item answers
404rather than403, so an id is never a hint that something exists. If you know the item exists but its target has gone out of reach, remove it — removal still accepts it
404 NOT_FOUNDon remove
- Cause
- No item with that id belongs to you
- What to do
- Re-list your inbox and use an id from that page. Unlike done and snooze, removal does not care whether you can still see the target
404 NOT_FOUNDon a bookmark
- Cause
- The target does not exist, or you cannot view it — the two are deliberately the same answer
- What to do
- Open the thing you are bookmarking first. If you can see it in the web app, you can bookmark it
404 NOT_FOUNDon a repository or group you are sure exists
- Cause
- It is private and you are not a member
- What to do
- A private resource answers
404rather than403so its existence stays private. Ask an Owner or Maintainer for Reporter on it, then retry
404 NOT_FOUNDon a profile feed
- Cause
- No such account
- What to do
- Check the user id. An account whose work you cannot see returns
200with an empty page instead, so a404really does mean the account is not there
409 CONFLICTon a bookmark
- Cause
- You have already bookmarked that exact thing
- What to do
- Nothing to do — the existing bookmark is untouched, note and all. Find it in your inbox under
marked
429 TOO_MANY_REQUESTSon a bookmark
- Cause
- Your inbox is at 2 000 items
- What to do
- Mark items done and remove ones you no longer want. Items whose target you can no longer see still hold a slot — remove those by id
An item you expected never appeared
- Cause
- Items are recorded after the event that causes them, and the platform never raises an item for the person who caused it
- What to do
- Re-read a moment later. If you commented on your own work item or mentioned yourself, no item is created by design
You were @-mentioned and got nothing
- Cause
- Mentions raise items from work-item comments; a merge-request comment raises none. A name used as a quick-action argument, as in
/assign @sam, is an instruction rather than a mention, and only the first 25 distinct names in one comment are acted on - What to do
- Mention the person in the body of a work-item comment. On a merge request, add them as a reviewer instead — that raises a
review_requesteditem
A failed pipeline run never reached anyone's inbox
- Cause
- Pipeline failures are recorded in the activity feed and in the insight counters, and they raise no inbox item
- What to do
- Read the repository's activity filtered to
pipeline, or your own recent-failure count in the summary
A gated deployment told nobody
- Cause
- The gate names no approvers, so it is open to anyone with Developer on the repository and there is no list to address
- What to do
- Name approvers — people, teams or a role — in the environment's protection rules, so the gate addresses a named set and raises an item for each of them
An item disappeared and you did not touch it
- Cause
- The condition cleared — the merge request merged, a criterion verified, the approval was granted
- What to do
- Nothing to do. Read the Done tab to confirm what closed and when
An item you removed came straight back
- Cause
- Removing is not declining, and it leaves nothing behind to recognise a repeat. The next matching event recreates it, including a redelivery of the one that raised it
- What to do
- Mark it done instead. A done item stays done until the condition genuinely recurs
An item you snoozed is marked done
- Cause
- A snooze hides an item, it does not detach it from its condition. The condition cleared while it was hidden
- What to do
- Nothing to do. This is the intended behaviour and is why snoozing is safe
The badge reads 99+ and never moves
- Cause
- The count stops at 100 and
truncatedistrue, so the number is a floor - What to do
- Work the list down, or filter it by reason to see the shape of what is there
A summary counter looks stuck at 100
- Cause
- The same ceiling. The response's
truncatedlist names every counter that hit it - What to do
- Read the underlying listing for the real number
Not all your namespaces are in the summary
- Cause
- The summary enumerates at most 10, and puts
namespacesintruncatedwhen it stops - What to do
- Read the namespace's usage directly for one that is missing
A filter by reason returns nothing at all
- Cause
- Five reasons are accepted by the filter and produced by nothing:
review_approved,mr_unmergeable,mr_commented,blocked_by_resolved,pipeline_failed - What to do
- Filter by a reason from the table above, or drop the filter
An mr_restack_required item is still there after you restacked
- Cause
- It clears on its own only when the merge request merges or closes — restacking the branch does not clear it
- What to do
- Mark the item done once the restack has landed
A changes_requested item is still there after you pushed a fix
- Cause
- A push is intent to address, not agreement. It clears when the reviewer who rejected approves, or when the merge request merges or closes
- What to do
- Ask the reviewer for another look, or mark the item done once you have handled it
A feed is empty beyond about three months
- Cause
- Feeds keep 90 days
- What to do
- Use insights for anything older. The daily counts behind them are permanent, so old activity is still counted even though it is no longer listed line by line
A cycle-time duration has n of 0 and no percentiles
- Cause
- Nothing measurable happened in the window — no merge request merged, or none was ever reviewed
- What to do
- Widen the window. An absent percentile means no measurement, which is different from a p50 of zero
change_failure_rate and time_to_restore_seconds are always null
- Cause
- Both need a record of what was deployed and when service was degraded. The reason is spelled out per metric in
unavailable - What to do
- Read
release_frequency_per_weekandmerge_lead_time_seconds_p50, which measure what their names say. A gap prompts the work; a plausible wrong number prevents it
Group insights carry no merge lead time at all
- Cause
- A median over a whole subtree means reading every merge request in it, so the group read reports means instead
- What to do
- Ask a single repository for its cycle time when you need the median
truncated is true on a cycle time
- Cause
- The window held more than 20 000 measurable rows, so the percentiles cover the most recent 20 000 and
nstops there - What to do
- Narrow the window if you need the exact figure for the whole period
A per-repository breakdown is missing repositories
- Cause
- The split is capped at the 25 busiest and
breakdown_truncatedsays so - What to do
- Read the missing repositories individually, or narrow the window so fewer are busy
Your most-active list is empty for a token that works elsewhere
- Cause
- It is a service-account token, and the personal reads resolve visibility against a person
- What to do
- Use a personal access token for the personal surfaces
An item points at a repository whose name you no longer recognise
- Cause
- An item stores no copy of its target, so what you see is read live and a rename shows the new name
- What to do
- Open the item. If you have lost access, it stops appearing on your next read
Related
- Merge requeststhe reviews, approvals and merges that fill most of an inbox
- Reviews and approvalshow a review request is raised, approved and withdrawn
- Work itemsassignment, criteria and mentions, the other half of what lands there
- Pipelinesruns, and where a deployment's approval gate comes from
- Repositoriesvisibility and membership, which decide what you see in every feed and metric here
- Groupsthe groups a feed and group insights roll up over, and who can read them
- Access tokensminting a token with the scopes these surfaces need
- Getting set upthe checklist the summary reports as finished or not