Organizeteams
PUT/teams/{team_id}/members/{user_id}
Put a person on a team, or change their place on it.
put_team_member
team:manage
A token needs theteam:managescope: Create, change and delete teams, and change who is on themGranted bywrite_api.Every operation this scope unlocksAudited · mutation
x-gitmoap-audit: {"kind":"audited","arg":"mutation"}
Quota · members per team
x-gitmoap-quota: {"kind":"enforced","arg":"members_per_team"}
Dry run
Takesdry_run.
Sets the person's role on the team (member or maintainer) and an optional end date. The team's
maintainers, and whoever manages the organization's teams, may call it; when the change gives
more — a new place, a higher role, a later end — the caller must also be able to give every
grant the team holds. Only people join teams, and a roster kept by the identity provider is
changed there instead. Answers 201 when the person is added and 200 when their place
changes; with dry_run=true it says what they would gain, and nothing changes.
Parameters
Path
- team_idTeamId (string · uuid)Team ID
- user_idUserId (string · uuid)The person
Query
- dry_runbooleanoptionalSay what they would gain, and change nothing
Request body
application/json- expires_atstring · date-time or nulloptional
- roleTeamMemberRolemembermaintaineroptionalA member's place on a team. Maintainers manage the roster.
Request body exampleSynthesized example
{}
Responses
200Their place as it now stands, or a previewapplication/json
- dry_runbooleanWhether this was only a preview, and nothing was changed.
gained_accessTeamAccessReachThe team's access, which the person now has through it.
- The TeamAccessReach schema
- grantsinteger · int64Grants the team holds.
- hidden_scopesbooleanWhether the team also holds access somewhere you cannot see. Those places are never named.
- scopes_visible_to_youinteger · int64Groups and repositories among them that you can see.
memberTeamMember
- The TeamMember schema
- created_atstring · date-time
- roleTeamMemberRolemembermaintainerA member's place on a team. Maintainers manage the roster.
- team_idTeamId (string · uuid)
userActorSummary
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring or nulloptional
added_byActorSummary or nulloptional
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring or nulloptional
- expires_atstring · date-time or nulloptionalWhen their place on the team ends. After it, the team's access no longer reaches them.
- synced_atstring · date-time or nulloptionalWhen the identity provider last confirmed this place, for a mirrored roster.
200 exampleSynthesized example
{
"dry_run": false,
"gained_access": {
"grants": 82,
"hidden_scopes": false,
"scopes_visible_to_you": 45
},
"member": {
"created_at": "2026-10-12T02:18:48Z",
"role": "member",
"team_id": "8b0ca319-3590-45ee-b948-37488753e8cf",
"user": {
"email": "lin@acme.example",
"id": "id-80d9",
"username": "mara",
"avatar_url": "https://gitmoap.example/acme/e7aae8ba"
},
"added_by": {
"email": "mara@acme.example",
"id": "id-e292",
"username": "tomas",
"avatar_url": "https://gitmoap.example/acme/c7f281c3"
},
"expires_at": "2026-10-10T23:51:52Z",
"synced_at": "2026-10-16T11:03:38Z"
}
}
201Put on the teamapplication/json
- dry_runbooleanWhether this was only a preview, and nothing was changed.
gained_accessTeamAccessReachThe team's access, which the person now has through it.
- The TeamAccessReach schema
- grantsinteger · int64Grants the team holds.
- hidden_scopesbooleanWhether the team also holds access somewhere you cannot see. Those places are never named.
- scopes_visible_to_youinteger · int64Groups and repositories among them that you can see.
memberTeamMember
- The TeamMember schema
- created_atstring · date-time
- roleTeamMemberRolemembermaintainerA member's place on a team. Maintainers manage the roster.
- team_idTeamId (string · uuid)
userActorSummary
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring or nulloptional
added_byActorSummary or nulloptional
- The ActorSummary schema
- emailstring
- idstring
- usernamestring
- avatar_urlstring or nulloptional
- expires_atstring · date-time or nulloptionalWhen their place on the team ends. After it, the team's access no longer reaches them.
- synced_atstring · date-time or nulloptionalWhen the identity provider last confirmed this place, for a mirrored roster.
201 exampleSynthesized example
{
"dry_run": false,
"gained_access": {
"grants": 70,
"hidden_scopes": false,
"scopes_visible_to_you": 37
},
"member": {
"created_at": "2026-10-14T07:26:42Z",
"role": "member",
"team_id": "fae5e1a6-0d2e-4fdc-b393-152992e4809a",
"user": {
"email": "lin@acme.example",
"id": "id-0501",
"username": "lin",
"avatar_url": "https://gitmoap.example/acme/ecd8f5ec"
},
"added_by": {
"email": "mara@acme.example",
"id": "id-699b",
"username": "lin",
"avatar_url": "https://gitmoap.example/acme/fb49be3a"
},
"expires_at": "2026-10-13T17:14:59Z",
"synced_at": "2026-10-13T13:53:44Z"
}
}
400Invalid requestapplication/json
Error codes
- BAD_REQUESTThe request is malformed: a parameter or a body field is not a well-formed value of its type
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
400 exampleSynthesized example
{
"error": {
"code": "code-fef9",
"message": "Inline scalar newtypes but keep their brand"
}
}
401Authentication requiredapplication/json
Error codes
- UNAUTHORIZEDNo credential was sent, or the one sent is invalid, expired or revoked
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
401 exampleSynthesized example
{
"error": {
"code": "code-d34e",
"message": "Draw the region map from operation density"
}
}
403The caller cannot change this roster, or cannot give the access the team holdsapplication/json
Error codes
- ACCESS_ESCALATIONThe change would give someone more access than you hold yourself
- FORBIDDENYou are signed in but may not do this here;
reasonnames the permission or the rule that refused it - INSUFFICIENT_SCOPEThe access token lacks the scope this operation needs;
required_scopenames it - PERMISSION_REQUIREDYou need a permission you do not hold here; the message names it
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
403 exampleSynthesized example
{
"error": {
"code": "code-e282",
"message": "Stream pipeline status into the run header"
}
}
404Team or person not foundapplication/json
Error codes
- NOT_FOUNDThe resource does not exist — or exists and you cannot see it: a private resource you have no access to answers exactly as an absent one does
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
404 exampleSynthesized example
{
"error": {
"code": "code-0e10",
"message": "Draw the region map from operation density"
}
}
409The team's people are kept by the identity providerapplication/json
Error codes
- CONFLICTThe request conflicts with the resource's current state;
reasonsays how - LEGAL_ACCEPTANCE_REQUIREDAccept the current Terms of Service before changing anything; reading stays open
- TEAM_ROSTER_MANAGED_BY_IDPThe team's members are kept by the identity provider; change the group there
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
409 exampleSynthesized example
{
"error": {
"code": "code-3a32",
"message": "Label every synthesized example"
}
}
422A service account cannot join a teamapplication/json
Error codes
- NOT_A_USERA team is made of people; give a service account access directly instead
- UNPROCESSABLE_ENTITYThe request is well-formed but asks for something the resource's rules do not allow;
reasonsays which
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
422 exampleSynthesized example
{
"error": {
"code": "code-152d",
"message": "Label every synthesized example"
}
}
429Member limit reached for this teamapplication/json
Error codes
- TOO_MANY_REQUESTSRetryableA quota, a rate limit or a transfer budget is spent. When the response carries
Retry-After, retry after that many seconds
errorErrorBody
- The ErrorBody schema
- codestringThe coarse category, tied to the status:
NOT_FOUND,CONFLICT,INSUFFICIENT_SCOPE. Every error has one; the API reference's error catalogue lists them all. - messagestringWhat went wrong, for a person. Written to be read, not parsed: match on
reasonorcode. - fieldstring or nulloptionalOn a
400that refused one field's value, the field, as its JSON path:email,items[0].name. Put the message under that input. Absent on every other error. - reasonstring or nulloptionalThe specific code, when the error has one:
LAST_ORGANIZATION_OWNER,BRANCH_PROTECTED. The message starts with it too. Match on this when it is present, and oncodeotherwise. - required_scopestring or nulloptionalThe scope the access token was missing, on
INSUFFICIENT_SCOPE. - violationsanyoptionalPresent on the structured-validation errors (
PROVIDER_VALIDATION_FAILEDper-node,PIPELINE_VALIDATION_FAILEDDAG): a JSON array of the offending elements, so a caller can fix every one in a single round-trip. Absent (omitted) on every other error.
429 exampleSynthesized example
{
"error": {
"code": "code-b87f",
"message": "Stream pipeline status into the run header"
}
}
CLI
gitmoap teams put-team-member
- --team-ididTeam ID
- --user-ididThe person
- --dry-runflagoptionalSay what they would gain, and change nothing
- --expires-atstringoptional
- --rolemember | maintaineroptional