Summary and recommendation
ChatGPT Enterprise exposes a SCIM 2.0 API at https://api.openai.com/scim/v2, authenticated via a static bearer token generated in the admin console. This is the only programmatic path for ChatGPT workspace user management - there is no separate general-purpose REST API.
The OpenAI Platform API at platform.openai.com is scoped to AI model access and is an entirely separate system.
For teams building or maintaining automated provisioning pipelines, Stitchflow's MCP server with ~100 deep IT/identity integrations provides a normalized layer over SCIM endpoints like these, reducing the need to handle IdP-specific connector quirks or undocumented rate limit behavior directly.
API quick reference
| Has user API | Yes |
| Auth method | Bearer token (SCIM API token generated in ChatGPT Enterprise admin console) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise |
Authentication
Auth method: Bearer token (SCIM API token generated in ChatGPT Enterprise admin console)
Setup steps
- Log in to ChatGPT Enterprise admin console.
- Navigate to Settings > Security > SCIM Provisioning.
- Enable SCIM and copy the generated SCIM base URL and Bearer token.
- Configure your IdP (Okta, Entra ID, Google Workspace, OneLogin) with the base URL and token.
- SSO (SAML) must be configured and active before SCIM can be enabled.
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique SCIM resource identifier assigned by OpenAI. | server-assigned | immutable | Returned by server; do not supply on create. |
| userName | string | User's email address used as the unique login identifier. | required | supported | Must match the email domain verified for the Enterprise org. |
| name.givenName | string | User's first name. | optional | supported | |
| name.familyName | string | User's last name. | optional | supported | |
| emails | array | List of email objects; primary email should match userName. | required | supported | Set primary: true on the main email entry. |
| active | boolean | Whether the user account is active. Setting false deprovisions access. | optional (defaults true) | supported | Used for soft deprovisioning without deleting the user record. |
| externalId | string | Identifier from the IdP used to correlate the user across systems. | optional | supported | Recommended to set for reliable IdP-to-OpenAI user matching. |
| displayName | string | Human-readable display name. | optional | supported | |
| groups | array | Groups the user belongs to (read-only on user object; managed via Group endpoints). | read-only | read-only | Manage group membership via /Groups endpoints. |
| meta.resourceType | string | Always 'User' for user resources. | server-assigned | immutable | |
| meta.created | datetime | Timestamp when the user was provisioned. | server-assigned | immutable | |
| meta.lastModified | datetime | Timestamp of last modification. | server-assigned | server-assigned |
Core endpoints
List Users
- Method: GET
- URL:
https://api.openai.com/scim/v2/Users - Watch out for: Filter support may be limited; verify supported filter attributes with your IdP connector.
Request example
GET /scim/v2/Users?filter=userName eq "user@example.com"
Authorization: Bearer {scim_token}
Response example
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 1,
"Resources": [{"id":"abc123","userName":"user@example.com","active":true}]
}
Get User
- Method: GET
- URL:
https://api.openai.com/scim/v2/Users/{id} - Watch out for: Use the OpenAI-assigned id, not externalId, in the URL path.
Request example
GET /scim/v2/Users/abc123
Authorization: Bearer {scim_token}
Response example
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "abc123",
"userName": "user@example.com",
"active": true
}
Create User
- Method: POST
- URL:
https://api.openai.com/scim/v2/Users - Watch out for: User's email domain must belong to a verified domain in the Enterprise org. Provisioning a user does not automatically assign a ChatGPT seat if seat limits are reached.
Request example
POST /scim/v2/Users
Authorization: Bearer {scim_token}
{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"newuser@example.com",
"name":{"givenName":"Jane","familyName":"Doe"},
"emails":[{"value":"newuser@example.com","primary":true}],
"active":true
}
Response example
{
"id": "xyz789",
"userName": "newuser@example.com",
"active": true,
"meta": {"resourceType":"User","created":"2025-01-01T00:00:00Z"}
}
Update User (full replace)
- Method: PUT
- URL:
https://api.openai.com/scim/v2/Users/{id} - Watch out for: PUT replaces the full user record; omitting optional fields may clear them.
Request example
PUT /scim/v2/Users/xyz789
Authorization: Bearer {scim_token}
{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"newuser@example.com",
"active":true,
"name":{"givenName":"Jane","familyName":"Smith"}
}
Response example
{
"id": "xyz789",
"userName": "newuser@example.com",
"name": {"givenName":"Jane","familyName":"Smith"},
"active": true
}
Update User (partial)
- Method: PATCH
- URL:
https://api.openai.com/scim/v2/Users/{id} - Watch out for: Setting active=false deactivates the user but does not delete the account or free the seat immediately.
Request example
PATCH /scim/v2/Users/xyz789
Authorization: Bearer {scim_token}
{
"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":[{"op":"replace","path":"active","value":false}]
}
Response example
{
"id": "xyz789",
"active": false
}
Delete User
- Method: DELETE
- URL:
https://api.openai.com/scim/v2/Users/{id} - Watch out for: Prefer PATCH active=false for soft deprovisioning. Hard delete behavior (seat release timing) is not fully documented publicly.
Request example
DELETE /scim/v2/Users/xyz789
Authorization: Bearer {scim_token}
Response example
HTTP 204 No Content
List Groups
- Method: GET
- URL:
https://api.openai.com/scim/v2/Groups - Watch out for: Group support scope (create/update/delete) should be verified against your IdP's SCIM connector for ChatGPT.
Request example
GET /scim/v2/Groups
Authorization: Bearer {scim_token}
Response example
{
"schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 2,
"Resources":[{"id":"grp1","displayName":"Engineering"}]
}
Patch Group (add/remove members)
- Method: PATCH
- URL:
https://api.openai.com/scim/v2/Groups/{id} - Watch out for: Group membership changes propagate to ChatGPT workspace access; timing of access changes is not documented.
Request example
PATCH /scim/v2/Groups/grp1
Authorization: Bearer {scim_token}
{
"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":[{"op":"add","path":"members","value":[{"value":"xyz789"}]}]
}
Response example
HTTP 204 No Content
Rate limits, pagination, and events
Rate limits: OpenAI does not publicly document specific rate limits for the ChatGPT Enterprise SCIM API. Standard SCIM provisioning rate limits apply as enforced by the platform; exact numbers are not published.
Rate-limit headers: Unknown
Retry-After header: Unknown
Rate-limit notes: No publicly documented rate limit figures for the SCIM endpoint. Contact OpenAI Enterprise support for specifics.
Pagination method: offset
Default page size: Not documented
Max page size: Not documented
Pagination pointer: startIndex
Webhooks available: No
Webhook notes: ChatGPT Enterprise does not expose outbound webhooks for user lifecycle events. Provisioning is driven inbound via SCIM from the IdP.
Alternative event strategy: Use IdP-side event logging (Okta System Log, Entra ID audit logs) to track provisioning events.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise
Endpoint: https://api.openai.com/scim/v2
Supported operations: GET /Users, GET /Users/{id}, POST /Users, PUT /Users/{id}, PATCH /Users/{id}, DELETE /Users/{id}, GET /Groups, PATCH /Groups/{id}
Limitations:
- SCIM is not available on Free, Plus, or Business (formerly Team) plans; Enterprise plan required.
- SSO (SAML) must be configured and active before SCIM can be enabled.
- The SCIM token is a static bearer token generated in the admin console; OAuth-based token exchange is not documented.
- Specific rate limits are not publicly documented.
- Seat limit enforcement behavior during provisioning is not fully documented.
- Group provisioning scope (create/delete groups via SCIM) is not fully detailed in public docs; verify with IdP connector.
- No public changelog or versioning policy for the SCIM API is documented.
Common scenarios
Three primary automation scenarios are supported by the SCIM API:
- Provision via Okta: Enable SCIM in the Enterprise admin console, copy the base URL and bearer token, configure the Okta SCIM 2.0 app, and assign users or groups. Okta sends POST /scim/v2/Users. Caveat: if the org has hit its seat limit, the user is created in SCIM but may not receive active ChatGPT access.
- Deprovision a departing employee: Unassign the user in the IdP; the IdP sends PATCH /scim/v2/Users/{id} with active=false. Prefer PATCH over DELETE - hard delete behavior and seat release timing are not publicly documented by OpenAI.
- Group-based access sync: Push an IdP group via POST /scim/v2/Groups, then manage membership with PATCH /scim/v2/Groups/{id}. Groups control provisioning access; they do not enforce fine-grained feature permissions within the workspace.
Provision a new employee via Okta
- In ChatGPT Enterprise admin console, enable SCIM under Settings > Security and copy the SCIM base URL and bearer token.
- In Okta, add the ChatGPT Enterprise SCIM app from the Okta Integration Network or configure a custom SCIM 2.0 app with the base URL and token.
- Assign the Okta app to the user or group. Okta sends POST /scim/v2/Users with userName, name, and emails.
- Verify the user appears in the ChatGPT Enterprise admin console with active status.
Watch out for: If the Enterprise org has reached its seat limit, the user may be provisioned in SCIM but not granted active ChatGPT access until a seat is available.
Deprovision a departing employee
- In Okta (or your IdP), unassign the user from the ChatGPT Enterprise app or deactivate the user.
- Okta sends PATCH /scim/v2/Users/{id} with active=false (or DELETE depending on IdP config).
- Confirm in the ChatGPT Enterprise admin console that the user is marked inactive and can no longer log in.
Watch out for: Prefer active=false (PATCH) over DELETE for auditability. Hard delete behavior and seat release timing are not publicly documented by OpenAI.
Sync a group to manage workspace access
- Create or identify a group in your IdP (e.g., Okta group 'ChatGPT-Users').
- Push the group to ChatGPT Enterprise via the IdP's SCIM group push feature; this sends POST /scim/v2/Groups.
- Add members to the IdP group; the IdP sends PATCH /scim/v2/Groups/{id} with member additions.
- Members receive ChatGPT Enterprise access based on group membership.
Watch out for: Group-based access control granularity within ChatGPT Enterprise (e.g., restricting features by group) is limited; groups primarily control provisioning, not fine-grained permissions.
Why building this yourself is a trap
Several non-obvious constraints create integration risk. SSO (SAML) is a hard prerequisite for SCIM - the API cannot be enabled without active SSO, and this dependency is not always surfaced early in planning. The bearer token is static; rotation requires generating a new token in the admin console and reconfiguring every connected IdP.
Rate limits for the SCIM endpoint are not publicly documented. Seat limit enforcement during provisioning is also undocumented - a user can be created via SCIM without receiving workspace access if capacity is exhausted, with no clear error signaling.
Group provisioning scope is not fully detailed in public documentation and should be verified against the specific IdP connector in use.
SCIM is strictly an Enterprise feature. The Business plan (renamed from Team in August 2025) includes SSO but explicitly excludes SCIM - there is no workaround or partial enablement at that tier.
Automate ChatGPT (OpenAI) 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.