Groups
- Create an organisation
- Add a sub-group
- Find the groups you can see
- Open a group by its id or its path
- Rename a group or change its details
- Take your reserved name
- Change who can see a group
- Set or remove a group avatar
- Add someone to a group
- See who is in a group
- Check one person's access
- Change someone's access level
- Remove someone from a group, or leave it yourself
- See the groups you belong to
- Check usage against your limits
- Check outbound-transfer usage
- Delete a group
- Reclaim an organisation's name
Overview
A group is a namespace: a name in a path, a place repositories live, and the level at which you hand out access once instead of repository by repository. The top group in a chain — the one with no parent — is your organisation, and it is also the boundary the metered resources are pooled against, so storage, pipeline minutes and outbound transfer all roll up to it. Below it you nest as deeply as your teams do, granting access at whatever level makes sense and letting it flow downwards.
Use groups to give a team read access to everything it owns in one action, to keep a client's work private inside an otherwise open organisation, and to see what an organisation is consuming against what its plan allows.
Quick start
Create a group
Choose Create in the top bar, then New group.
Give it a name — it becomes the first segment of every path inside it — and leave Parent group empty for a top-level group.
Choose Create group. You are its Owner, and it is ready for repositories and subgroups.
Add a subgroup
Open the parent group and choose New subgroup. The parent is filled in.
Name it after the team or the product line it holds. Access is granted per group, so nest by who owns what.
Choose Create group. It starts with its parent's visibility, and can never be more open than its parent.
Give someone access to a group
Start at Members in the group's side navigation.
Choose Add member.
Find the person and pick a level. Reporter is the lowest level that reads a private group.
Choose Add member. The access reaches every repository and subgroup beneath this group.
Before you start
- An account with a profile.Creating an organisation needs one, and the call answers
404if you have signed in but never completed your profile. It also has to be a personal account: a service-account token is refused with400, whatever scopes it carries, because an organisation is owned by a person. - Reporter to read a private group, and Reporter on any group to read its members and its usage. A public group answers anyone, signed in or not; an internal one answers anyone signed in; a private one answers only its members, and Guest is not enough — a Guest membership on a private group still gets
404. Its members and its usage are never public, whatever the group's visibility. - Maintainer on the parent to nest a group under it.Creating an organisation needs no membership anywhere — it is the one group you can create from nothing — but every sub-group is created inside something you already help run.
- Maintainer to rename a subgroup, change a group's description or set its avatar. Owner to rename an organisation, change a group's visibility or delete it.These three sit a level higher than the rest because each reaches people outside the group — and renaming an organisation gives its name up, for good once it has published anything.
- Maintainer to manage members, and Owner to add, promote, demote or remove an Owner.You can never grant a level above your own.
- The person you are adding already has a Gitmoap account.Adding a member resolves the account first and answers
404when there is none. Single sign-on can create accounts on first login instead, but only once you turn automatic provisioning on and only for email domains your organisation has verified — otherwise a first login is refused unless the person was invited. - A token with the right scope, if you are calling the API or the CLI:
group:readto read groups and their usage,group:create,group:update(which also covers the avatar),group:delete; andgroup_member:read,group_member:add,group_member:update,group_member:removefor membership. Scopes are fixed when a token is minted, so a script that only reports usage should carry onlygroup:read. - A name that is a valid path segment.Lowercase letters, digits and hyphens, one to a hundred characters, no leading or trailing hyphen.
platform-teamis fine;Platform Team,platform_teamand-platformare refused. An organisation's name also has to be free: not a word Gitmoap keeps, not a well-known organisation's name or one that looks like it, and not a name another organisation gave up recently — see How organisation names work.
How it works
The path is the hierarchy
Every group and every repository has one path, built by joining its name to its parent's path. Two groups under the same parent cannot share a name, and no two groups anywhere can share a full path.
acme an organisation: a group with no parent├── platform a sub-group│ ├── api a repository at acme/platform/api│ └── ingest a repository at acme/platform/ingest└── web a sub-group └── storefront a repository at acme/web/storefrontRenaming platform rewrites the path of everything beneath it in the same request, so acme/platform/api becomes acme/core/api the moment the rename returns. The ids do not move. Anything addressed by id — a script holding a group or repository id, a pipeline definition, a token bound to the group — keeps working across a rename; anything addressed by path has to be told the new one, and that includes every git remote, because a remote names the repository by path.
How organisation names work
An organisation's name is the first segment of every address inside it, so to anyone reading a link, whoever holds a name is that name. Gitmoap keeps some names back for that reason, and checks an organisation's name against them whenever you create an organisation or rename one. A subgroup's name only has to be unique inside its parent.
| A name is refused when | The answer | What it means |
|---|---|---|
| It is a word Gitmoap keeps for itself | 403 RESERVED_NAMESPACE | Words such as admin, api, login and security, and the top-level pages of the web app. Nobody can take one |
| It is a well-known organisation's name | 403 RESERVED_NAMESPACE | It is kept for whoever proves they own that organisation's domain, and the message names the domain. You can take your reserved name by verifying it |
| It looks like a well-known organisation's name | 403 NAME_RESEMBLES_RESERVED | Digits standing in for letters (micros0ft), rn standing in for m, a hyphen inside the name (micro-soft), or a word such as official, support or inc before or after it (microsoft-support). The same domain unlocks these |
| Another organisation gave it up recently | 409 NAME_RETIRED | The message says until when, or that the name is held for good |
The well-known organisations are drawn from Wikidata and the Majestic Million (Majestic-12 Ltd, CC BY 3.0): an organisation is on the list when its official website's domain is also among the most-linked domains on the web. Everyday words that happen to be brands — apple, delta, target — are kept only exactly as spelt, so apple-store is free, and names shorter than four characters, such as ibm, are kept exactly with no look-alikes refused. Places are not on the list. A name somebody already held when it joined the list stays theirs.
A name has one spelling. Names are lowercase, so Acme is never a second acme. When you look something up — a group or repository by its path, a person by username, a repository in a git clone URL — what you type is lowercased first, so Acme/Platform finds acme/platform. Creating or renaming still needs the lowercase form; put capitals in the display name.
A name you give up is held. When you rename an organisation, its old name is held for it for 90 days: nobody else can take it, and you can rename back. If the organisation has ever had a public repository or published a package, the old name is held for good instead, because people depend on what was published under it. An organisation holds at most five of its former names at a time. When an organisation is deleted, its name is held for nobody — 90 days, or for good once it published — so not even its former Owners can take it during that time. Renaming or deleting a subgroup holds nothing.
Verified domains show on the organisation. Every domain your organisation has verified under single sign-on appears on it — verified_domains on the organisation's details and in group listings — to everyone who can see the organisation, and to nobody else. It is how a reader tells your organisation from one with a similar name. A domain you have claimed but not verified never appears.
Access levels, and how they reach down
There are five levels, ordered:
| Level | What it gets you in a group |
|---|---|
| Guest | See that a private group or repository exists, and read whatever is public or internal |
| Reporter | Read private repositories, work items and merge requests, and file and comment on work items |
| Developer | Push code, open and merge merge requests, create branches, tags and releases, trigger pipeline runs |
| Maintainer | Create repositories and sub-groups, manage members, rules, settings and pipeline variables |
| Owner | Change visibility, rename an organisation, delete, manage other Owners, read the audit log, and manage single sign-on and billing |
Your effective level on any group is the highest level you hold on it or on any group above it. An Owner of acme is an Owner of acme/platform and of every repository underneath without holding a single row there, and a Developer on acme who is also a Maintainer on acme/web is a Maintainer there and a Developer everywhere else. Levels only ever add: a membership deeper in the tree can raise someone, never lower them. That is the one thing people get wrong — removing somebody from a sub-group does nothing if their access came from an ancestor.
The creator of a group is its Owner from the moment it exists, in the same operation, so a group is never left without one.
Visibility, and the rule that a child is never more open than its parent
| Visibility | Signed out | Signed in, not a member | Member |
|---|---|---|---|
| Public | Read | Read | Full, per level |
| Internal | 401 | Read | Full, per level |
| Private | 401 | 404 | Full, per level, from Reporter up |
Signed out, anything that is not public answers 401 — the platform asks for a credential before it will say anything else. Signed in, a private group answers 404 rather than 403 to anyone who is not a member, so its existence stays private too. If you were given a path and get 404, either the spelling is wrong or you are not in it — the response is deliberately the same either way. A Guest is a member: they see the group, and are told 403 rather than 404 for anything more, because it is no secret from them.
Visibility is constrained in one direction: a group can never be more visible than its parent. Asking for more is refused when you create the group and when you update it, and lowering a parent below a child that is more open is refused as well, naming the child that blocks it. Fix the named one first, then the parent.
The namespace is where the pooled limits live
Two kinds of limit apply, and they are counted in different places. Pooled resources — stored bytes, pipeline runs and minutes, outbound transfer — are counted against the organisation at the top of the chain, so every repository anywhere in the tree draws on the same budget. Counts of things — repositories, members, webhooks, service accounts — are counted against the individual group that holds them, so each group gets its own allowance.
Ask any group in the tree for its usage and you are told the organisation's pooled numbers. The group you named only decides which group's own counts come back beside them, and only the limits view carries those — the shorter usage view reports the organisation and nothing else.
How to
Create an organisation
An organisation is a group with no parent. You do not need to belong to anything to create one, only to have a profile. It starts private, and every provider Gitmoap publishes itself is installed on it at its latest version, so you can build a pipeline without installing anything first.
Choose Create in the top bar, then New group, and leave Parent group empty. Give it a name — that name becomes the first segment of every path inside it — and, if you want, a display name and description. Create group takes you to the new organisation's overview with you listed as its Owner.
gitmoap groups create --group-name <group name>curl -X POST https://api.gitmoap.example/groups \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "group_name": "<string>" }'Pick the name carefully. Renaming later is one action, but it changes the path of every repository underneath it, everyone with a clone has to update their remote, and the name you leave behind is held. If the name is refused, the answer says why — see How organisation names work. If it is your own company's name, kept for whoever owns your domain, create the organisation under another name first, then take your reserved name.
Add a sub-group
A sub-group is created the same way, naming the group it sits inside. It inherits its parent's visibility unless you ask for something less open, and it cannot be more open than its parent.
Open the parent group and choose New subgroup. The parent is filled in. Name it, optionally set a description, and leave visibility alone to inherit the parent's. Create group drops you into the new group.
gitmoap groups create --group-name <group name>curl -X POST https://api.gitmoap.example/groups \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "group_name": "<string>" }'Nest by ownership, not by repository count. A sub-group's real purpose is to be the thing you grant access to, so the useful shape is usually one sub-group per team or per product line, not one per repository.
Find the groups you can see
With no filter you get organisations — every one you can see, which for a signed-out caller means the public ones and for a signed-in caller adds the internal ones and the private ones you belong to. Name a parent and you get that group's direct children instead. You can name the parent by id or by path, but not both in the same request.
Choose Groups in the top navigation for the organisations you belong to. Inside a group, Sub-groups lists its direct children. Both lists page as you scroll and show each group's visibility beside its name.
gitmoap groups listcurl -X GET https://api.gitmoap.example/groups \ -H "Authorization: Bearer $GITMOAP_TOKEN"Groups you may not see are dropped from a page after it is read, so a page can come back with fewer groups than the limit you asked for while there is still more to fetch. Keep following the next-page token until there is none; a short page is not the end of the list. A page tops out at 100 groups however large a limit you ask for, so a script that asks for a thousand and reads one page has seen a tenth of them.
Open a group by its id or its path
Two ways in, same group. The id never changes; the path changes when the group or any of its ancestors is renamed.
Every group's overview lives at its path — /acme/platform in the web app is the group at acme/platform. The Copy id action on the overview gives you the id for scripts.
gitmoap groups get --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Paste a path into the search box, or navigate to it directly: the web app resolves paths for you, so /acme/platform and the group's id URL land in the same place.
gitmoap groups get-by-path --full-path <id>curl -X GET https://api.gitmoap.example/groups/by-path/{full_path} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Prefer the id in anything you store. Prefer the path in anything a person types. The CLI takes either wherever it asks for a group: a value shaped like an id is used as one, and anything else is looked up as a path.
The whole path travels as a single value, slashes and all, so let the CLI or a generated client build the request rather than pasting acme/platform into a URL by hand.
Rename a group or change its details
Display name, description and avatar reference are ordinary metadata. The group_name is not: changing it recomputes this group's path and rewrites every descendant group and repository path in the same request.
Open the group, choose Settings, then General. Edit the display name, description or name, and Save changes. Renaming asks you to confirm, because it moves everything below the group to a new path.
gitmoap groups update --group-id <id>curl -X PUT https://api.gitmoap.example/groups/{group_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Fields you leave out are left alone, so a request carrying only group_name changes only the name. To clear a display name or description, send it as an empty string rather than omitting it. If the new name is taken by a sibling group, or the new path by any other group, the rename is refused and nothing moves.
Renaming an organisation needs Owner, and its new name is checked the way a new organisation's is — except that a domain the organisation has verified unlocks the name kept for that domain. The old name is held for the organisation: for 90 days, or for good once it has published, and never more than five at a time. Sending the name the organisation already has is not a rename.
Take your reserved name
A well-known organisation's name is kept for whoever proves they own its domain, and the proof is the DNS record you publish to verify a domain under single sign-on. Verify the domain on an organisation you already have, then rename that organisation into the name.
- Create your organisation under any free name, or use one you already own.
- Claim and verify, on that organisation, the domain the refusal named — see Verify a claimed domain. A domain beneath it works too:
microsoftis unlocked bymicrosoft.comoreu.microsoft.com, and never by a domain that only contains the name, such asmicrosoft.mooo.com. - Rename the organisation to the name, as an Owner.
Open the organisation, choose Settings, then General, and change the name to the one kept for you. Save changes renames it, and the name it leaves behind is held for it.
gitmoap groups update --group-id <id>curl -X PUT https://api.gitmoap.example/groups/{group_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"The same domain unlocks the names that look like yours, so microsoft-support is yours to take as well. Only an organisation renaming itself is ever unlocked this way: a new organisation, a username and a personal group never are, which is why you create first and rename second. Releasing the domain later does not take the name back. If verifying the domain answers 501, domain verification is unavailable on Gitmoap's side — contact support@gitmoap.com.
Change who can see a group
Visibility is the one metadata change that needs Owner, and it is checked in both directions: not more open than the parent, and not more closed than a child that is already more open.
Open the group, choose Settings, then General, and pick a visibility. Anything more open than the parent is not offered. Save changes applies it.
gitmoap groups update --group-id <id>curl -X PUT https://api.gitmoap.example/groups/{group_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Going from private to internal or public exposes the group's name, description and its public contents to people who were never members. It does not open the repositories inside it — each keeps the visibility it already had. Going the other way is refused while a sub-group or repository beneath it is still more open, and the refusal names the one that blocks you.
Note
The Owner bar is on sending the visibility field, not on changing the value. A Maintainer who sends the whole group back with visibility set to what it already was is refused 403 all the same. When you are scripting a metadata edit, leave visibility out of the body unless you mean to change it.
Set or remove a group avatar
Uploading is two steps: ask for an upload URL, then send the bytes to it. The request declares the exact size of the file, and that size is bound into the URL — sending a different number of bytes is refused by the storage service, so a small declaration cannot smuggle a large upload.
Open the group, choose Settings, then General, and choose Change avatar. Pick a PNG, JPEG, GIF or WebP of at most 5 MiB. The web app requests the URL and uploads for you; the new image appears as soon as the upload finishes.
gitmoap groups upload-avatar \ --group-id <id> \ --content-length <n> \ --content-type <content type>curl -X PUT https://api.gitmoap.example/groups/{group_id}/avatar \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "content_length": "<int64>", "content_type": "<string>" }'The response carries two URLs: one to PUT the bytes to, which is valid for five minutes, and the address the image is served from afterwards. That second address is fixed for the life of the group, so uploading again replaces the image in place and nothing that already points at it has to be updated. Removing the avatar deletes the image, and the address stops serving one.
In Settings → General, choose Remove avatar beside the current image.
gitmoap groups delete-avatar --group-id <id>curl -X DELETE https://api.gitmoap.example/groups/{group_id}/avatar \ -H "Authorization: Bearer $GITMOAP_TOKEN"Add someone to a group
Adding is create-only and names the level you want them at. Maintainer is enough for every level except Owner, which needs Owner. The request identifies the person by their account id, not by an email address, so a script adds people in two steps: look the account up by username or email, then add the id it gives back.
Open the group, choose Members, then Add member. Search for the person by username or email, pick a level, and Add. They appear in the list immediately with the level you chose.
gitmoap group-members add \ --group-id <id> \ --access-level guest|reporter|developer|maintainer|owner \ --user-id <user id>curl -X POST https://api.gitmoap.example/groups/{group_id}/members \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "access_level": "<one of developer | guest | maintainer | owner | reporter>", "user_id": "<uuid>" }'Three refusals are worth knowing before you hit them. The person must already have an account — there is no way to add an address that has never signed in. Adding somebody who is already a member is refused rather than silently changed; change the level instead. And each group has its own member cap for the plan, counted against that group alone, not against the organisation.
Add at the lowest level that works, but not lower. Guest lets somebody see that a private group and its repositories exist — their names, and nothing inside them. Reporter is the lowest level that reads a private group's content and the repositories in it.
See who is in a group
The list shows direct members of this group only. It does not show the people who reach it from an ancestor, which is the usual reason a group appears to have fewer members than it behaves as having. It lists people; the service accounts a group owns are listed separately and counted against a separate cap.
You need Reporter or above on the group to read its members — even when the group itself is Public or Internal. Who has access to a group is not part of what the group shows the world, so a signed-in person without a membership gets a 403, and a visitor who is not signed in is asked to sign in.
Open the group and choose Members. Type in the filter box to narrow by username or email. Each row shows the level and when the membership was created.
gitmoap group-members list --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/members \ -H "Authorization: Bearer $GITMOAP_TOKEN"To answer who can actually touch this?, read the members of every group on the path above it as well.
Each row names the person by account id and level, not by username, so a report that has to print names resolves each id through the users API. The filter still matches on username and email even though neither comes back in the row.
Check one person's access
On the Members list, choose a row to open that person's membership, showing their level in this group and when it was granted.
gitmoap group-members get --group-id <id> --user-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/members/{user_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"A 404 here means they hold no membership on this group. It is not an answer about whether they can reach it — they may hold one on an ancestor. Like the list, it needs Reporter or above on the group.
Change someone's access level
Open the group, choose Members, and pick a new level from the dropdown at the end of the row.
gitmoap group-members update \ --group-id <id> \ --user-id <id> \ --access-level guest|reporter|developer|maintainer|ownercurl -X PUT https://api.gitmoap.example/groups/{group_id}/members/{user_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "access_level": "<one of developer | guest | maintainer | owner | reporter>" }'Promoting somebody to Owner, or moving an existing Owner to anything else, needs Owner. An organisation — a top-level group — always keeps at least one Owner, so demoting its last one is refused: promote a second Owner first, then demote the first. A subgroup may be left with no direct Owner, because the organisation's Owners always administer it.
Remove someone from a group, or leave it yourself
Warning
Removing a member is immediate. Anything they hold because of that membership goes with it: access to every repository in the group and everything nested beneath it, and any work in progress they cannot reach any more. Their commits, work items, comments and merge requests stay exactly where they are — the history is not rewritten — but they lose the ability to open them if nothing else grants access. Re-adding them restores access; it does not restore anything they lost in between.
You can always remove yourself, at any level, without needing permission to manage members — with one exception: the last Owner of an organisation cannot leave it, because that would strand the organisation with nobody able to administer it. Leaving a subgroup as its last direct Owner is fine.
Open the group, choose Members, and use the menu at the end of the row to Remove from group. To leave a group yourself, use Leave group on the group's overview. Both ask you to confirm.
gitmoap group-members remove --group-id <id> --user-id <id>curl -X DELETE https://api.gitmoap.example/groups/{group_id}/members/{user_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"If somebody still has access after you removed them, their access is coming from a group above this one. Remove the membership where it actually lives.
See the groups you belong to
This is your own list, and only yours — asking for somebody else's memberships is refused.
Choose Groups in the top navigation. The list shows every group you hold a direct membership on, with your level in each.
gitmoap group-members list-groups-for-user --user-id <id>curl -X GET https://api.gitmoap.example/users/{user_id}/groups \ -H "Authorization: Bearer $GITMOAP_TOKEN"Membership inherited from an ancestor does not create a row here, so a group you can administer through its parent will not appear. The parent will.
Check usage against your limits
Two views, different shapes. The usage view is the short one: storage, pipeline runs in flight, runs and minutes this month, and the plan the organisation is on. The limits view is the complete one: everything metered across the organisation, plus the live counts for the group you named, plus the caps that apply to individual repositories, merge requests and issues.
Open the group, choose Settings, then Usage. The cards show storage and pipeline consumption for the whole organisation against the plan's ceilings, whichever group in the tree you opened.
gitmoap groups get-namespace-usage --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/usage \ -H "Authorization: Bearer $GITMOAP_TOKEN"Settings → Usage also lists every metered resource in three tables: what the organisation consumes, what this group holds, and the per-resource caps that have no organisation-wide count.
gitmoap groups get-namespace-limits --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/limits \ -H "Authorization: Bearer $GITMOAP_TOKEN"Name any group in the tree where you are Reporter or above — the organisation-wide numbers are the same from anywhere in it, and they are never public, whatever the group's visibility. What changes is the second table, which counts this group's own repositories, members, webhooks, service accounts and the rest.
Check outbound-transfer usage
Bytes leaving the platform — clones and fetches, downloaded release assets and archives, published packages people pull — are metered per day for the whole organisation against a cap that comes from your plan.
Settings → Usage shows the current day's outbound transfer for the organisation beside the day's cap, with the window it covers.
gitmoap groups get-namespace-egress-usage --group-id <id>curl -X GET https://api.gitmoap.example/groups/{group_id}/egress-usage \ -H "Authorization: Bearer $GITMOAP_TOKEN"The window is a UTC day, named in the response, and it resets on its own; there is nothing to clear. A big first clone of a large repository is the usual reason a number jumps — a shallow clone (git clone --depth 1) moves far fewer bytes, and a build agent that clones on every run is worth pointing at a cache.
Delete a group
Warning
Deleting a group destroys everything attached to it, immediately and permanently. That includes every membership, every service account the group owns and their tokens, its webhooks, branch and push rules, merge-request settings, provider connections and their stored credentials, any packages published to the group, and the group's own work items, labels and milestones. There is no undo and no recycle bin. A group must be emptied of sub-groups and repositories before it can be deleted, which is the only safety net there is — everything else on the list goes without a second confirmation. Deleting an organisation also holds its name back from everybody, you included: for 90 days, or for good if it ever had a public repository or published a package.
Deleting is Owner-only and refuses while anything is still nested inside. Move or delete the repositories first, then the sub-groups, working from the leaves upwards.
Open the group, choose Settings, then General, and scroll to Delete group. The confirmation names the group and what deleting it destroys. If the group still holds sub-groups or repositories, it tells you what has to go first.
gitmoap groups delete --group-id <id>curl -X DELETE https://api.gitmoap.example/groups/{group_id} \ -H "Authorization: Bearer $GITMOAP_TOKEN"Deleting an organisation gives its slot back straight away — to the account that created it, which is not necessarily the Owner doing the deleting.
Reclaim an organisation's name
This one belongs to Gitmoap's platform administrators, not to an organisation's Owner. It is how Gitmoap acts on a report that an organisation impersonates somebody, or that its name infringes a trademark or another right somebody holds in it. To make such a report, write to the legal desk through the contact form.
Warning
Reclaiming takes the name away from the organisation for good. The organisation is renamed — to a name the administrator chooses, or to renamed- followed by eight letters and digits — and every path inside it moves with it, so every git remote and every link that spelled the old name stops working. The old name is held for good: for the organisation it rightly belongs to, when the administrator names one, and otherwise for nobody. Nothing inside the organisation is deleted, and its id does not change.
The administrator records the reason, impersonation or infringement, and a note of what the reclaim rests on, and the organisation's Owners are sent the reasons before the name is taken. If the name is held for your organisation, rename your organisation to it the way you would to any free name. The other checks still apply, so a well-known organisation's name also needs its domain verified first.
There is no screen for this. A platform administrator calls it while signed in; an access token never makes anybody an administrator, whatever it carries.
gitmoap groups reclaim-name \ --group-id <id> \ --note <note> \ --reason impersonation|infringementcurl -X POST https://api.gitmoap.example/admin/groups/{group_id}/reclaim-name \ -H "Authorization: Bearer $GITMOAP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "note": "<string>", "reason": "<one of impersonation | infringement>" }'Reference
18 endpoints
POST/groupsgroup:create
Create a new repository group
Token scope
group:create
Counts against
root_groups_per_user
Send
Body
- avatarobjectoptional
- descriptionobjectoptional
- display_nameobjectoptional
- group_namestring
- parent_group_idobjectoptional
- visibilityobjectoptional
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Forbidden, or the name is reserved or looks like a reserved name404Parent group not found or caller has no user profile409Path already taken, or the name is held back after another organization gave it up429The root-group limit is reached; request an increase to raise it
Receive
- avatarobjectoptional
- created_atstring
- created_byuuid
- descriptionobjectoptional
- display_nameobjectoptional
- full_pathstring
- group_iduuid
- group_namestring
- parent_group_idobjectoptional
- updated_atstring
- visibilityinternalprivatepublic
GET/groups/{group_id}group:read
Get a group by ID
Token scope
group: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
No body.
GET/groups/by-path/{full_path}group:read
Get a group by its full path
Token scope
group:read
Send
Path
- full_pathstringFull hierarchical path (e.g. acme/platform)
Refuses
400Invalid path401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404Group not found
Receive
No body.
GET/groupsgroup:read
List groups
Token scope
group:read
Send
Query
- parent_group_idstringoptionalFilter by parent group ID (mutually exclusive with parent_group_path)
- parent_group_pathstringoptionalFilter by parent group path (mutually exclusive with parent_group_id)
- limitint32optionalMaximum number of items to return
- next_tokenstringoptionalPagination token
Refuses
400Invalid request (both parent_group_id and parent_group_path provided)401Unauthenticated — no credential, or an invalid one403Forbidden — the caller's access level or token scope is insufficient404The parent group named by `parent_group_path` does not exist
Receive
- next_tokenobjectoptional
PUT/groups/{group_id}group:update
Update a group
Token scope
group:update
Send
Path
- group_iduuidGroup ID
Body
- avatarobjectoptional
- descriptionobjectoptional
- display_nameobjectoptional
- group_nameobjectoptional
- visibilityobjectoptional
Refuses
400Invalid request or visibility exceeds parent401Unauthenticated — no credential, or an invalid one403Forbidden (Owner required for a visibility change or an organization's rename), or the new name is reserved404Group not found409New path already taken, the name is held back, or the organization holds back as many former names as it may
Receive
The same shape create_group returns — 11 fields. Go to it
Show it here
- avatarobjectoptional
- created_atstring
- created_byuuid
- descriptionobjectoptional
- display_nameobjectoptional
- full_pathstring
- group_iduuid
- group_namestring
- parent_group_idobjectoptional
- updated_atstring
- visibilityinternalprivatepublic
DELETE/groups/{group_id}group:delete
Delete a group
Token scope
group:delete
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 (Owner required)404Group not found409Group is not empty
Receive
No body.
PUT/groups/{group_id}/avatargroup:update
Get a URL to upload a group's avatar to
Token scope
group:update
Counts against
avatar_bytes
Send
Path
- group_iduuidGroup ID
Body
- content_lengthint64Exact byte size of the upload. Bound into the presigned PUT, so the upload must send exactly this many bytes; rejected up front if over the avatar cap.
- content_typestring
Refuses
400Invalid content type401Unauthenticated — no credential, or an invalid one403Forbidden (Maintainer required)404Group not found409The request conflicts with the resource's current state; `reason` says how501Avatar uploads are not available on this deployment
Receive
- avatar_urlstring
- upload_urlstring
DELETE/groups/{group_id}/avatargroup:update
Delete a group avatar
Token scope
group:update
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 (Maintainer required)404Group not found409The request conflicts with the resource's current state; `reason` says how500Avatar upload not configured
Receive
No body.
POST/groups/{group_id}/membersgroup_member:add
Add a member to a group
Token scope
group_member:add
Counts against
members_per_scope
Send
Path
- group_iduuidGroup ID
Body
- access_leveldeveloperguestmaintainerownerreporter
- user_iduuid
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Forbidden404Group or user not found409User is already a member429Member limit reached for this group
Receive
- access_leveldeveloperguestmaintainerownerreporter
- created_atstring
- group_iduuid
- parent_group_iduuid
- user_iduuid
- visibilityinternalprivatepublic
GET/groups/{group_id}/members/{user_id}group_member:read
Get a specific group member
Token scope
group_member:read
Send
Path
- group_iduuidGroup ID
- user_iduuidUser ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Authentication required — a roster is not public403Caller is not a member with at least Reporter404Group or member not found
Receive
The same shape add_group_member returns — 6 fields. Go to it
Show it here
- access_leveldeveloperguestmaintainerownerreporter
- created_atstring
- group_iduuid
- parent_group_iduuid
- user_iduuid
- visibilityinternalprivatepublic
GET/groups/{group_id}/membersgroup_member:read
List group members
Token scope
group_member:read
Send
Path
- group_iduuidGroup ID
Query
- searchstringoptionalAutocomplete fragment — substring match on the member's username or email
- limitint32optionalMaximum number of items to return
- next_tokenstringoptionalPagination token
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Authentication required — a roster is not public403Caller is not a member with at least Reporter404Group not found
Receive
items[]object6 fields
- access_leveldeveloperguestmaintainerownerreporter
- created_atstring
- group_iduuid
- parent_group_iduuid
- user_iduuid
- visibilityinternalprivatepublic
- next_tokenobjectoptional
PUT/groups/{group_id}/members/{user_id}group_member:update
Update a group member's access level
Token scope
group_member:update
Send
Path
- group_iduuidGroup ID
- user_iduuidUser ID
Body
- access_leveldeveloperguestmaintainerownerreporter
Refuses
400Invalid request401Unauthenticated — no credential, or an invalid one403Forbidden404Group or member not found409The organization's last Owner, or a person whose access here is a custom role
Receive
The same shape add_group_member returns — 6 fields. Go to it
Show it here
- access_leveldeveloperguestmaintainerownerreporter
- created_atstring
- group_iduuid
- parent_group_iduuid
- user_iduuid
- visibilityinternalprivatepublic
DELETE/groups/{group_id}/members/{user_id}group_member:remove
Remove a member from a group
Token scope
group_member:remove
Send
Path
- group_iduuidGroup ID
- user_iduuidUser ID
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden404Group or member not found409The organization's last Owner, or a person whose access here is a custom role
Receive
No body.
GET/users/{user_id}/groupsgroup_member:read
List groups the user is a member of
Token scope
group_member:read
Send
Path
- user_iduuidUser ID
Query
- limitint32optionalMaximum number of items to return
- next_tokenstringoptionalPagination token
Refuses
400Bad request — a path parameter is not a well-formed value of its type401Unauthenticated — no credential, or an invalid one403Forbidden — not the target user404Not found — or found and private, which is masked as absent
Receive
The same shape list_group_members returns — 2 fields. Go to it
Show it here
items[]object6 fields
- access_leveldeveloperguestmaintainerownerreporter
- created_atstring
- group_iduuid
- parent_group_iduuid
- user_iduuid
- visibilityinternalprivatepublic
- next_tokenobjectoptional
GET/groups/{group_id}/usagegroup:read
Get resource usage and plan limits for a group's namespace
Token scope
group:read
Send
Path
- group_iduuidGroup ID (usage is reported for its root namespace)
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
- max_concurrent_pipeline_runsint32
- max_pipeline_minutes_per_monthint32
- max_pipeline_runs_per_monthint32
- pipeline_minutes_this_monthint32Pipeline minutes used in the current calendar month: the running time of every pipeline step, added together.
- pipeline_runs_in_flightint32
- pipeline_runs_this_monthint32Runs started in the current calendar month.
- 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
GET/groups/{group_id}/limitsgroup:read
Get the full usage-and-limits view for a group's namespace
Token scope
group:read
Send
Path
- group_iduuidGroup ID (namespace usage is reported for its root; group-scoped counts for this group)
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
group_counts[]object3 fields
- limitint64
- nameaccess_limitsanchors_per_issueanchors_per_repoapproval_rulesblueprintsbranch_rulesbranches_per_repochildren_per_issuecode_todos_per_repocomments_per_issuecomments_per_mrcommit_statuses_per_commitconcurrent_pipeline_runscriteria_per_issuecriteria_per_repocustom_rolesenvironmentslabelsmembersmembers_per_teammilestonesopen_issuesopen_mrs_per_repopackage_bytespipeline_componentspipeline_dag_nodespipeline_minutes_this_monthpipeline_runs_this_monthpipelines_per_repoprovider_connectionsprovider_installspush_bytesreactions_per_commentrelations_per_issuerelease_asset_bytesreleases_per_reporeposreviewers_per_mrscim_tokensscorecardsservice_accountsservicessso_invites_per_scopestorage_bytestags_per_repoteamsversions_per_pipeline_componentwebhookswiki_pagesWhich limit a usage-and-limits entry describes.
- usedint64
- group_iduuid
namespace[]object3 fields
- limitint64
- nameaccess_limitsanchors_per_issueanchors_per_repoapproval_rulesblueprintsbranch_rulesbranches_per_repochildren_per_issuecode_todos_per_repocomments_per_issuecomments_per_mrcommit_statuses_per_commitconcurrent_pipeline_runscriteria_per_issuecriteria_per_repocustom_rolesenvironmentslabelsmembersmembers_per_teammilestonesopen_issuesopen_mrs_per_repopackage_bytespipeline_componentspipeline_dag_nodespipeline_minutes_this_monthpipeline_runs_this_monthpipelines_per_repoprovider_connectionsprovider_installspush_bytesreactions_per_commentrelations_per_issuerelease_asset_bytesreleases_per_reporeposreviewers_per_mrscim_tokensscorecardsservice_accountsservicessso_invites_per_scopestorage_bytestags_per_repoteamsversions_per_pipeline_componentwebhookswiki_pagesWhich limit a usage-and-limits entry describes.
- usedint64
- plan_tierenterprisefreeproteamThe subscription plan an organization is on, which sets its resource limits. From smallest to
largest:
free,pro,team,enterprise. - root_group_iduuid
scope_limits[]object3 fields
- limitint64
- nameaccess_limitsanchors_per_issueanchors_per_repoapproval_rulesblueprintsbranch_rulesbranches_per_repochildren_per_issuecode_todos_per_repocomments_per_issuecomments_per_mrcommit_statuses_per_commitconcurrent_pipeline_runscriteria_per_issuecriteria_per_repocustom_rolesenvironmentslabelsmembersmembers_per_teammilestonesopen_issuesopen_mrs_per_repopackage_bytespipeline_componentspipeline_dag_nodespipeline_minutes_this_monthpipeline_runs_this_monthpipelines_per_repoprovider_connectionsprovider_installspush_bytesreactions_per_commentrelations_per_issuerelease_asset_bytesreleases_per_reporeposreviewers_per_mrscim_tokensscorecardsservice_accountsservicessso_invites_per_scopestorage_bytestags_per_repoteamsversions_per_pipeline_componentwebhookswiki_pagesWhich limit a usage-and-limits entry describes.
- scopecommentcommitissuemerge_requestnamespacepackagepipeline_componentpushreleasereporunteamWhat a per-resource limit applies to — each repository, each merge request, each team, and so on. Usage against it is reported on that resource, not in the organization-wide view.
GET/groups/{group_id}/egress-usagegroup:read
Outbound-byte usage for a namespace, against its effective daily limit
Token scope
group:read
Send
Path
- group_iduuidGroup ID (usage is reported for its root namespace)
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
namespace_dayobject3 fields
- limit_bytesint64The limit for this window, in bytes — reported even where the limit is not enforced, so you can see what you would be held to.
- used_bytesint64Bytes charged to this window so far.
- windowstringThe period this covers:
YYYY-MM-DDTHHfor an hour,YYYY-MM-DDfor a day.
- plan_tierenterprisefreeproteamThe subscription plan an organization is on, which sets its resource limits. From smallest to
largest:
free,pro,team,enterprise. - root_group_iduuid
POST/admin/groups/{group_id}/reclaim-namenamespace_admin:manage
Reclaim an organization's name (platform admin)
Token scope
namespace_admin:manage
Send
Path
- group_iduuidThe organization whose name is reclaimed
Body
- hold_for_group_idobjectoptional
- new_nameobjectoptional
- notestringWhat a reclaim rests on — the report's reference and the right relied on, never who reported it: 1 to 2000 characters. It is kept for as long as the name is held back.
- reasonimpersonationinfringementWhy a platform administrator reclaims an organization's name. Only these two let the name be taken at once, once its owners have been sent the reasons.
Refuses
400The group is not an organization, or the request is invalid401Unauthenticated — no credential, or an invalid one403Not a platform administrator, or the new name is reserved404Group not found409The new name is taken or held back
Receive
groupobject11 fields
- avatarobjectoptional
- created_atstring
- created_byuuid
- descriptionobjectoptional
- display_nameobjectoptional
- full_pathstring
- group_iduuid
- group_namestring
- parent_group_idobjectoptional
- updated_atstring
- visibilityinternalprivatepublic
- held_for_group_idobjectoptional
- reasonimpersonationinfringementWhy a platform administrator reclaims an organization's name. Only these two let the name be taken at once, once its owners have been sent the reasons.
- reclaimed_atstringWhen the name was reclaimed.
- released_namestring
Limits
Three caps apply directly to what this page covers. All three refuse the request outright when you reach them — nothing is half-created, and no counter moves.
| Limit | What it counts | Value | What happens at the limit |
|---|---|---|---|
| Organisations per account | Groups you create with no parent | 3, raisable to 1000 | 429 TOO_MANY_REQUESTS on create. Delete one you no longer use, or ask for an increase |
| Members per group | People holding a membership on that one group | 50 on Free, 200 on Pro, 1000 on Team, 5000 on Enterprise; never above 50 000 | 429 TOO_MANY_REQUESTS on add. Remove somebody, change plan, or ask for an increase |
| Avatar upload size | Bytes in one image | 5 MiB, on every plan | 400 BAD_REQUEST before an upload URL is issued. Resize the image |
The member cap is per group, not per organisation, so a hundred-person company can run ten fifty-member teams on a plan whose cap is fifty. It counts the memberships written on that group — including the creator's Owner membership, which is there from the moment the group exists — and nothing else: people who reach the group through an ancestor do not occupy a slot, and neither do the group's service accounts, which have a cap of their own (10 on Free, 50 on Pro, 200 on Team, 1000 on Enterprise).
The organisation cap is per account and follows the person who created the group, not the group.
Three more caps shape a hierarchy and are worth knowing before you build one. Repositories and storage are reported by the usage views above; outbound transfer has its own view, because it is a rate rather than a level and is measured over a day:
| Limit | Scope | Free | Pro | Team | Enterprise |
|---|---|---|---|---|---|
| Repositories | per group | 20 | 200 | 2 000 | 20 000 |
| Storage | per organisation | 5 GiB | 100 GiB | 1 TiB | 10 TiB |
| Outbound transfer | per organisation, per day | 5 GiB | 500 GiB | 2 TiB | 10 TiB |
An Owner files an increase request against the organisation, naming the one limit and the value wanted, and it is reviewed before anything changes. An approved increase to a pooled or per-group limit applies to that organisation alone, and the new number appears in the limits view as soon as it is applied, because the view reports the limit enforcement actually uses. The organisations-per-account cap is the exception: it belongs to an account rather than to a namespace, so no group's limits view reports it — the only way to see where you stand is that creating one more either works or answers 429.
Troubleshooting
400 BAD_REQUESTon create, naming the name
- Cause
- The name is not a valid path segment — an uppercase letter, a space, an underscore, or a leading or trailing hyphen
- What to do
- Rewrite it as lowercase letters, digits and hyphens:
platform-team, notPlatform Team
400 BAD_REQUESTon any call, naming group_id
- Cause
- A path was pasted where an id belongs
- What to do
- Use the id, or the by-path endpoint. The CLI accepts either wherever it asks for a group
400 BAD_REQUESTon the by-path lookup, naming a segment
- Cause
- One segment of the path is not a valid name — an uppercase letter, a space, an underscore, or an empty segment from a doubled or trailing
/ - What to do
- Check that segment against the naming rules, then let the CLI or a generated client build the request: the whole path is one value, and assembling the URL by hand is what produces the empty segments
400 BAD_REQUESTon list, naming both filters
- Cause
- The request sent a parent id and a parent path together
- What to do
- Send one of them
400 BAD_REQUEST: Child visibility cannot exceed parent visibility
- Cause
- You asked for a group more open than the group above it
- What to do
- Raise the parent's visibility first, which needs Owner on the parent, or choose the lower setting
400 BAD_REQUEST: Cannot lower group visibility … is more visible
- Cause
- A sub-group or repository beneath this one is more open than the level you asked for
- What to do
- Lower the one the message names, then retry. Work from the leaves upwards
400 BAD_REQUESTon avatar upload, naming the content type
- Cause
- The file is not PNG, JPEG, GIF or WebP
- What to do
- Convert it. SVG, HEIC and TIFF are refused
400 BAD_REQUESTon avatar upload, naming the size
- Cause
- The declared size is zero or above 5 MiB
- What to do
- Send the file's exact byte count, and resize anything larger than 5 MiB
The upload URL is accepted but the PUT to it fails
- Cause
- The bytes sent do not match the size declared when the URL was issued, or the five-minute URL has expired
- What to do
- Request a new upload URL with the true byte count and send it straight away
400 NOT_AN_ORGANIZATIONon reclaiming a name
- Cause
- The group, or the group the name is to be held for, is a subgroup
- What to do
- Name the top-level group. Only an organisation holds a name that can be reclaimed, and only an organisation can be given one
400 BAD_REQUESTon reclaiming a name, about the organisation it is held for
- Cause
- The name was to be held for the very organisation it is taken from
- What to do
- Name a different organisation to hold it for, or none
400 BAD_REQUESTon create, saying service-account callers are not supported
- Cause
- An organisation was created with a service-account token
- What to do
- Run the create with a personal token or from the web app, then add the service account to the new group and let it do the rest
401 UNAUTHORIZED
- Cause
- No credential at all — on a read of a group that is not public, or on any change, which always needs one — or a token that is expired or revoked
- What to do
- Sign in, or mint a fresh token, and send it. Only a public group answers a read with no credential; an internal or private one answers
401before it will say whether it exists
403 FORBIDDENon creating a sub-group
- Cause
- Creating inside a group needs Maintainer on that group
- What to do
- Ask an Owner or Maintainer of the parent to raise your level, or to create it for you
403 FORBIDDENon update, where reading works
- Cause
- Metadata needs Maintainer, but any request that carries
visibilityat all needs Owner — even one that repeats the current value - What to do
- Drop
visibilityfrom the body if you are not changing it. If you are, ask an Owner to make the change
403 FORBIDDENon delete
- Cause
- Deleting needs Owner
- What to do
- Ask an Owner. There is no level between Maintainer and Owner that can delete
403 PERMISSION_REQUIREDnaming scope.delete, on renaming an organisation
- Cause
- Renaming an organisation needs Owner, because it gives the name up
- What to do
- Ask an Owner to rename it. A Maintainer can still rename subgroups and change the organisation's display name
403 RESERVED_NAMESPACEon creating or renaming an organisation
- Cause
- The name is a word Gitmoap keeps, or a well-known organisation's name — the message says which, and names the domain it is kept for
- What to do
- Choose another name. If it is your own organisation's name, create the organisation under another name, verify the domain the message names, then rename — see Take your reserved name
403 NAME_RESEMBLES_RESERVEDon creating or renaming an organisation
- Cause
- The name looks like a well-known organisation's name — a digit for a letter, a hyphen inside it, or a word such as
officialorsupportadded - What to do
- Choose another name. If the name it resembles is yours, verify that organisation's domain on your organisation first, then rename
403 FORBIDDENon reclaiming a name
- Cause
- Reclaiming is for Gitmoap's platform administrators, signed in — an Owner cannot, and no access token can
- What to do
- To report impersonation or infringement, write to the
legaldesk through the contact form
403 FORBIDDENon adding, changing or removing a member
- Cause
- Managing members needs Maintainer, and anything touching an Owner needs Owner
- What to do
- Ask an Owner to make the change, or to promote you
403 FORBIDDENon listing somebody else's groups
- Cause
- That listing is yours alone
- What to do
- List your own memberships instead. To see who is in a group, list the group's members
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 —
group:updateto rename,group_member:addto add somebody. Scopes are chosen at mint time and cannot be added afterwards
404 NOT_FOUNDon create
- Cause
- With a parent named: the parent id is wrong, or the parent is private and you are not in it. With no parent: you have signed in but have no profile yet
- What to do
- Read which the message names. For a parent, check the id and your membership; for an account, finish your profile and create the organisation again
404 NOT_FOUNDon list, with a parent path
- Cause
- No group sits at that path, or it is private and you are not a member
- What to do
- Check the spelling segment by segment, or list by parent id instead
404 NOT_FOUNDon a group you were told exists
- Cause
- It is private and you are not a member, or the path is misspelled
- What to do
- A private group answers
404to non-members so its existence stays private. Check the spelling, then ask to be added
404 NOT_FOUNDon add member
- Cause
- The person has no Gitmoap account, or the id in the URL is not theirs
- What to do
- Look the account up by username or email and add the id it returns. If there is no account, have them sign up — or, if you run single sign-on, invite them, or turn on automatic provisioning for a domain you have verified so their first login creates one
404 NOT_FOUNDon get, update or remove member
- Cause
- They hold no membership on this group
- What to do
- List the group's members first. They may reach the group through an ancestor instead
404 NOT_FOUNDon reclaiming a name
- Cause
- No group has that id, or none has the id the name is to be held for
- What to do
- Check both ids against the organisations' details
409 CONFLICTon create
- Cause
- Another group already holds that name under the same parent, or a group or repository already holds that full path — groups and repositories share one namespace
- What to do
- Pick another name. Nothing was created
409 CONFLICTon rename
- Cause
- A sibling group already holds the new name, or a group or repository already holds the new full path
- What to do
- Pick another name. The group keeps its old name and nothing beneath it moved
409 NAME_RETIREDon creating or renaming an organisation
- Cause
- Another organisation gave the name up and it is held — the message says until when, or that it is for good
- What to do
- Choose another name. If your own organisation renamed away from it, rename that same organisation back: a name is held for the organisation that gave it up
409 NAME_HOLD_LIMITon renaming an organisation
- Cause
- The organisation already holds five of its former names
- What to do
- Rename it back to one of them, which is always allowed, or contact support@gitmoap.com to release one
409 CONFLICTon reclaiming a name
- Cause
- The new name's path is taken, or no free
renamed-name was found - What to do
- Name a free new name explicitly and repeat. Nothing was changed
409 CONFLICTon delete: it still has child groups / it still has repositories
- Cause
- The group is not empty
- What to do
- Delete or move what is inside first, starting at the leaves. The message says which kind is blocking
409 CONFLICTon add member
- Cause
- They are already a member
- What to do
- Change their level instead of adding them again
409 CONFLICT: Cannot demote the organization's last Owner / Cannot remove the organization's last Owner
- Cause
- The organisation would be left with nobody able to administer it
- What to do
- Promote a second Owner, then repeat the change
429 TOO_MANY_REQUESTSon creating an organisation
- Cause
- You are at your organisation cap
- What to do
- Delete an organisation you no longer use, or request an increase. Nothing was created and no counter moved
429 TOO_MANY_REQUESTSon add member
- Cause
- This group is at its member cap for the plan
- What to do
- Remove a membership on this group, change plan, or request an increase. Granting the same person access from a parent group instead costs this group no slot
500 INTERNAL_ERRORon an avatar upload or delete
- Cause
- Image hosting is unavailable on Gitmoap's side
- What to do
- Contact support@gitmoap.com. Retrying will not change the result, and every other group operation is unaffected
501 NOT_IMPLEMENTEDon an avatar upload
- Cause
- This Gitmoap deployment does not host avatars
- What to do
- Set the group's
avatarfield to the address of a picture you host elsewhere. Every other group operation is unaffected
500 DATABASE_ERRORon any call
- Cause
- A transient failure on our side
- What to do
- Retry once. If it persists, report it with the time of the request — nothing was partially applied
Somebody you added sees a private repository in the group but cannot read its files, work items or merge requests
- Cause
- They were added at Guest, which shows that private content exists and reads none of it
- What to do
- Raise them to Reporter, the lowest level that reads private content
Somebody's access is higher than the level on their membership row
- Cause
- Their effective level is the highest they hold on this group or any group above it
- What to do
- Read the members of every group on the path above this one. The higher grant is where the access is coming from
You removed a member and they still have access
- Cause
- The membership that grants it lives on an ancestor group
- What to do
- Remove it there. Removing a row lower down cannot lower access granted higher up
The member count in the limits view is higher than the people you added
- Cause
- The creator's Owner membership is written when the group is created and counts like any other
- What to do
- Open the members list beside the count — it shows the same rows, the creator's included
A page of groups came back shorter than the limit you asked for
- Cause
- Groups you may not see are dropped from the page after it is read
- What to do
- Follow the next-page token until there is none. A short page is not the end of the list
Somebody else's organisation shows a name like yours, and yours shows your domain
- Cause
- The verified-domain badge is the difference: only the organisation that proved the domain shows it
- What to do
- Point people at the domain shown on the organisation. If the other organisation impersonates yours, report it to the
legaldesk through the contact form
Clone URLs stopped working after a rename
- Cause
- A rename rewrites the path of every repository beneath the group, and a git remote names its repository by path
- What to do
- Run
git remote set-urlagainst the new path in every clone. A remote cannot be addressed by id, so there is nothing to switch to that would survive the next rename
A group you created does not appear when a colleague lists groups
- Cause
- New organisations are private, and private groups are filtered out for people who are not members
- What to do
- Add them, or set the group to internal so everyone signed in can see it
FAQ
Can I move a group under a different parent?
Not as one operation — a group keeps the parent it was created with. Repositories can be transferred between groups, so the practical route is to create the group where you want it and transfer its repositories across, then delete the empty original.
What happens to a person's work when I remove them?
Nothing is deleted. Their commits, work items, comments, merge requests and releases stay exactly where they are and keep their name on them. They lose the ability to reach them, unless some other membership still grants it.
Does a sub-group need its own members?
No, and usually it should not have them. Grant at the level where the answer is the same for everything underneath, and add a sub-group membership only to raise somebody above what they inherit.
Which group do I ask for usage?
Any of them. Storage, pipeline consumption and outbound transfer are always reported for the organisation at the top of the chain. Only the per-group counts — members, repositories, webhooks — change with the group you name.
Why is a private group a 404 instead of a 403?
Because 403 would confirm it exists. For a private group, whose name may itself be sensitive, the response to a signed-in non-member is identical to the response for a group that was never created. Signed out you get 401 instead, which says nothing about the group either.
Related
- Repositoriescreating repositories inside a group, transferring them between groups, and repository-level members
- Your accountlooking an account up by username or email to get the id a membership call needs
- Access tokensminting a token with the
groupandgroup_memberscopes this page needs, and revoking one - Service accountsnon-human identities a group owns, with their own per-group cap
- Single sign-onconnecting an identity provider, verifying a domain — which also shows on your organisation and unlocks its reserved name — and inviting or auto-provisioning the people who sign in through it
- Billing and planswhat each plan raises, and how to request an increase to a limit you have reached
- Audit logwho created, renamed, deleted or re-levelled what, and when
- Repository rulesbranch and push rules set on a group so every repository beneath it inherits them
- Using providersthe pipeline steps a new organisation starts with, and how to install more
- Contact Gitmoapreporting an organisation that impersonates yours or infringes your rights, through the
legaldesk