> For the complete documentation index, see [llms.txt](https://docs.imerit.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.imerit.net/api/docs/organization.md).

# Organization

Organization and user management

## Get Organization Members

> Retrieves the members of your organization. Any User field can be used as a query filter, and \`sort\`, \`fields\` and \`populate\` work the same way as on the other list endpoints. Each member's \`organizations\` array is trimmed to your organization.

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Organization","description":"Organization and user management"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"OrgIdParam":{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID. The value is not read by the server: every organization endpoint resolves the organization from the API key, so the call always targets your own organization."}},"schemas":{"UserListResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"users":{"type":"array","items":{"$ref":"#/components/schemas/User"}},"total":{"type":"integer","description":"Number of members matching the filter, ignoring pagination"}}}}},"User":{"type":"object","description":"Credentials and tokens (password, API key, reset tokens, two factor secret) are never returned.","properties":{"_id":{"type":"string"},"id":{"type":"string","description":"Same value as `_id`"},"email":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["human","agent"]},"organizations":{"type":"array","description":"Organization memberships. On the members endpoint this is trimmed to your organization, and `organizationRole` here is the role that endpoint manages.","items":{"type":"object","properties":{"organization":{"type":"string"},"organizationRole":{"type":"string","enum":["admin","member"]}}}},"organization":{"type":"string","description":"ID of the user's active organization"},"organizationRole":{"type":"string","enum":["admin","member"],"description":"Role on the user's active organization"},"organizationLimit":{"type":"integer"},"pinnedProjects":{"type":"array","items":{"type":"string"}},"lastActiveAt":{"type":"string","format":"date-time"},"emailVerified":{"type":"boolean"},"globalExpert":{"type":"boolean"},"twoFactorEnabled":{"type":"boolean"},"notificationsSnoozed":{"type":"boolean"},"personalInformation":{"type":"object"},"professionalInformation":{"type":"object"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/organization/{orgId}/users":{"get":{"tags":["Organization"],"summary":"Get Organization Members","description":"Retrieves the members of your organization. Any User field can be used as a query filter, and `sort`, `fields` and `populate` work the same way as on the other list endpoints. Each member's `organizations` array is trimmed to your organization.","operationId":"getOrganizationMembers","parameters":[{"$ref":"#/components/parameters/OrgIdParam"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1},"description":"Page number (1-indexed). Sets the page size to 10 when `limit` is absent."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1},"description":"Items per page. Not capped; without it and without `page` no limit is applied."},{"name":"email","in":"query","schema":{"type":"string"},"description":"Filter by exact email"}],"responses":{"200":{"description":"Members retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserListResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```

## Update Members

> Sets the organization role of existing members. The body is not validated here, so a role outside \`admin\` and \`member\`, or a missing one, is stored as is and the member stops being treated as an admin. Entries whose email is not a member are skipped, but the returned counts still include them.

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Organization","description":"Organization and user management"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"OrgIdParam":{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID. The value is not read by the server: every organization endpoint resolves the organization from the API key, so the call always targets your own organization."}},"schemas":{"BulkUpdateMembersRequest":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"object","required":["email","organizationRole"],"properties":{"email":{"type":"string","format":"email"},"organizationRole":{"type":"string","enum":["admin","member"]}}}}}},"MemberBulkWriteResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"users":{"type":"object","properties":{"matchedCount":{"type":"integer","description":"Number of entries sent in the request, including ones that matched no member"},"modifiedCount":{"type":"integer","description":"Same value as `matchedCount`"}}}}}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/organization/{orgId}/users":{"post":{"tags":["Organization"],"summary":"Update Members","description":"Sets the organization role of existing members. The body is not validated here, so a role outside `admin` and `member`, or a missing one, is stored as is and the member stops being treated as an admin. Entries whose email is not a member are skipped, but the returned counts still include them.","operationId":"bulkUpdateMembers","parameters":[{"$ref":"#/components/parameters/OrgIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateMembersRequest"}}}},"responses":{"200":{"description":"Members updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberBulkWriteResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```

## Delete Members

> Removes members from your organization. The user account itself is kept and the member stays assigned to any project they were on. One seat is freed per entry that matches an existing user account, whether or not that account was a member. Entries whose email matches no account are skipped, but the returned counts still include them.

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Organization","description":"Organization and user management"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"OrgIdParam":{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID. The value is not read by the server: every organization endpoint resolves the organization from the API key, so the call always targets your own organization."}},"schemas":{"BulkDeleteMembersRequest":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string","format":"email"}}}},"MemberBulkWriteResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"users":{"type":"object","properties":{"matchedCount":{"type":"integer","description":"Number of entries sent in the request, including ones that matched no member"},"modifiedCount":{"type":"integer","description":"Same value as `matchedCount`"}}}}}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/organization/{orgId}/users":{"delete":{"tags":["Organization"],"summary":"Delete Members","description":"Removes members from your organization. The user account itself is kept and the member stays assigned to any project they were on. One seat is freed per entry that matches an existing user account, whether or not that account was a member. Entries whose email matches no account are skipped, but the returned counts still include them.","operationId":"bulkDeleteMembers","parameters":[{"$ref":"#/components/parameters/OrgIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteMembersRequest"}}}},"responses":{"200":{"description":"Members deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberBulkWriteResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```

## Get Organization Invites

> Retrieves the invitations of your organization, including ones already registered or revoked. Any Invitation field can be used as a query filter, and \`sort\`, \`fields\` and \`populate\` work the same way as on the other list endpoints.

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Organization","description":"Organization and user management"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"OrgIdParam":{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID. The value is not read by the server: every organization endpoint resolves the organization from the API key, so the call always targets your own organization."}},"schemas":{"InviteListResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"invites":{"type":"array","items":{"$ref":"#/components/schemas/Invitation"}},"total":{"type":"integer","description":"Number of invitations matching the filter, ignoring pagination. Only the list endpoint sets it."}}}}},"Invitation":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string","description":"Same value as `_id`"},"to":{"type":"string","format":"email","description":"Recipient email"},"sender":{"type":"string","description":"Email of the member who sent the invitation"},"organization":{"type":"string"},"organizationRole":{"type":"string","enum":["admin","member"]},"status":{"type":"string","enum":["pending","registered","revoked"]},"projectAssignments":{"type":"array","items":{"type":"object","properties":{"projectId":{"type":"string"},"projectRole":{"type":"string","enum":["Manager","Lead","Reviewer","Labeler"]}}}},"toExist":{"type":"boolean","description":"True when the recipient already had a user account"},"link":{"type":"string","description":"Invitation link sent to the recipient. Absent when generating or sending the email failed, which does not fail the request."},"sso":{"type":"boolean","description":"True when the recipient's email domain is bound to an SSO provider"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/organization/{orgId}/invites":{"get":{"tags":["Organization"],"summary":"Get Organization Invites","description":"Retrieves the invitations of your organization, including ones already registered or revoked. Any Invitation field can be used as a query filter, and `sort`, `fields` and `populate` work the same way as on the other list endpoints.","operationId":"getOrganizationInvites","parameters":[{"$ref":"#/components/parameters/OrgIdParam"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1},"description":"Page number (1-indexed). Sets the page size to 10 when `limit` is absent."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1},"description":"Items per page. Not capped; without it and without `page` no limit is applied."},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","registered","revoked"]},"description":"Filter by invitation status"}],"responses":{"200":{"description":"Invites retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteListResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```

## Send Invitations

> Invites people to your organization. Emails are lowercased and de-duplicated, and addresses that already belong to a member or already have a pending invitation are dropped, so the returned list can be shorter than \`to\`. Each new invitation consumes a seat, and the call fails with 403 when the subscription cannot cover every address in \`to\`, counted before the dropped ones are removed. Every recipient also gets an in-app notification.

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Organization","description":"Organization and user management"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"OrgIdParam":{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID. The value is not read by the server: every organization endpoint resolves the organization from the API key, so the call always targets your own organization."}},"schemas":{"InvitationRequest":{"type":"object","required":["to","organizationRole"],"properties":{"to":{"type":"array","items":{"type":"string","format":"email"},"minItems":1},"organizationRole":{"type":"string","enum":["admin","member"],"description":"Rejected with 400 when it is not one of these two values"},"projectAssignments":{"type":"array","items":{"type":"object","required":["projectId","projectRole"],"properties":{"projectId":{"type":"string"},"projectRole":{"type":"string","enum":["Manager","Lead","Reviewer","Labeler"],"description":"Not validated by the server, but only these values are recognised by the authorization layer. The value is copied onto the project when the invite is accepted."}}}},"organizationRoleAssignments":{"type":"object","additionalProperties":{"type":"string"},"description":"Per-email override of `organizationRole`, keyed by recipient email. Unlike `organizationRole` it is not validated, so an unrecognised role is stored as is."},"projectRoleAssignments":{"type":"object","additionalProperties":{"type":"string"},"description":"Per-email override of the project role, keyed by recipient email. Not validated either."}}},"InviteListResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"invites":{"type":"array","items":{"$ref":"#/components/schemas/Invitation"}},"total":{"type":"integer","description":"Number of invitations matching the filter, ignoring pagination. Only the list endpoint sets it."}}}}},"Invitation":{"type":"object","properties":{"_id":{"type":"string"},"id":{"type":"string","description":"Same value as `_id`"},"to":{"type":"string","format":"email","description":"Recipient email"},"sender":{"type":"string","description":"Email of the member who sent the invitation"},"organization":{"type":"string"},"organizationRole":{"type":"string","enum":["admin","member"]},"status":{"type":"string","enum":["pending","registered","revoked"]},"projectAssignments":{"type":"array","items":{"type":"object","properties":{"projectId":{"type":"string"},"projectRole":{"type":"string","enum":["Manager","Lead","Reviewer","Labeler"]}}}},"toExist":{"type":"boolean","description":"True when the recipient already had a user account"},"link":{"type":"string","description":"Invitation link sent to the recipient. Absent when generating or sending the email failed, which does not fail the request."},"sso":{"type":"boolean","description":"True when the recipient's email domain is bound to an SSO provider"},"deleted":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"BadRequestError":{"description":"Bad request - validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/organization/{orgId}/invites":{"post":{"tags":["Organization"],"summary":"Send Invitations","description":"Invites people to your organization. Emails are lowercased and de-duplicated, and addresses that already belong to a member or already have a pending invitation are dropped, so the returned list can be shorter than `to`. Each new invitation consumes a seat, and the call fails with 403 when the subscription cannot cover every address in `to`, counted before the dropped ones are removed. Every recipient also gets an in-app notification.","operationId":"sendInvitations","parameters":[{"$ref":"#/components/parameters/OrgIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRequest"}}}},"responses":{"200":{"description":"Invitations sent successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteListResponse"}}}},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```

## Delete Invites

> Revokes invitations by recipient email, not by invitation ID. The invitation row is kept and its status becomes \`revoked\`, and one seat is freed per revoked invitation.

```json
{"openapi":"3.0.3","info":{"title":"Ango Hub API v2","version":"2.0.0"},"tags":[{"name":"Organization","description":"Organization and user management"}],"servers":[{"url":"https://imeritapi.ango.ai/v2","description":"EU Production Server"},{"url":"https://us-api.ango.ai/v2","description":"US Production Server"},{"url":"https://in-api.ango.ai/v2","description":"India Production Server"},{"url":"https://testapi.ango.ai/v2","description":"Test Server"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"apikey","description":"API key for authentication. Format - apikey YOUR_API_KEY"}},"parameters":{"OrgIdParam":{"name":"orgId","in":"path","required":true,"schema":{"type":"string"},"description":"Organization ID. The value is not read by the server: every organization endpoint resolves the organization from the API key, so the call always targets your own organization."}},"schemas":{"BulkDeleteInvitesRequest":{"type":"object","required":["invites"],"properties":{"invites":{"type":"array","description":"Recipient emails of the invitations to revoke, not invitation IDs","items":{"type":"string","format":"email"}}}},"InviteBulkDeleteResponse":{"type":"object","properties":{"status":{"type":"string"},"data":{"type":"object","properties":{"invites":{"type":"object","properties":{"matchedCount":{"type":"integer","description":"Number of invitations actually revoked"},"modifiedCount":{"type":"integer","description":"Same value as `matchedCount`"}}}}}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"string","enum":["fail","error"]},"message":{"type":"string"}}}},"responses":{"UnauthorizedError":{"description":"Unauthorized - invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ForbiddenError":{"description":"Forbidden - insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"paths":{"/organization/{orgId}/invites":{"delete":{"tags":["Organization"],"summary":"Delete Invites","description":"Revokes invitations by recipient email, not by invitation ID. The invitation row is kept and its status becomes `revoked`, and one seat is freed per revoked invitation.","operationId":"bulkDeleteInvites","parameters":[{"$ref":"#/components/parameters/OrgIdParam"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteInvitesRequest"}}}},"responses":{"200":{"description":"Invites revoked successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteBulkDeleteResponse"}}}},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.imerit.net/api/docs/organization.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
