Stitchflow
RingCentral logo

RingCentral User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 6, 2026

Summary and recommendation

RingCentral exposes user management through two distinct API surfaces: the REST API (base URL https://platform.ringcentral.com/restapi/v1.0) using OAuth 2.0, and the SCIM 2.0 API (base URL https://platform.ringcentral.com/scim/v2) using a static bearer token generated in the Admin Portal.

These are separate systems - changes made via SCIM may not immediately reflect in REST API responses due to eventual consistency. Integrations that build an identity graph across both surfaces must account for this lag explicitly.

User-management endpoints (extension read/write) are classified as Heavy usage plan, capped at 10 requests/min per app per user. Bulk provisioning at scale must use the async bulk-create endpoint (POST /account/{accountId}/extension/bulk-create) and handle partial failures per-record.

Access tokens expire after 1 hour; JWT grant flows do not issue refresh tokens by default, requiring re-authentication on expiry.

API quick reference

Has user APIYes
Auth methodOAuth 2.0
Base URLOfficial docs
SCIM availableYes
SCIM plan requiredEnterprise (RingEX Ultra or Enterprise tier; SSO must be configured as a prerequisite)

Authentication

Auth method: OAuth 2.0

Setup steps

  1. Register an application at https://developers.ringcentral.com/my-account.html#/applications
  2. Select the appropriate auth flow: Authorization Code (user-facing apps), JWT (server-to-server/service accounts), or Client Credentials
  3. Note the Client ID and Client Secret from the app dashboard
  4. For JWT flow: create a service account user in RingCentral Admin Portal and generate a JWT credential
  5. Exchange credentials for an access token at https://platform.ringcentral.com/restapi/oauth/token
  6. Include the access token as a Bearer token in the Authorization header of all API requests
  7. Access tokens expire in 1 hour; use the refresh token (Authorization Code flow) or re-authenticate (JWT flow) to obtain a new one

Required scopes

Scope Description Required for
ReadAccounts Read account, extension, and user information GET user, list users, read extension details
EditAccounts Create, update, and delete extensions/users POST, PUT, PATCH, DELETE user/extension operations
ReadPresence Read user presence status GET presence/status for users
EditPresence Update user presence status PUT presence for users
Contacts Read and manage company contacts Directory/contact operations

User object / data model

Field Type Description On create On update Notes
id string Unique internal extension/user ID system-generated immutable Used as path parameter in all user-specific requests
extensionNumber string User's internal extension number optional (auto-assigned if omitted) updatable Must be unique within the account
contact.firstName string User's first name required updatable Nested under contact object
contact.lastName string User's last name required updatable Nested under contact object
contact.email string User's email address (used for login) required updatable Must be unique across the account
contact.businessPhone string User's direct business phone number optional updatable E.164 format recommended
contact.mobilePhone string User's mobile phone number optional updatable
contact.department string Department the user belongs to optional updatable
contact.jobTitle string User's job title optional updatable
status enum Account status: Enabled, Disabled, NotActivated, Unassigned optional (defaults to NotActivated) updatable Setting to Disabled suspends the user without deleting
type enum Extension type: User, Department, Announcement, Voicemail, etc. required generally immutable Use 'User' for standard user accounts
name string Display name (read-only, derived from contact.firstName + contact.lastName) system-derived read-only
password string User's password (write-only on create) optional updatable via separate endpoint Not returned in GET responses
regionalSettings.timezone object User's timezone setting optional updatable Nested under regionalSettings
regionalSettings.language object User's language preference optional updatable
serviceFeatures array List of features enabled for the user (e.g., SMS, Voicemail, VideoConferencing) system-assigned based on license some features togglable Read-only for most features; controlled by license tier
profileImage object Reference to user's profile image not applicable updatable via separate image endpoint Use PUT /restapi/v1.0/account/{accountId}/extension/{extensionId}/profile-image

Core endpoints

List Users (Extensions)

  • Method: GET
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension
  • Watch out for: Use accountId '~' to reference the authenticated user's account. Filter by type=User to exclude non-user extensions (departments, voicemail boxes, etc.).

Request example

GET /restapi/v1.0/account/~/extension?type=User&status=Enabled&perPage=100&page=1
Authorization: Bearer {access_token}

Response example

{
  "uri": "https://platform.ringcentral.com/restapi/v1.0/account/~/extension?page=1&perPage=100",
  "records": [{"id": "12345", "extensionNumber": "101", "name": "Jane Doe", "status": "Enabled"}],
  "paging": {"page": 1, "perPage": 100, "totalPages": 3, "totalElements": 250}
}

Get User

  • Method: GET
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}
  • Watch out for: Use extensionId '~' to retrieve the currently authenticated user's own profile.

Request example

GET /restapi/v1.0/account/~/extension/12345
Authorization: Bearer {access_token}

Response example

{
  "id": "12345",
  "extensionNumber": "101",
  "contact": {"firstName": "Jane", "lastName": "Doe", "email": "jane@example.com"},
  "status": "Enabled",
  "type": "User"
}

Create User (Extension)

  • Method: POST
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension
  • Watch out for: Newly created users have status 'NotActivated' until they complete email verification or an admin activates them. A license must be available in the account to assign to the new user.

Request example

POST /restapi/v1.0/account/~/extension
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "type": "User",
  "contact": {"firstName": "John", "lastName": "Smith", "email": "john@example.com"},
  "extensionNumber": "102"
}

Response example

{
  "id": "67890",
  "extensionNumber": "102",
  "status": "NotActivated",
  "contact": {"firstName": "John", "lastName": "Smith", "email": "john@example.com"}
}

Update User

  • Method: PUT
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}
  • Watch out for: PUT replaces the full resource; omitting optional fields may clear them. Use only the fields you intend to set.

Request example

PUT /restapi/v1.0/account/~/extension/12345
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "contact": {"firstName": "Jane", "lastName": "Doe-Updated", "department": "Engineering"}
}

Response example

{
  "id": "12345",
  "contact": {"firstName": "Jane", "lastName": "Doe-Updated", "department": "Engineering"},
  "status": "Enabled"
}

Disable / Suspend User

  • Method: PUT
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}
  • Watch out for: Setting status to 'Disabled' suspends the user but retains their data and license. There is no dedicated PATCH endpoint; use PUT with the status field.

Request example

PUT /restapi/v1.0/account/~/extension/12345
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "status": "Disabled"
}

Response example

{
  "id": "12345",
  "status": "Disabled"
}

Delete User (Extension)

  • Method: DELETE
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}
  • Watch out for: Deleting an extension is irreversible and releases the license. Only extensions of type 'User' with status 'Disabled' or 'NotActivated' can typically be deleted via API.

Request example

DELETE /restapi/v1.0/account/~/extension/12345
Authorization: Bearer {access_token}

Response example

HTTP 204 No Content

List User Roles / Permissions

  • Method: GET
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension/{extensionId}/assigned-role
  • Watch out for: Role assignment is separate from user creation. Roles must be pre-configured in the RingCentral Admin Portal before assignment via API.

Request example

GET /restapi/v1.0/account/~/extension/12345/assigned-role
Authorization: Bearer {access_token}

Response example

{
  "uri": "...",
  "records": [{"id": "1", "displayName": "Standard User", "siteCompatible": true}]
}

Bulk Create/Update Users

  • Method: POST
  • URL: https://platform.ringcentral.com/restapi/v1.0/account/{accountId}/extension/bulk-create
  • Watch out for: Bulk operations are asynchronous; check individual record statuses in the response. Partial failures are possible - some records may succeed while others fail.

Request example

POST /restapi/v1.0/account/~/extension/bulk-create
Authorization: Bearer {access_token}
Content-Type: application/json
{
  "records": [
    {"type": "User", "contact": {"firstName": "A", "email": "a@x.com"}},
    {"type": "User", "contact": {"firstName": "B", "email": "b@x.com"}}
  ]
}

Response example

{
  "response": [
    {"id": "111", "status": "NotActivated"},
    {"id": "112", "status": "NotActivated"}
  ]
}

Rate limits, pagination, and events

  • Rate limits: RingCentral enforces per-app, per-user rate limits grouped by API usage plan (Light, Medium, Heavy, Auth). Limits are applied per minute. Exceeding limits returns HTTP 429.
  • Rate-limit headers: Yes
  • Retry-After header: Yes
  • Rate-limit notes: Each endpoint is classified into a usage plan (Light/Medium/Heavy/Auth). Headers X-Rate-Limit-Limit, X-Rate-Limit-Remaining, X-Rate-Limit-Window, and Retry-After are returned. User-management endpoints (read/write extensions) are typically Heavy plan.
  • Pagination method: offset
  • Default page size: 100
  • Max page size: 1000
  • Pagination pointer: page and perPage (page is 1-indexed; perPage sets page size)
Plan Limit Concurrent
Light 50 requests/min per app per user 0
Medium 40 requests/min per app per user 0
Heavy 10 requests/min per app per user 0
Auth 5 requests/min per app per user 0
  • Webhooks available: Yes
  • Webhook notes: RingCentral supports webhooks via its Subscription API. Subscriptions are created via POST to /restapi/v1.0/subscription and deliver events to a publicly accessible HTTPS endpoint. Subscriptions expire and must be renewed (max TTL is configurable, typically up to 20160 minutes / 14 days).
  • Alternative event strategy: RingCentral also supports WebSocket-based subscriptions (PubNub transport deprecated) for real-time event delivery without requiring a public endpoint.
  • Webhook events: /restapi/v1.0/account//extension, /restapi/v1.0/account//extension//presence, /restapi/v1.0/account//extension//message-store, /restapi/v1.0/account//extension//telephony/sessions, /restapi/v1.0/account//extension/~/voicemail

SCIM API status

  • SCIM available: Yes

  • SCIM version: 2.0

  • Plan required: Enterprise (RingEX Ultra or Enterprise tier; SSO must be configured as a prerequisite)

  • Endpoint: https://platform.ringcentral.com/scim/v2

  • Supported operations: GET /Users (list users), GET /Users/{id} (get user), POST /Users (create user), PUT /Users/{id} (replace user), PATCH /Users/{id} (update user), DELETE /Users/{id} (delete user), GET /Groups (list groups), GET /ServiceProviderConfig, GET /Schemas

Limitations:

  • SSO (SAML 2.0) must be enabled before SCIM provisioning can be activated
  • SCIM provisioning requires Enterprise-tier plan (Ultra or above for RingEX)
  • Supported IdPs with native connectors: Okta, Microsoft Entra ID (Azure AD), OneLogin
  • Group provisioning support is limited; not all IdP group-push features are fully supported
  • SCIM token is generated in the RingCentral Admin Portal under Tools > User Management > SCIM
  • SCIM token does not use OAuth 2.0; it is a static bearer token generated in the admin UI

Common scenarios

Provisioning a new employee requires a POST to /restapi/v1.0/account/~/extension with type=User and core contact fields.

The returned user will have status NotActivated - a separate PUT to /assigned-role is needed to set the role, and a license must be confirmed available via GET /account/~/service-info before bulk runs, or the create call will fail.

Deprovisioning requires a PUT with status=Disabled before a DELETE can be issued; attempting to DELETE an Enabled extension returns an error, and deletion is irreversible - voicemail and call logs are lost.

SCIM sync with Okta requires the account to be on an Enterprise/Ultra plan with SAML 2.0 SSO already active.

The SCIM bearer token is generated under Tools > User Management > SCIM in the Admin Portal - it is a static credential, not an OAuth token, and does not expire automatically but can be revoked.

Group push support via SCIM is limited; verify supported attributes in the Okta RingCentral OIN app configuration before relying on group-based provisioning.

Webhook subscriptions for real-time user-state events expire at approximately 14 days and require explicit renewal logic to avoid event gaps.

Provision a new employee

  1. POST /restapi/v1.0/account/~/extension with type=User, contact.firstName, contact.lastName, contact.email to create the extension
  2. Note the returned extension id; status will be 'NotActivated'
  3. PUT /restapi/v1.0/account/~/extension/{id}/assigned-role to assign the appropriate role (e.g., Standard User)
  4. Optionally assign a phone number via PUT /restapi/v1.0/account/~/extension/{id}/phone-number
  5. Trigger activation email or set status to 'Enabled' if SSO is configured (user won't need password)

Watch out for: A license must be available in the account before creating a new user. Check account license availability via GET /restapi/v1.0/account/~/service-info before bulk provisioning.

Deprovision a departing employee

  1. GET /restapi/v1.0/account/~/extension?email={email} to locate the user's extensionId
  2. PUT /restapi/v1.0/account/~/extension/{id} with status=Disabled to immediately suspend access
  3. Optionally reassign or forward the user's phone number to another extension
  4. DELETE /restapi/v1.0/account/~/extension/{id} to permanently remove the extension and release the license

Watch out for: DELETE will fail if the extension is still in 'Enabled' status. Always disable first. Deletion is irreversible; voicemail and call logs associated with the extension are lost.

Sync users via SCIM with Okta

  1. Ensure RingCentral account is on an Enterprise/Ultra plan with SSO (SAML 2.0) configured
  2. In RingCentral Admin Portal, navigate to Tools > User Management > SCIM and generate a SCIM bearer token
  3. In Okta, add the RingCentral application from the Okta Integration Network (OIN)
  4. Configure the SCIM base URL as https://platform.ringcentral.com/scim/v2 and paste the bearer token
  5. Enable provisioning features: Push New Users, Push Profile Updates, Deactivate Users
  6. Assign users/groups in Okta to trigger SCIM provisioning to RingCentral

Watch out for: SCIM token is a static credential - store it securely. If SSO is not configured before enabling SCIM, provisioning will fail. Group push support is limited; verify supported attributes in the Okta RingCentral app configuration.

Why building this yourself is a trap

The most common integration failure mode is treating the REST API and SCIM API as a unified identity graph when they are not.

Writes via SCIM are not guaranteed to be immediately visible via REST API reads, which breaks any provisioning pipeline that creates a user via SCIM and then immediately queries the REST API to confirm or enrich the record. Build explicit retry and consistency-check logic between the two surfaces.

The Heavy rate limit (10 req/min per app per user) on extension endpoints is the second trap: sequential per-user provisioning loops will hit this ceiling quickly. Use bulk-create for initial loads and design incremental sync to batch updates.

Finally, the SCIM static token is a single credential with no automatic rotation - treat it as a high-value secret, store it in a secrets manager, and implement revocation procedures as part of your offboarding runbook for the integration itself, not just for end users.

Automate RingCentral 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.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 6, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

15Five logo

15Five

Full API + SCIM
AutomationAPI + SCIM
Last updatedFeb 2026

15Five uses a fixed role-based permission model with six predefined roles: Account Admin, HR Admin, Billing Admin, Group Admin, Manager, and Employee. No custom roles can be constructed. User management lives at Settings gear → People → Manage people p

1Password logo

1Password

Full API + SCIM
AutomationAPI + SCIM
Last updatedFeb 2026

1Password's admin console at my.1password.com covers the full user lifecycle — invitations, group assignments, vault access, suspension, and deletion — without any third-party tooling. Like every app that mixes role-based and resource-level permissions

8x8 logo

8x8

Full API + SCIM
AutomationAPI + SCIM
Last updatedFeb 2026

8x8 Admin Console supports full lifecycle user management — create, deactivate, and delete — across its X Series unified communications platform. Every app a user can access (8x8 Work desktop, mobile, web, Agent Workspace) is gated by license assignmen