Summary and recommendation
Google Gemini has no standalone user management API. All provisioning, suspension, and deprovisioning is handled through the Admin SDK Directory API (base URL: https://admin.googleapis.com/admin/directory/v1), which manages the underlying Google Workspace user objects.
Gemini feature access is a downstream effect of orgUnitPath assignment and the Workspace plan tier bound to that OU - there is no API field or endpoint to toggle Gemini access independently.
Authentication requires OAuth 2.0; for automated pipelines, a service account with domain-wide delegation is the standard pattern, and the service account must impersonate a super-admin via the sub claim in the JWT.
Integrating this API into an identity graph enables cross-system correlation of Workspace user state, OU membership, and downstream Gemini access tier without manual console inspection.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (service account with domain-wide delegation, or 3-legged OAuth for admin users) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Google Workspace (any paid plan; Gemini features included in Business Standard and above as of March 2025) |
Authentication
Auth method: OAuth 2.0 (service account with domain-wide delegation, or 3-legged OAuth for admin users)
Setup steps
- Create a Google Cloud project at console.cloud.google.com.
- Enable the Admin SDK API in the project's API Library.
- Create a Service Account and download the JSON key, or configure an OAuth 2.0 client ID for 3-legged flows.
- For service accounts: grant domain-wide delegation in the Google Workspace Admin Console under Security > API Controls > Domain-wide Delegation.
- Authorize the required OAuth scopes for the service account client ID.
- Use the service account to impersonate a super-admin when making API calls (set 'sub' claim to admin email in JWT).
Required scopes
| Scope | Description | Required for |
|---|---|---|
| https://www.googleapis.com/auth/admin.directory.user | Full read/write access to user accounts in the domain. | Create, update, delete, and list users |
| https://www.googleapis.com/auth/admin.directory.user.readonly | Read-only access to user accounts. | List and get user details |
| https://www.googleapis.com/auth/admin.directory.user.security | Manage user security settings (tokens, ASPs, verification codes). | Revoking tokens, managing 2FA |
| https://www.googleapis.com/auth/admin.directory.group | Read/write access to groups and group memberships. | Group-based Gemini feature access management |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| primaryEmail | string | User's primary email address (immutable after creation in most cases). | required | optional | Must be within the domain. Changing requires admin action. |
| name.givenName | string | User's first name. | required | optional | Max 60 characters. |
| name.familyName | string | User's last name. | required | optional | Max 60 characters. |
| password | string | User's password (hashed or plaintext on create). | required | optional | Min 8 characters. Use hashFunction field to specify MD5/SHA-1 if pre-hashed. |
| id | string | Immutable unique identifier for the user (Google-assigned). | server-assigned | read-only | Use as stable identifier; primaryEmail can change. |
| suspended | boolean | Whether the user account is suspended. | optional | optional | Suspended users cannot sign in or use Gemini. |
| suspensionReason | string | Reason for suspension (read-only, set by Google). | read-only | read-only | Populated when suspended=true. |
| orgUnitPath | string | Organizational unit the user belongs to. | optional | optional | Controls which Workspace/Gemini policies apply. Defaults to root OU. |
| isAdmin | boolean | Whether the user has super-admin privileges. | optional | optional | Use makeAdmin method to promote; cannot demote self. |
| isDelegatedAdmin | boolean | Whether the user is a delegated admin. | read-only | read-only | Set via Admin Console roles, not directly via API. |
| emails | array | List of email addresses for the user. | optional | optional | Includes aliases and alternate addresses. |
| phones | array | List of phone numbers. | optional | optional | Each entry has 'value' and 'type' fields. |
| recoveryEmail | string | Recovery email address for the user. | optional | optional | Used for account recovery flows. |
| recoveryPhone | string | Recovery phone number in E.164 format. | optional | optional | Must include country code. |
| changePasswordAtNextLogin | boolean | Forces password change on next login. | optional | optional | Recommended for provisioned accounts. |
| agreedToTerms | boolean | Whether user has accepted Google's Terms of Service. | read-only | read-only | Set automatically on first login. |
| lastLoginTime | datetime | Timestamp of user's last login. | read-only | read-only | ISO 8601 format. May be delayed up to 24 hours. |
| creationTime | datetime | Timestamp when the account was created. | server-assigned | read-only | ISO 8601 format. |
| customSchemas | object | Custom attribute schemas defined for the domain. | optional | optional | Must define schema first via Admin SDK Schemas resource. |
| isEnrolledIn2Sv | boolean | Whether the user is enrolled in 2-Step Verification. | read-only | read-only | Relevant for security posture; enforce via OU policy. |
Core endpoints
Create User
- Method: POST
- URL:
https://admin.googleapis.com/admin/directory/v1/users - Watch out for: New users may take up to 24 hours to appear in all Google services including Gemini. Password must meet domain policy requirements.
Request example
POST /admin/directory/v1/users
{
"primaryEmail": "jdoe@example.com",
"name": {"givenName": "Jane", "familyName": "Doe"},
"password": "TempPass123!",
"changePasswordAtNextLogin": true,
"orgUnitPath": "/Engineering"
}
Response example
{
"kind": "admin#directory#user",
"id": "118153477854...",
"primaryEmail": "jdoe@example.com",
"name": {"givenName": "Jane", "familyName": "Doe"},
"suspended": false,
"creationTime": "2025-01-15T10:00:00.000Z"
}
Get User
- Method: GET
- URL:
https://admin.googleapis.com/admin/directory/v1/users/{userKey} - Watch out for: userKey can be primaryEmail, alias email, or immutable user ID. Use the immutable ID for reliability.
Request example
GET /admin/directory/v1/users/jdoe@example.com
Response example
{
"kind": "admin#directory#user",
"id": "118153477854...",
"primaryEmail": "jdoe@example.com",
"name": {"givenName": "Jane", "familyName": "Doe"},
"suspended": false,
"orgUnitPath": "/Engineering",
"lastLoginTime": "2025-01-14T08:30:00.000Z"
}
List Users
- Method: GET
- URL:
https://admin.googleapis.com/admin/directory/v1/users?domain={domain}&maxResults=500&pageToken={token} - Watch out for: Must specify either 'domain' or 'customer=my_customer'. Use 'my_customer' as the customer value to reference the authenticated admin's domain.
Request example
GET /admin/directory/v1/users?domain=example.com&maxResults=200&orderBy=email
Response example
{
"kind": "admin#directory#users",
"nextPageToken": "CAESB...",
"users": [
{"primaryEmail": "asmith@example.com", "id": "..."},
{"primaryEmail": "jdoe@example.com", "id": "..."}
]
}
Update User (partial)
- Method: PATCH
- URL:
https://admin.googleapis.com/admin/directory/v1/users/{userKey} - Watch out for: Use PATCH (not PUT) for partial updates. PUT replaces the entire user object and requires all required fields.
Request example
PATCH /admin/directory/v1/users/jdoe@example.com
{
"orgUnitPath": "/Sales",
"suspended": false
}
Response example
{
"kind": "admin#directory#user",
"id": "118153477854...",
"primaryEmail": "jdoe@example.com",
"orgUnitPath": "/Sales",
"suspended": false
}
Suspend User
- Method: PATCH
- URL:
https://admin.googleapis.com/admin/directory/v1/users/{userKey} - Watch out for: Suspended users immediately lose access to Gemini and all Workspace services. Suspension is reversible; deletion is not.
Request example
PATCH /admin/directory/v1/users/jdoe@example.com
{
"suspended": true
}
Response example
{
"kind": "admin#directory#user",
"id": "118153477854...",
"primaryEmail": "jdoe@example.com",
"suspended": true,
"suspensionReason": "ADMIN"
}
Delete User
- Method: DELETE
- URL:
https://admin.googleapis.com/admin/directory/v1/users/{userKey} - Watch out for: Deleted users are moved to a 20-day recovery window before permanent deletion. Data recovery is possible within this window via Admin Console. Cannot be undone via API after the window.
Request example
DELETE /admin/directory/v1/users/jdoe@example.com
Response example
HTTP 204 No Content
Make User Admin
- Method: POST
- URL:
https://admin.googleapis.com/admin/directory/v1/users/{userKey}/makeAdmin - Watch out for: Grants super-admin privileges. Use delegated admin roles via Admin Console for least-privilege access instead.
Request example
POST /admin/directory/v1/users/jdoe@example.com/makeAdmin
{
"status": true
}
Response example
HTTP 204 No Content
Search/Filter Users
- Method: GET
- URL:
https://admin.googleapis.com/admin/directory/v1/users?domain={domain}&query={query} - Watch out for: Query syntax uses field:value format (e.g., 'email:jdoe*'). Not all fields are searchable. orgUnitPath filter returns users in that OU only, not sub-OUs, unless using orgUnitPath=/OU/* pattern.
Request example
GET /admin/directory/v1/users?domain=example.com&query=orgUnitPath%3D%2FEngineering&maxResults=500
Response example
{
"kind": "admin#directory#users",
"users": [
{"primaryEmail": "eng1@example.com", "orgUnitPath": "/Engineering"}
]
}
Rate limits, pagination, and events
- Rate limits: Admin SDK Directory API enforces per-project and per-domain quotas. Default is 1,500 queries per 100 seconds per project, and 10 queries per second per user.
- Rate-limit headers: No
- Retry-After header: No
- Rate-limit notes: Quota increases can be requested via Google Cloud Console. Errors return HTTP 429 with reason 'rateLimitExceeded' or 'userRateLimitExceeded'. Implement exponential backoff. Batch requests count as one HTTP call but each sub-request counts toward quota.
- Pagination method: token
- Default page size: 100
- Max page size: 500
- Pagination pointer: pageToken
| Plan | Limit | Concurrent |
|---|---|---|
| All Google Workspace plans (including Gemini-included tiers) | 1,500 requests/100 seconds per project; 10 requests/second per user | 0 |
- Webhooks available: Yes
- Webhook notes: Google Admin SDK supports push notifications (webhooks) via the Reports API and Directory API watch endpoints. Clients register a channel with a callback URL to receive notifications when resources change.
- Alternative event strategy: Poll the Admin SDK Reports API (activities.list) for audit log events if push notifications are not feasible. Reports API provides detailed admin activity logs.
- Webhook events: user.add, user.delete, user.update, user.suspend, user.unsuspend, login.login, login.logout, admin.user.password_change
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Google Workspace (any paid plan; Gemini features included in Business Standard and above as of March 2025)
Endpoint: https://www.googleapis.com/auth/admin.directory.user (SCIM provisioning is configured per third-party IdP via Google Workspace Admin Console under Directory > Directory settings > Auto-provisioning, not a standalone SCIM base URL exposed directly)
Supported operations: Create user (POST /Users), Read user (GET /Users/{id}), Update user (PUT /Users/{id}), Patch user (PATCH /Users/{id}), Delete/deprovision user (DELETE /Users/{id}), List users (GET /Users), Create group (POST /Groups), Read group (GET /Groups/{id}), Update group membership (PATCH /Groups/{id}), Delete group (DELETE /Groups/{id})
Limitations:
- SCIM provisioning to Google Workspace is configured from the IdP side (e.g., Okta, Azure AD); Google does not publish a standalone SCIM base URL for inbound provisioning in the same way as other SaaS apps.
- Google Workspace acts as the identity source (IdP) for outbound SCIM to third-party apps, not typically as a SCIM SP for inbound provisioning from external IdPs via a public endpoint.
- Gemini-specific feature access (e.g., Gemini side panels) is controlled by OU assignment and Workspace plan, not by SCIM attributes.
- Custom SCIM attribute mappings are limited to fields supported by the Admin SDK Directory API.
- SCIM provisioning changes may take up to 24 hours to propagate across all Google services.
Common scenarios
Three automation scenarios cover the majority of Gemini-related lifecycle operations via the Directory API. For provisioning with Gemini access, POST to /users with orgUnitPath set to an OU on Business Standard or higher.
full Gemini features can take up to 24 hours to propagate, and users in OUs on Business Starter are capped at 5 prompts/day regardless of account creation timing. For bulk offboarding, paginate GET /users using pageToken (max 500 per page), filter for offboarding targets, then PATCH each with suspended: true.
use batch requests to stay within the 1,500 req/100s project-level quota, and note that suspension immediately revokes Gemini access but does not release the billing seat - a subsequent DELETE is required to stop seat charges.
For OU-based tier changes, PATCH /users/{userKey} with the target orgUnitPath to move users between Gemini tiers, then audit moves via the Reports API filtering for USER_MOVE_TO_ORG_UNIT events, allowing up to 24 hours for policy propagation.
Provision a new employee with Gemini access
- POST /admin/directory/v1/users with primaryEmail, name, password, orgUnitPath set to an OU covered by a Workspace plan that includes Gemini (Business Standard or higher).
- Verify the user's orgUnitPath maps to the correct Workspace license tier in Admin Console > Billing > Subscriptions.
- Optionally PATCH the user to set changePasswordAtNextLogin: true and recoveryEmail.
- Wait up to 24 hours for Gemini features to become available in the user's account.
- Confirm access by checking Admin Console > Reports > User activity for Gemini usage events.
Watch out for: Gemini feature availability depends on the OU's assigned Workspace plan, not just account creation. Users in OUs on Business Starter get limited Gemini (5 prompts/day); full Gemini requires Business Standard or higher.
Bulk suspend offboarded users
- GET /admin/directory/v1/users?domain=example.com&maxResults=500 and paginate through all users using nextPageToken.
- Filter the response client-side for users matching offboarding criteria (e.g., department, last login date from Reports API).
- For each target user, PATCH /admin/directory/v1/users/{userKey} with {"suspended": true}.
- Use batch requests (up to 1,000 per batch) to reduce HTTP overhead, respecting the 1,500 req/100s quota.
- Implement exponential backoff on HTTP 429 responses.
- Verify suspension via GET /admin/directory/v1/users/{userKey} and confirm suspended: true.
Watch out for: Suspension immediately revokes Gemini and Workspace access. If the intent is permanent offboarding, follow up with DELETE after data transfer/export is complete. Suspended users still consume a Workspace license seat.
Move users between OUs to change Gemini feature tier
- Identify the target OU paths corresponding to the desired Workspace plan tier in Admin Console.
- PATCH /admin/directory/v1/users/{userKey} with {"orgUnitPath": "/NewOU"} for each user.
- For bulk moves, use batch requests and paginate the user list as needed.
- Allow up to 24 hours for policy changes (including Gemini feature access) to propagate.
- Audit changes via Admin SDK Reports API: GET /admin/reports/v1/activity/users/all/applications/admin filtering for USER_MOVE_TO_ORG_UNIT events.
Watch out for: OU-based Gemini access is tied to the Workspace license assigned to that OU. Moving a user to an OU on a lower-tier plan (e.g., Business Starter) will reduce their Gemini capabilities to 5 prompts/day. Ensure billing reflects the correct seat counts per plan tier.
Why building this yourself is a trap
The primary integration trap is treating primaryEmail as a stable foreign key in an identity graph - it is mutable and unavailable for reuse during the 20-day post-deletion recovery window; use the immutable id field for all cross-system references instead.
A second trap is scope underprovisioning: the admin.directory.user scope is required for write operations, but group-based Gemini access management also requires admin.directory.group, and omitting it silently breaks OU-group hybrid access models.
Rate limits are enforced at the Google Cloud project level, not per domain - multiple integrations sharing a project share the 1,500 req/100s quota, and HTTP 429 errors will not include a Retry-After header, so exponential backoff must be implemented explicitly.
Finally, push notification channels via the Directory API watch endpoint expire without auto-renewal; pipelines that rely on event-driven sync must implement channel refresh logic or fall back to polling the Reports API activities.list endpoint.
Automate Google Gemini 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.