Summary and recommendation
The Zoho CRM REST API v7 exposes full user lifecycle operations - create, read, update, deactivate, and delete - under the base URL https://www.zohoapis.com/crm/v7.
Authentication is OAuth 2.0;
access tokens expire after 1 hour and must be refreshed via the refresh token grant.
A critical region-matching requirement applies: the base URL must correspond to the user's org data center (.com for US, .eu for EU, .in for India, .com.au for AU, .jp for Japan)
using the wrong region returns authentication errors, not a helpful 404.
For teams building an identity graph across SaaS applications, the user object's role, profile, status, and reporting_to fields are the key attributes to capture and normalize;
they map directly to access scope and org hierarchy within Zoho CRM.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise (or Zoho One); requires Zoho Directory and SAML SSO to be configured |
Authentication
Auth method: OAuth 2.0
Setup steps
- Register a server-based or self-client application at https://api-console.zoho.com/.
- Select the appropriate client type (Server-based Application for backend integrations).
- Add required OAuth scopes (e.g., ZohoCRM.users.ALL) during app registration.
- Generate an authorization URL and redirect the user to obtain an authorization code.
- Exchange the authorization code for an access token and refresh token via POST to https://accounts.zoho.com/oauth/v2/token.
- Use the access token in the Authorization header as 'Zoho-oauthtoken {access_token}' on all API requests.
- Use the refresh token to obtain new access tokens before expiry (access tokens expire in 1 hour).
Required scopes
| Scope | Description | Required for |
|---|---|---|
| ZohoCRM.users.ALL | Full read and write access to CRM users. | Create, read, update, delete users |
| ZohoCRM.users.READ | Read-only access to CRM users. | List and get user details |
| ZohoCRM.users.CREATE | Permission to create new CRM users. | Add users |
| ZohoCRM.users.UPDATE | Permission to update existing CRM users. | Update user profile, role, or status |
| ZohoCRM.users.DELETE | Permission to delete CRM users. | Delete/deactivate users |
| ZohoCRM.org.ALL | Access to organization-level settings. | Retrieve org info associated with users |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique system-generated user ID. | auto-generated | read-only | Used as path parameter for update/delete operations. |
| first_name | string | User's first name. | optional | optional | |
| last_name | string | User's last name. | required | optional | |
| string | User's email address; used as login identifier. | required | optional | Must be unique within the organization. | |
| role | object | Role assigned to the user (id and name). | required | optional | Role ID must reference an existing CRM role. |
| profile | object | Permission profile assigned to the user (id and name). | required | optional | Profile ID must reference an existing CRM profile. |
| status | string | User account status: 'active', 'inactive'. | auto-set to active | optional | Set to 'inactive' to deactivate without deleting. |
| mobile | string | User's mobile phone number. | optional | optional | |
| phone | string | User's office phone number. | optional | optional | |
| time_zone | string | User's time zone (e.g., 'America/New_York'). | optional | optional | |
| locale | string | User's locale setting (e.g., 'en_US'). | optional | optional | |
| language | string | User's preferred language. | optional | optional | |
| date_format | string | Preferred date format for the user. | optional | optional | |
| country_locale | string | Country locale for the user. | optional | optional | |
| reporting_to | object | The user's manager (id and name). | optional | optional | |
| territories | array | List of territories assigned to the user. | optional | optional | Territory management is an Enterprise-tier feature. |
| created_time | datetime | Timestamp when the user was created. | auto-generated | read-only | |
| modified_time | datetime | Timestamp of last modification. | auto-generated | auto-updated | |
| full_name | string | Computed full name of the user. | auto-generated | read-only | Derived from first_name + last_name. |
| confirm | boolean | Whether the user has confirmed their account. | auto-set | read-only |
Core endpoints
List Users
- Method: GET
- URL:
https://www.zohoapis.com/crm/v7/users?type=AllUsers&page=1&per_page=200 - Watch out for: The 'type' parameter filters users: AllUsers, ActiveUsers, DeactiveUsers, ConfirmedUsers, NotConfirmedUsers, DeletedUsers, ActiveConfirmedUsers, AdminUsers, ActiveConfirmedAdmins, CurrentUser. Omitting it defaults to AllUsers.
Request example
GET /crm/v7/users?type=AllUsers&page=1&per_page=200
Authorization: Zoho-oauthtoken {access_token}
Response example
{
"users": [
{"id":"111","email":"user@example.com","status":"active","role":{"id":"r1","name":"Manager"}}
],
"info": {"page":1,"per_page":200,"count":1,"more_records":false}
}
Get Single User
- Method: GET
- URL:
https://www.zohoapis.com/crm/v7/users/{user_id} - Watch out for: Response wraps single user in a 'users' array, not a single object.
Request example
GET /crm/v7/users/111
Authorization: Zoho-oauthtoken {access_token}
Response example
{
"users": [
{"id":"111","email":"user@example.com","first_name":"Jane","last_name":"Doe","status":"active"}
]
}
Get Current User
- Method: GET
- URL:
https://www.zohoapis.com/crm/v7/users?type=CurrentUser - Watch out for: Returns the user associated with the OAuth token in use.
Request example
GET /crm/v7/users?type=CurrentUser
Authorization: Zoho-oauthtoken {access_token}
Response example
{
"users": [
{"id":"222","email":"me@example.com","full_name":"John Smith"}
]
}
Create User
- Method: POST
- URL:
https://www.zohoapis.com/crm/v7/users - Watch out for: An invitation email is sent to the new user automatically. The user must accept the invite to activate. 'role' and 'profile' IDs are mandatory.
Request example
POST /crm/v7/users
Authorization: Zoho-oauthtoken {access_token}
Content-Type: application/json
{"users":[{"last_name":"Doe","email":"jane@example.com","role":{"id":"r1"},"profile":{"id":"p1"}}]}
Response example
{
"users": [
{"code":"SUCCESS","details":{"id":"333"},"message":"User added","status":"success"}
]
}
Update User
- Method: PUT
- URL:
https://www.zohoapis.com/crm/v7/users/{user_id} - Watch out for: Use PUT (not PATCH) for updates. The user ID must be included both in the URL path and in the request body.
Request example
PUT /crm/v7/users/333
Authorization: Zoho-oauthtoken {access_token}
Content-Type: application/json
{"users":[{"id":"333","mobile":"+1-555-0100","role":{"id":"r2"}}]}
Response example
{
"users": [
{"code":"SUCCESS","details":{"id":"333"},"message":"User updated","status":"success"}
]
}
Delete User
- Method: DELETE
- URL:
https://www.zohoapis.com/crm/v7/users/{user_id} - Watch out for: Deleting a user removes them from the CRM org. Records owned by the deleted user must be reassigned beforehand or they will be reassigned to the admin. Consider deactivating (status=inactive) instead of deleting to preserve data ownership.
Request example
DELETE /crm/v7/users/333
Authorization: Zoho-oauthtoken {access_token}
Response example
{
"users": [
{"code":"SUCCESS","details":{"id":"333"},"message":"User deleted","status":"success"}
]
}
Get Roles
- Method: GET
- URL:
https://www.zohoapis.com/crm/v7/settings/roles - Watch out for: Role IDs are required when creating or updating users. Retrieve them here before provisioning.
Request example
GET /crm/v7/settings/roles
Authorization: Zoho-oauthtoken {access_token}
Response example
{
"roles": [
{"id":"r1","name":"Manager","description":"Sales Manager role"}
]
}
Get Profiles
- Method: GET
- URL:
https://www.zohoapis.com/crm/v7/settings/profiles - Watch out for: Profile IDs are required when creating or updating users. Retrieve them here before provisioning.
Request example
GET /crm/v7/settings/profiles
Authorization: Zoho-oauthtoken {access_token}
Response example
{
"profiles": [
{"id":"p1","name":"Administrator","description":"Full access profile"}
]
}
Rate limits, pagination, and events
- Rate limits: Zoho CRM API rate limits are based on the organization's plan and the number of licensed users. Limits apply per organization per day (API credits) and per 5-minute window.
- Rate-limit headers: Unknown
- Retry-After header: Unknown
- Rate-limit notes: Each API call consumes a variable number of credits depending on the operation. Bulk operations consume more credits. The exact per-minute concurrency limits are not explicitly published in official docs. Exceeding limits returns HTTP 429.
- Pagination method: offset
- Default page size: 200
- Max page size: 200
- Pagination pointer: page, per_page
| Plan | Limit | Concurrent |
|---|---|---|
| Standard | Up to 1,000 API credits/day per org (varies by user count) | 0 |
| Professional | Up to 2,000 API credits/day per org (varies by user count) | 0 |
| Enterprise | Up to 5,000 API credits/day per org (varies by user count) | 0 |
| Ultimate | Up to 10,000 API credits/day per org (varies by user count) | 0 |
- Webhooks available: Yes
- Webhook notes: Zoho CRM supports webhooks (called 'Notifications' in the API) that can be triggered by record-level events. However, native webhook events for user lifecycle changes (user created, user deactivated) are not documented as supported triggers. Webhooks are primarily for CRM record events (Leads, Contacts, Deals, etc.).
- Alternative event strategy: Poll GET /crm/v7/users periodically to detect user changes, or use Zoho Directory SCIM provisioning events via your IdP (Okta, Azure AD) for user lifecycle automation.
- Webhook events: record.create (for CRM modules like Leads, Contacts, Deals), record.update, record.delete
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise (or Zoho One); requires Zoho Directory and SAML SSO to be configured
Endpoint: SCIM endpoint is provisioned per IdP integration via Zoho Directory (e.g., https://directory.zoho.com/scim/v2/). The exact tenant-specific URL is generated within the Zoho Directory admin console when configuring an IdP connector.
Supported operations: Create user (POST /Users), Update user (PUT /Users/{id}), Deactivate user (PATCH /Users/{id} with active=false), List users (GET /Users), Get user (GET /Users/{id})
Limitations:
- SCIM provisioning is managed through Zoho Directory, not directly through the Zoho CRM API.
- Requires SAML SSO to be configured as a prerequisite.
- Available on Enterprise plan or Zoho One; not available on Standard or Professional CRM plans.
- SCIM endpoint URL is IdP-specific and generated in the Zoho Directory admin console; it is not a static public endpoint.
- Group/role provisioning support via SCIM may be limited depending on the IdP connector used.
- Okta and Azure AD (Entra ID) are documented as supported IdPs; other IdPs may have limited support.
Common scenarios
Three provisioning scenarios cover the primary lifecycle needs.
For onboarding, fetch role and profile IDs from /settings/roles and /settings/profiles first - both are mandatory on POST /users and cannot be inferred.
The API sends an invitation email automatically on user creation with no suppression option;
poll GET /users/{id} and check the confirm field to detect when the user has activated.
For offboarding, PUT /users/{user_id} with status set to inactive is the recommended path;
deletion via DELETE is irreversible and will reassign owned records to the org admin if not pre-transferred.
For directory sync, pagination is offset-based with a maximum page size of 200;
loop on info.more_records and use modified_time as a delta filter to minimize redundant data transfer across sync runs.
Provision a new CRM user on employee onboarding
- Authenticate via OAuth 2.0 and obtain an access token with ZohoCRM.users.CREATE and ZohoCRM.settings.roles.READ and ZohoCRM.settings.profiles.READ scopes.
- GET /crm/v7/settings/roles to retrieve available role IDs and identify the correct role for the new user.
- GET /crm/v7/settings/profiles to retrieve available profile IDs and identify the correct permission profile.
- POST /crm/v7/users with the user's last_name, email, role.id, and profile.id in the request body.
- Store the returned user ID from the response for future updates.
- Inform the new user to check their email and accept the CRM invitation to activate their account.
Watch out for: The user will not be active until they accept the invitation email. Poll GET /crm/v7/users/{id} and check 'confirm' field to verify activation status.
Deactivate a user on offboarding
- Authenticate via OAuth 2.0 with ZohoCRM.users.UPDATE scope.
- GET /crm/v7/users?type=ActiveUsers to find the user's ID by email if not already stored.
- PUT /crm/v7/users/{user_id} with body {"users":[{"id":"{user_id}","status":"inactive"}]} to deactivate the user.
- Verify the response returns code: SUCCESS.
- Optionally reassign the deactivated user's records to another active user via the CRM record transfer API.
Watch out for: Deactivation preserves the user record and their owned records. Deletion is permanent and may cause data ownership issues if records are not reassigned first.
Sync CRM users to an external directory
- Authenticate via OAuth 2.0 with ZohoCRM.users.READ scope.
- GET /crm/v7/users?type=AllUsers&page=1&per_page=200 to retrieve the first page of users.
- Check response info.more_records; if true, increment page parameter and repeat until more_records is false.
- For each user, extract id, email, first_name, last_name, status, role, profile, and modified_time.
- Compare modified_time against your last sync timestamp to identify changed records.
- Update your external directory with the delta changes.
Watch out for: There is no native change-event webhook for user objects. Full or delta polling is required. Store modified_time from each sync to minimize data transfer on subsequent runs.
Why building this yourself is a trap
There is no native webhook for user lifecycle events - user.created and user.deactivated are not supported notification triggers. Webhooks in Zoho CRM fire on CRM record events (Leads, Contacts, Deals), not on user object changes, so any identity graph or downstream sync that needs real-time user state must rely on polling.
Bulk user creation is not supported; every user requires an individual POST, which compounds API credit consumption on large provisioning runs. Daily credit limits are plan-tiered (up to 5,000 credits/day on Enterprise) and per-minute concurrency limits are not published, making it difficult to safely size burst provisioning jobs.
SCIM provisioning is a separate system entirely - it runs through Zoho Directory, not the CRM REST API, requires SAML SSO as a prerequisite, and is only available on Enterprise or Zoho One; the SCIM endpoint URL is tenant-specific and generated inside the Zoho Directory admin console, not a static public address.
Automate Zoho CRM 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.