Summary and recommendation
The Atlas Admin API (`https://cloud.mongodb.com/api/atlas/v2`) uses date-versioned media types and HTTP Digest Authentication - standard Basic Auth is not accepted. Every request must include an `Accept` header specifying a versioned media type (e.g., `application/vnd.atlas.2023-02-01+json`); omitting it or using a stale version can return deprecated fields or errors.
All API keys must have an IP access list configured at creation time. Requests from unlisted IPs return HTTP 403, not 401 - a distinction that matters for debugging auth failures in CI/CD pipelines or dynamic-IP environments.
Atlas uses `groups` as the internal API term for projects. Every project-scoped endpoint uses `/groups/{groupId}` in the path, not `/projects/{projectId}`. This is consistent across the entire API surface and must be accounted for in any identity graph that maps Atlas resources to organizational units.
Pagination is offset-based using `pageNum` and `itemsPerPage` parameters, with a default page size of 100 and a maximum of 500. Rate limits are enforced per API key at approximately 100 requests per minute for general endpoints; HTTP 429 is returned on breach with no `Retry-After` header. Implement exponential backoff.
API quick reference
| Has user API | Yes |
| Auth method | HTTP Digest Authentication using Atlas API public/private key pairs |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | Enterprise |
Authentication
Auth method: HTTP Digest Authentication using Atlas API public/private key pairs
Setup steps
- Navigate to Atlas UI → Organization Settings → Access Manager → API Keys.
- Click 'Create API Key', assign an Organization role (e.g., Organization Owner), and note the Public Key and Private Key.
- Add an API Access List entry (IP allowlist) for the calling host; requests from unlisted IPs are rejected.
- Use HTTP Digest Auth in requests: public key as username, private key as password.
- Set the Accept header to 'application/vnd.atlas.2023-02-01+json' (or a later date-versioned media type) on all requests.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| Organization Owner | Full control over organization-level resources including creating/deleting org-level API keys and inviting users. | Create/delete organization users and API keys |
| Organization User Admin | Can manage organization users and teams but cannot manage billing or delete the organization. | Invite, update, and remove organization users |
| Project Owner | Full control over a specific project including adding/removing project-level users. | Add/remove users from a project, assign project roles |
| Organization Read Only | Read-only access to organization resources. | List organization users and teams |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique identifier for the Atlas user (UUID). | system-generated | immutable | Used as path parameter in user-specific endpoints. |
| username | string | Email address used as the Atlas login username. | required | immutable | Must be a valid email address. |
| firstName | string | User's first name. | required | supported | |
| lastName | string | User's last name. | required | supported | |
| emailAddress | string | User's email address; typically matches username. | required | supported | |
| mobileNumber | string | User's mobile phone number for MFA. | optional | supported | |
| password | string | User's password (write-only, never returned in responses). | required | supported | Not returned in GET responses. |
| country | string | ISO 3166-1 alpha-2 country code. | required | supported | |
| roles | array of objects | Array of role assignments; each object contains orgId or groupId and roleName. | optional | supported | roleName values: ORG_OWNER, ORG_MEMBER, ORG_READ_ONLY, GROUP_OWNER, GROUP_DATA_ACCESS_ADMIN, etc. |
| teamIds | array of strings | IDs of teams the user belongs to. | read-only | managed via teams endpoints | Assign users to teams via /orgs/{orgId}/teams/{teamId}/users. |
| links | array of objects | HATEOAS links for the resource. | system-generated | system-generated | |
| createdAt | string (ISO 8601) | Timestamp when the user was created. | system-generated | immutable | |
| lastAuth | string (ISO 8601) | Timestamp of the user's last authentication. | system-generated | system-generated |
Core endpoints
List Organization Users
- Method: GET
- URL:
https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/users - Watch out for: Returns only users who have accepted their invitation. Pending invitees appear under the invitations endpoint.
Request example
GET /api/atlas/v2/orgs/{orgId}/users?pageNum=1&itemsPerPage=100
Accept: application/vnd.atlas.2023-02-01+json
Response example
{
"results": [
{"id":"...","username":"user@example.com","firstName":"Jane","roles":[{"orgId":"...","roleName":"ORG_MEMBER"}]}
],
"totalCount": 1
}
Get Organization User by ID
- Method: GET
- URL:
https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/users/{userId} - Watch out for: userId is the Atlas internal UUID, not the email address.
Request example
GET /api/atlas/v2/orgs/{orgId}/users/{userId}
Accept: application/vnd.atlas.2023-02-01+json
Response example
{
"id": "5f5a6b3e1c9d440000d9a1b2",
"username": "user@example.com",
"firstName": "Jane",
"lastName": "Doe",
"roles": [{"orgId":"...","roleName":"ORG_MEMBER"}]
}
Create/Invite Organization User
- Method: POST
- URL:
https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/invites - Watch out for: New users receive an email invitation and must accept before appearing in the users list. Invitations expire after 30 days.
Request example
POST /api/atlas/v2/orgs/{orgId}/invites
Content-Type: application/vnd.atlas.2023-02-01+json
{
"username": "newuser@example.com",
"roles": [{"orgId":"...","roleName":"ORG_MEMBER"}]
}
Response example
{
"id": "invite-uuid",
"username": "newuser@example.com",
"expiresAt": "2024-12-01T00:00:00Z",
"status": "PENDING"
}
Update Organization User Roles
- Method: PATCH
- URL:
https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/users/{userId} - Watch out for: PATCH replaces the entire roles array; include all desired roles, not just the changed ones.
Request example
PATCH /api/atlas/v2/orgs/{orgId}/users/{userId}
Content-Type: application/vnd.atlas.2023-02-01+json
{
"roles": [{"orgId":"...","roleName":"ORG_READ_ONLY"}]
}
Response example
{
"id": "...",
"username": "user@example.com",
"roles": [{"orgId":"...","roleName":"ORG_READ_ONLY"}]
}
Remove User from Organization
- Method: DELETE
- URL:
https://cloud.mongodb.com/api/atlas/v2/orgs/{orgId}/users/{userId} - Watch out for: Cannot remove the last Organization Owner. Removing a user from the org also removes them from all projects within that org.
Request example
DELETE /api/atlas/v2/orgs/{orgId}/users/{userId}
Accept: application/vnd.atlas.2023-02-01+json
Response example
HTTP 204 No Content
List Project Users
- Method: GET
- URL:
https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/users - Watch out for: Atlas uses 'groups' as the internal term for projects in the API path.
Request example
GET /api/atlas/v2/groups/{groupId}/users?pageNum=1&itemsPerPage=100
Accept: application/vnd.atlas.2023-02-01+json
Response example
{
"results": [
{"id":"...","username":"user@example.com","roles":[{"groupId":"...","roleName":"GROUP_READ_ONLY"}]}
],
"totalCount": 1
}
Add User to Project
- Method: POST
- URL:
https://cloud.mongodb.com/api/atlas/v2/groups/{groupId}/invites - Watch out for: User must already exist in the organization or will receive an org + project invitation. Project path uses 'groups/{groupId}'.
Request example
POST /api/atlas/v2/groups/{groupId}/invites
Content-Type: application/vnd.atlas.2023-02-01+json
{
"username": "user@example.com",
"roles": [{"groupId":"...","roleName":"GROUP_DATA_ACCESS_READ_ONLY"}]
}
Response example
{
"id": "invite-uuid",
"username": "user@example.com",
"status": "PENDING"
}
Create Atlas User (global)
- Method: POST
- URL:
https://cloud.mongodb.com/api/atlas/v2/users - Watch out for: Creates a net-new Atlas account. If the email already has an Atlas account, use the invite endpoint instead. Password is write-only.
Request example
POST /api/atlas/v2/users
Content-Type: application/vnd.atlas.2023-02-01+json
{
"username": "newuser@example.com",
"password": "Str0ng!Pass",
"firstName": "Jane",
"lastName": "Doe",
"country": "US",
"roles": [{"orgId":"...","roleName":"ORG_MEMBER"}]
}
Response example
{
"id": "...",
"username": "newuser@example.com",
"firstName": "Jane",
"lastName": "Doe"
}
Rate limits, pagination, and events
- Rate limits: MongoDB Atlas Admin API enforces rate limits per API key. Limits vary by endpoint category. Exceeding limits returns HTTP 429.
- Rate-limit headers: No
- Retry-After header: No
- Rate-limit notes: Official docs do not publish granular per-endpoint rate limits publicly. HTTP 429 is returned on breach. Implement exponential backoff. Rate limits apply per API key, not per IP.
- Pagination method: offset
- Default page size: 100
- Max page size: 500
- Pagination pointer: pageNum / itemsPerPage
| Plan | Limit | Concurrent |
|---|---|---|
| All Atlas plans (M0, Flex, Dedicated, Enterprise) | 100 requests per minute per API key (general endpoints); some write endpoints lower | 0 |
- Webhooks available: No
- Webhook notes: MongoDB Atlas does not offer native user-lifecycle webhooks (e.g., user.created, user.deleted). Atlas does support alert notifications via webhooks for operational events (cluster alerts, backup failures), but these are not user-management events.
- Alternative event strategy: Poll the /orgs/{orgId}/users and /orgs/{orgId}/invites endpoints on a schedule to detect user changes. For audit events, use Atlas Audit Logs (available on M10+ clusters) exported to a SIEM.
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: Enterprise
- Endpoint: Not documented
Limitations:
- MongoDB Atlas does not provide a native SCIM 2.0 endpoint.
- User provisioning via IdP (Okta, Entra ID, Google Workspace) is supported through Federated Authentication (SAML 2.0 / OIDC) with Just-In-Time (JIT) provisioning only.
- JIT provisioning creates Atlas accounts on first SSO login but does not support automated deprovisioning or attribute sync via SCIM.
- Deprovisioning must be handled via the Atlas Admin API or manual removal.
- Enterprise Advanced plan ($5,000+/year) is required for Federated Authentication features.
Common scenarios
Onboarding a net-new user requires branching on whether the target email already holds an Atlas account. Use POST /api/atlas/v2/users for new accounts (providing username, password, firstName, lastName, country, and initial org role).
For existing Atlas accounts, use POST /api/atlas/v2/orgs/{orgId}/invites instead - sending to an existing email via the global users endpoint returns a conflict error.
Project assignment via POST /api/atlas/v2/groups/{groupId}/invites can only follow after the org invitation is accepted; the API does not support pre-staging project membership.
Deprovisioning requires three discrete steps that do not cascade automatically: (1) DELETE /api/atlas/v2/orgs/{orgId}/users/{userId} removes the user from the org and all its projects in one call; (2) pending invitations must be revoked separately via DELETE /api/atlas/v2/orgs/{orgId}/invites/{invitationId}; (3) API keys owned by the user must be audited via GET /api/atlas/v2/orgs/{orgId}/apiKeys and deleted individually. Skipping step 3 leaves active programmatic credentials in place after the human user is removed.
For bulk role changes, the Teams API (POST /api/atlas/v2/orgs/{orgId}/teams) is the correct abstraction. Teams are org-scoped and assigned to projects with specific roles via POST /api/atlas/v2/groups/{groupId}/teams. Role updates use PATCH /api/atlas/v2/groups/{groupId}/teams/{teamId} and replace the entire roleNames array - partial updates are not supported. Individual team membership is managed via POST/DELETE on /api/atlas/v2/orgs/{orgId}/teams/{teamId}/users.
Role updates on individual users via PATCH /api/atlas/v2/orgs/{orgId}/users/{userId} also replace the entire roles array. Always retrieve the current roles first and merge before sending the PATCH body to avoid unintentionally stripping existing assignments.
Onboard a new user to an organization and project
- POST /api/atlas/v2/users to create a new Atlas account (if the user has no existing Atlas account), providing username (email), password, firstName, lastName, country, and initial org role.
- If the user already has an Atlas account, POST /api/atlas/v2/orgs/{orgId}/invites with their email and desired org role to send an org invitation.
- Once the user accepts the org invitation (or after account creation), POST /api/atlas/v2/groups/{groupId}/invites to add them to the specific project with the appropriate GROUP_* role.
- Verify membership by GET /api/atlas/v2/groups/{groupId}/users and confirming the user appears with the correct role.
Watch out for: Users must accept the org invitation before they can be added to a project via the API. Attempting to add a non-org-member to a project will send a combined org+project invitation.
Deprovision a departing user
- GET /api/atlas/v2/orgs/{orgId}/users to retrieve the user's Atlas userId by matching on username (email).
- DELETE /api/atlas/v2/orgs/{orgId}/users/{userId} to remove the user from the organization and all its projects in one call.
- If the user has pending invitations, GET /api/atlas/v2/orgs/{orgId}/invites and DELETE /api/atlas/v2/orgs/{orgId}/invites/{invitationId} to revoke them.
- Rotate or delete any personal API keys the user owned via GET /api/atlas/v2/orgs/{orgId}/apiKeys and DELETE /api/atlas/v2/orgs/{orgId}/apiKeys/{apiUserId}.
Watch out for: Org deletion cascades to all projects, but API keys created by the user are not automatically deleted. Audit and revoke them separately to prevent orphaned access.
Bulk update project roles for a team
- Create or retrieve a team: POST /api/atlas/v2/orgs/{orgId}/teams with a name and array of usernames.
- Add the team to the project with a role: POST /api/atlas/v2/groups/{groupId}/teams with body {"teamId":"...","roleNames":["GROUP_READ_ONLY"]}.
- To change the team's project role: PATCH /api/atlas/v2/groups/{groupId}/teams/{teamId} with the new roleNames array.
- Add or remove individual users from the team via POST/DELETE /api/atlas/v2/orgs/{orgId}/teams/{teamId}/users rather than updating each project assignment individually.
Watch out for: Teams are org-scoped but assigned to projects with specific roles. Changing a team's project role via PATCH replaces all roles for that team in that project.
Why building this yourself is a trap
The most significant integration trap is the invitation acceptance dependency. The /orgs/{orgId}/users endpoint returns only users who have accepted their invitation; pending invitees appear exclusively under /orgs/{orgId}/invites. Any identity graph or access reconciliation job that queries only the users endpoint will produce an incomplete picture of who has been granted access to the organization.
JIT provisioning via SAML/OIDC federation creates Atlas accounts on first SSO login but writes no event to a webhook or audit stream that an integration can consume in real time. Atlas does not offer native user-lifecycle webhooks.
Detecting new JIT-provisioned users requires polling /orgs/{orgId}/users on a schedule and diffing against a known state - a pattern that introduces latency between provisioning and governance visibility.
The SCIM gap is structural: MongoDB Atlas has no native SCIM 2.0 endpoint at any plan tier. Federated authentication (SAML/OIDC) with JIT is the closest native analog, but it covers only provisioning on first login and provides no deprovisioning signal.
Any integration that assumes SCIM-style push-based lifecycle events will need to be redesigned around pull-based API polling and explicit deletion calls. Connecting Atlas to an identity graph via an MCP server with 60+ deep IT/identity integrations is one pattern for centralizing this polling and reconciliation logic across the full user lifecycle.
Automate MongoDB workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.