Stitchflow
Salesforce logo

Salesforce User Management API Guide

API workflow

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

UpdatedFeb 27, 2026

Summary and recommendation

Salesforce exposes user management through its REST API (sobjects/User), SOQL query interface, SCIM 2.0 (Enterprise+), and Change Data Capture for real-time events. Auth is OAuth 2.0; JWT Bearer Flow with an X.509 certificate is the recommended approach for server-to-server integrations.

The User object has 10 required fields on create - missing any one returns a generic `REQUIRED_FIELD_MISSING` error. User listing requires SOQL queries, not a standard REST collection endpoint. Rate limits are org-wide and shared across all API consumers, which means a poorly behaved integration can starve others.

Users cannot be deleted via API; deactivation is a PATCH to `IsActive: false`, subject to the same dependency blockers that apply in the UI.

API quick reference

Has user APIYes
Auth methodOAuth 2.0
Base URLOfficial docs
SCIM availableYes
SCIM plan requiredEnterprise or Unlimited (API access required; SSO must be configured as a prerequisite)

Authentication

Auth method: OAuth 2.0

Setup steps

  1. In Salesforce Setup, navigate to App Manager (or External Client Apps Manager in newer orgs) and create a Connected App.
  2. Under API (Enable OAuth Settings), check 'Enable OAuth Settings' and set a Callback URL.
  3. Select required OAuth scopes (e.g., 'api', 'refresh_token').
  4. Save and retrieve the Consumer Key (client_id) and Consumer Secret (client_secret).
  5. Obtain an access token by POSTing to https://{instance}.my.salesforce.com/services/oauth2/token with grant_type, client_id, client_secret, and (for auth-code flow) the authorization code.
  6. Include the returned access_token as a Bearer token in the Authorization header of all API requests.

Required scopes

Scope Description Required for
api Allows access to the current user's account via REST, SOAP, and other APIs. All REST API calls including User CRUD operations
refresh_token Allows the app to obtain a new access token using a refresh token without re-prompting the user. Long-lived integrations and server-to-server flows
full Full access to all data accessible by the logged-in user; equivalent to combining api + web + chatter_api. Broad integrations requiring unrestricted data access (use least-privilege instead when possible)

User object / data model

Field Type Description On create On update Notes
Id ID Unique 18-character Salesforce record ID for the user. auto-generated read-only System field; cannot be set by the caller.
Username string (80) The user's login name. Must be in email format and globally unique across all Salesforce orgs. required optional Must be unique org-wide and across all Salesforce instances, not just within your org.
LastName string (80) User's last name. required optional
FirstName string (40) User's first name. optional optional
Email string (128) User's email address. required optional Used for system notifications and password resets.
Alias string (8) Short name to identify the user on list pages, reports, and other pages where the entire name doesn't fit. required optional Max 8 characters.
ProfileId reference (Profile) ID of the user's profile, which controls permissions and access. required optional Every user must have exactly one profile.
TimeZoneSidKey picklist User's time zone (e.g., 'America/New_York'). required optional Must be a valid IANA time zone key.
LocaleSidKey picklist User's locale for number and date formatting (e.g., 'en_US'). required optional
EmailEncodingKey picklist Email encoding for outbound emails (e.g., 'UTF-8'). required optional
LanguageLocaleKey picklist User's language for the Salesforce UI (e.g., 'en_US'). required optional
IsActive boolean Indicates whether the user can log in. Set to false to deactivate. optional (defaults to true) optional Salesforce does not support hard-deleting users; deactivation via IsActive=false is the standard offboarding method.
UserRoleId reference (UserRole) ID of the user's role in the role hierarchy. optional optional Required for orgs using role-based record sharing.
Title string (80) User's job title. optional optional
Department string (80) User's department. optional optional
Phone phone User's primary phone number. optional optional
MobilePhone phone User's mobile phone number. optional optional
FederationIdentifier string (512) The SAML Federation ID used for SSO. Maps the Salesforce user to an external identity provider identity. optional optional Required when using SAML SSO with a federated identity. Must be unique within the org.
UserType picklist Type of user license (e.g., 'Standard', 'PowerPartner', 'CsnOnly'). auto-set by ProfileId read-only Determined by the assigned profile's license type.
CreatedDate datetime Timestamp when the user record was created. auto-generated read-only System field.

Core endpoints

Create user

  • Method: POST
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/sobjects/User
  • Watch out for: Username must be globally unique across all Salesforce orgs (not just yours) and must be in email format. Creating a user consumes a license seat immediately.

Request example

POST /services/data/v60.0/sobjects/User
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "Username": "jdoe@example.com",
  "LastName": "Doe",
  "FirstName": "Jane",
  "Email": "jdoe@example.com",
  "Alias": "jdoe",
  "ProfileId": "00e000000000001",
  "TimeZoneSidKey": "America/New_York",
  "LocaleSidKey": "en_US",
  "EmailEncodingKey": "UTF-8",
  "LanguageLocaleKey": "en_US"
}

Response example

HTTP 201 Created
{
  "id": "005xx000001Sv6AAAS",
  "success": true,
  "errors": []
}

Get single user by ID

  • Method: GET
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/sobjects/User/{userId}
  • Watch out for: By default returns all fields. Use ?fields=Id,Username,Email to limit payload size.

Request example

GET /services/data/v60.0/sobjects/User/005xx000001Sv6AAAS
Authorization: Bearer {access_token}

Response example

HTTP 200 OK
{
  "Id": "005xx000001Sv6AAAS",
  "Username": "jdoe@example.com",
  "FirstName": "Jane",
  "LastName": "Doe",
  "IsActive": true,
  "ProfileId": "00e000000000001"
}

List / search users (SOQL query)

  • Method: GET
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/query?q=SELECT+Id,Username,Email,IsActive+FROM+User+WHERE+IsActive=true+LIMIT+200
  • Watch out for: SOQL OFFSET is capped at 2000. For datasets >2000 records, use nextRecordsUrl cursor-based pagination returned in the response when done=false.

Request example

GET /services/data/v60.0/query?q=SELECT+Id,Username,Email,IsActive+FROM+User+LIMIT+200
Authorization: Bearer {access_token}

Response example

HTTP 200 OK
{
  "totalSize": 42,
  "done": true,
  "records": [
    {"Id": "005xx...", "Username": "jdoe@example.com", "IsActive": true}
  ]
}

Update user

  • Method: PATCH
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/sobjects/User/{userId}
  • Watch out for: PATCH returns 204 with no body on success. Only include fields you want to change; omitted fields are left unchanged.

Request example

PATCH /services/data/v60.0/sobjects/User/005xx000001Sv6AAAS
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "Title": "Senior Engineer",
  "Department": "Engineering"
}

Response example

HTTP 204 No Content

Deactivate user

  • Method: PATCH
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/sobjects/User/{userId}
  • Watch out for: Salesforce does not support deleting users via the API. Deactivation (IsActive=false) is the only supported offboarding method. The user's license is freed upon deactivation.

Request example

PATCH /services/data/v60.0/sobjects/User/005xx000001Sv6AAAS
Authorization: Bearer {access_token}
Content-Type: application/json

{"IsActive": false}

Response example

HTTP 204 No Content

Upsert user by external ID

  • Method: PATCH
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/sobjects/User/{externalIdField}/{externalIdValue}
  • Watch out for: The external ID field (e.g., FederationIdentifier) must be marked as an External ID in the org's field settings. Returns 201 on insert, 204 on update.

Request example

PATCH /services/data/v60.0/sobjects/User/FederationIdentifier/ext-user-123
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "LastName": "Doe",
  "Email": "jdoe@example.com"
}

Response example

HTTP 201 Created (insert) or 204 No Content (update)

Get current API limits

  • Method: GET
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/limits
  • Watch out for: Limit values are accurate within approximately 5 minutes of resource consumption. Avoid rapid polling of this endpoint.

Request example

GET /services/data/v60.0/limits
Authorization: Bearer {access_token}

Response example

HTTP 200 OK
{
  "DailyApiRequests": {
    "Max": 115000,
    "Remaining": 114823
  }
}

Query users via SOQL (paginated follow-up)

  • Method: GET
  • URL: https://{instance}.my.salesforce.com/services/data/v60.0/query/{queryLocatorId}
  • Watch out for: Use the nextRecordsUrl from the previous response to fetch the next batch of up to 2000 records. Continue until done=true.

Request example

GET /services/data/v60.0/query/01gxx000000001SAAQ-2000
Authorization: Bearer {access_token}

Response example

HTTP 200 OK
{
  "totalSize": 5000,
  "done": false,
  "nextRecordsUrl": "/services/data/v60.0/query/01gxx000000001SAAQ-4000",
  "records": [...]
}

Rate limits, pagination, and events

  • Rate limits: Salesforce enforces a rolling 24-hour total API request limit shared across REST, SOAP, Bulk, and Connect APIs. Enterprise Edition orgs start at 100,000 requests per 24-hour period, plus 1,000 additional requests per user license. Concurrent long-running requests (>20 seconds) are capped at 25 for production orgs. Each API call has a 10-minute timeout. The daily limit is a soft cap with a hard ceiling enforced to protect platform health.
  • Rate-limit headers: No
  • Retry-After header: No
  • Rate-limit notes: No standard rate-limit response headers are returned on REST API calls. Remaining API usage can be queried via GET /services/data/v60.0/limits. When the concurrent long-running request cap is exceeded, Salesforce returns a REQUEST_LIMIT_EXCEEDED error. The daily limit operates on a rolling 24-hour window, not a calendar day. Additional API calls can be purchased in increments of 200–10,000 per 24-hour period.
  • Pagination method: cursor
  • Default page size: 2000
  • Max page size: 2000
  • Pagination pointer: nextRecordsUrl
Plan Limit Concurrent
Starter Suite No API access 0
Pro Suite No API access 0
Enterprise 100,000 requests/24h base + 1,000 per user license 25
Unlimited 5,000 API calls per license per 24h (higher effective total) 25
Developer Edition 15,000 requests/24h 5
  • Webhooks available: No
  • Webhook notes: Salesforce REST API does not offer traditional outbound webhooks for user lifecycle events (create, update, deactivate). Salesforce uses an event-driven model instead.
  • Alternative event strategy: Use Salesforce Streaming API (PushTopic or Change Data Capture) to subscribe to real-time User object change events via CometD long-polling. Platform Events can also be used for custom event-driven workflows. Outbound Messages (via Workflow Rules or Flow) can POST XML payloads to an external HTTPS endpoint on user record changes.

SCIM API status

  • SCIM available: Yes

  • SCIM version: 2.0

  • Plan required: Enterprise or Unlimited (API access required; SSO must be configured as a prerequisite)

  • Endpoint: https://{instance}.my.salesforce.com/services/scim/v2

  • Supported operations: GET /Users - list users, GET /Users/{id} - get single user, POST /Users - create user, PATCH /Users/{id} - update user attributes, PUT /Users/{id} - replace user, GET /Groups - list groups (Permission Sets/Profiles exposed as groups), GET /ServiceProviderConfig - retrieve SCIM capabilities, GET /Schemas - retrieve supported SCIM schemas

Limitations:

  • SSO must be configured before SCIM provisioning can be enabled.
  • SCIM is only available on Enterprise and Unlimited editions; Starter and Pro Suite plans do not support it.
  • Salesforce does not support hard-deleting users via SCIM; deprovisioning sets IsActive=false.
  • Profiles are surfaced as SCIM Groups/roles; permission sets are not directly manageable via standard SCIM group operations.
  • The SCIM endpoint uses OAuth 2.0 bearer tokens (not a static bearer token); the Connected App must have SCIM write permissions enabled.
  • Salesforce's SCIM PATCH format must match its specific attribute structure; generic SCIM 2.0 payloads from some IdPs (e.g., Entra custom enterprise apps) may cause timeouts if attribute mappings are misaligned.
  • Trial orgs cannot use automated SCIM provisioning.

Common scenarios

Offboard a user: Query by email to get the user ID, transfer owned records per object type before deactivating (Mass Transfer Records only covers standard objects - custom objects need individual API calls), then PATCH IsActive: false. Deactivation blockers (Default Lead Owner, approval process assignee, etc.) return API errors; you must resolve each one before the deactivation call succeeds.

Audit inactive users: Query SELECT Id, Username, Email, LastLoginDate, IsActive FROM User WHERE IsActive = true and filter for LastLoginDate older than 90 days or null. Note: LastLoginDate is null for recently provisioned users who have never logged in - separate these from genuinely inactive accounts before acting.

Sync users from an IdP: Match on FederationIdentifier (preferred) or Email. If FederationIdentifier is not set during initial provisioning, email matching is unreliable due to format differences between Salesforce and IdP records. Create missing users with all 10 required fields, PATCH changed attributes, and PATCH IsActive: false for removed users.

Provision a new employee from an IdP (Okta/Entra) via SCIM

  1. Ensure the Salesforce org is on Enterprise or Unlimited edition with SSO configured.
  2. In Salesforce Setup, create a Connected App (or External Client App) with OAuth enabled and SCIM write permissions.
  3. In the IdP (Okta/Entra), configure the Salesforce SCIM app with the tenant URL (https://{instance}.my.salesforce.com/services/scim/v2) and an OAuth bearer token.
  4. Assign the new employee to the Salesforce app in the IdP.
  5. The IdP sends a POST /services/scim/v2/Users request with the user's attributes (userName, name, email, profileId via entitlement mapping).
  6. Salesforce creates the User record and returns the new user's Salesforce ID.
  7. Verify the user appears in Salesforce with the correct profile and IsActive=true.

Watch out for: SSO must be configured before SCIM is enabled. Profile assignment via SCIM requires mapping IdP roles/groups to Salesforce Profile IDs, which must be pre-configured in the IdP attribute mapping. Entra's pre-integrated Salesforce gallery app uses legacy username/password auth; use a custom enterprise app with OAuth 2.0 Client Credentials for new setups.

Deactivate a departing employee via REST API

  1. Query the user's Salesforce ID: GET /services/data/v60.0/query?q=SELECT+Id+FROM+User+WHERE+Username='jdoe@example.com'
  2. Extract the Id from the response.
  3. Send PATCH /services/data/v60.0/sobjects/User/{Id} with body {"IsActive": false}.
  4. Confirm the response is HTTP 204 No Content.
  5. Optionally, reassign the user's open records (Opportunities, Cases) to another user before or after deactivation.

Watch out for: Deactivation does not revoke active OAuth tokens immediately. If the user has active sessions, those may persist until token expiry. Salesforce does not support hard-deleting users; the record remains in the org permanently.

Bulk-list all active users with pagination

  1. Send GET /services/data/v60.0/query?q=SELECT+Id,Username,Email,IsActive,ProfileId+FROM+User+WHERE+IsActive=true+ORDER+BY+Id
  2. Parse the response: if done=true, all records are returned. If done=false, a nextRecordsUrl is present.
  3. Follow the nextRecordsUrl (GET {nextRecordsUrl}) to retrieve the next batch of up to 2000 records.
  4. Repeat until done=true.
  5. Aggregate all records across pages for a complete active user list.

Watch out for: Do not use SOQL OFFSET for pagination beyond 2000 records - it will return a NUMBER_OUTSIDE_VALID_RANGE error. Always use the nextRecordsUrl cursor. For very large orgs (tens of thousands of users), consider Bulk API 2.0 query jobs to avoid consuming daily REST API quota.

Why building this yourself is a trap

Salesforce's API surface looks straightforward until you hit the edge cases that dominate real usage. User listing requires SOQL, not a REST collection - you need to learn and maintain query strings. The 10-field create requirement produces opaque errors.

ProfileId is a required 18-character record ID, not a human-readable name, so every provisioning flow needs a profile lookup step first.

Rate limits are org-wide and shared: on Enterprise, the formula is 100,000 + (1,000 × license count) calls per 24 hours across every integration in the org - one runaway sync job affects everything else.

Deactivation blockers apply via API exactly as they do in the UI, meaning your offboarding automation needs to handle an open-ended list of dependency errors gracefully. OAuth tokens expire and JWT Bearer setup requires X.509 certificate management. SCIM (Enterprise+) reduces provisioning complexity but does not cover record ownership transfer or automation reassignment on offboarding.

Stitchflow maintains ~100 deep integrations at this level of specificity so your team does not have to.

Automate Salesforce 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

UpdatedFeb 27, 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