Stitchflow
Outreach logo

Outreach User Management API Guide

API workflow

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

UpdatedMar 11, 2026

Summary and recommendation

The Outreach REST API follows JSON:API (jsonapi.org) spec throughout - every request and response uses `application/vnd.api+json` content negotiation, and standard JSON clients require adaptation before use. Authentication is OAuth 2.0 Authorization Code flow; access tokens expire after approximately 2 hours, so refresh_token rotation must be implemented.

A separate long-lived SCIM bearer token exists for SCIM 2.0 operations and is generated independently in the Outreach admin UI under Security settings - it is not interchangeable with OAuth tokens.

For identity graph construction, the canonical user identifier is the integer `id` field. Email (`email`) doubles as the login identifier and is filterable via `filter[email]=`. The `active` and `locked` boolean fields together represent provisioning state; deactivation is a PATCH setting `locked: true`, as hard deletion is not available via the REST API.

Role and profile assignments are relationship objects requiring valid IDs pre-fetched from `/roles` and `/profiles` before any create or update call.

API quick reference

Has user APIYes
Auth methodOAuth 2.0 (Authorization Code flow; also supports Client Credentials for server-to-server)
Base URLOfficial docs
SCIM availableYes
SCIM plan requiredEnterprise

Authentication

Auth method: OAuth 2.0 (Authorization Code flow; also supports Client Credentials for server-to-server)

Setup steps

  1. Register an OAuth application in the Outreach developer portal (https://developers.outreach.io)
  2. Obtain client_id and client_secret from the registered app
  3. Redirect user to https://api.outreach.io/oauth/authorize with response_type=code, client_id, redirect_uri, scope, and state params
  4. Exchange the returned authorization code for an access_token and refresh_token via POST to https://api.outreach.io/oauth/token
  5. Include the access_token as a Bearer token in the Authorization header on all API requests
  6. Refresh the access_token using the refresh_token before expiry (tokens expire in 2 hours)

Required scopes

Scope Description Required for
users.read Read user records GET /users, GET /users/{id}
users.write Create and update user records POST /users, PATCH /users/{id}
users.delete Delete or deactivate user records DELETE /users/{id}
profiles.read Read user profile/role data GET /profiles
roles.read Read role definitions GET /roles

User object / data model

Field Type Description On create On update Notes
id integer Unique Outreach user identifier auto-assigned immutable Used as path param in single-resource endpoints
firstName string User's first name required optional
lastName string User's last name required optional
email string Primary email address; used as login identifier required optional Must be unique within the org
username string Outreach username (often same as email) optional optional
locked boolean Whether the user account is locked/deactivated optional optional Set to true to deactivate; Outreach does not hard-delete users via REST
active boolean Whether the user is active in the org optional optional Deprovisioning sets active=false
title string Job title optional optional
phoneNumber string Primary phone number optional optional
mobilePhoneNumber string Mobile phone number optional optional
timeZone string IANA timezone string (e.g. America/New_York) optional optional
locale string User locale (e.g. en-US) optional optional
createdAt datetime (ISO 8601) Timestamp of user creation auto-assigned immutable
updatedAt datetime (ISO 8601) Timestamp of last update auto-assigned auto-assigned
role relationship (Role) Role assigned to the user optional optional Specified as a JSON:API relationship object referencing a Role id
profile relationship (Profile) Profile (permissions set) assigned to the user optional optional Specified as a JSON:API relationship object
externalSource string Source system identifier (e.g. SCIM) optional optional Set automatically when provisioned via SCIM
externalId string External system user ID (e.g. IdP user ID) optional optional Used for SCIM correlation

Core endpoints

List Users

  • Method: GET
  • URL: https://api.outreach.io/api/v2/users
  • Watch out for: Uses JSON:API format. Must include Accept: application/vnd.api+json header or requests may fail.

Request example

GET /api/v2/users?page[size]=50&page[offset]=0
Authorization: Bearer {access_token}
Content-Type: application/vnd.api+json

Response example

{
  "data": [
    {
      "type": "user",
      "id": "123",
      "attributes": {
        "firstName": "Jane",
        "email": "jane@example.com",
        "active": true
      }
    }
  ],
  "meta": {"count": 200}
}

Get User

  • Method: GET
  • URL: https://api.outreach.io/api/v2/users/{id}
  • Watch out for: id is an integer in the path but returned as a string in JSON:API responses.

Request example

GET /api/v2/users/123
Authorization: Bearer {access_token}

Response example

{
  "data": {
    "type": "user",
    "id": "123",
    "attributes": {
      "firstName": "Jane",
      "lastName": "Doe",
      "email": "jane@example.com",
      "locked": false
    }
  }
}

Create User

  • Method: POST
  • URL: https://api.outreach.io/api/v2/users
  • Watch out for: Creating a user does not automatically send an invitation email unless configured in org settings. Requires users.write scope.

Request example

POST /api/v2/users
Authorization: Bearer {access_token}
Content-Type: application/vnd.api+json

{"data":{"type":"user","attributes":{"firstName":"Jane","lastName":"Doe","email":"jane@example.com"}}}

Response example

{
  "data": {
    "type": "user",
    "id": "456",
    "attributes": {
      "email": "jane@example.com",
      "active": true,
      "createdAt": "2024-01-15T10:00:00Z"
    }
  }
}

Update User

  • Method: PATCH
  • URL: https://api.outreach.io/api/v2/users/{id}
  • Watch out for: PATCH is partial update (JSON:API compliant). The id must be included in the request body data object, not just the URL.

Request example

PATCH /api/v2/users/123
Authorization: Bearer {access_token}
Content-Type: application/vnd.api+json

{"data":{"type":"user","id":"123","attributes":{"title":"AE"}}}

Response example

{
  "data": {
    "type": "user",
    "id": "123",
    "attributes": {
      "title": "AE",
      "updatedAt": "2024-06-01T12:00:00Z"
    }
  }
}

Deactivate User (lock)

  • Method: PATCH
  • URL: https://api.outreach.io/api/v2/users/{id}
  • Watch out for: Outreach does not support hard deletion of users via the REST API. Deactivation is done by setting locked=true.

Request example

PATCH /api/v2/users/123
Authorization: Bearer {access_token}
Content-Type: application/vnd.api+json

{"data":{"type":"user","id":"123","attributes":{"locked":true}}}

Response example

{
  "data": {
    "type": "user",
    "id": "123",
    "attributes": {"locked": true}
  }
}

List Roles

  • Method: GET
  • URL: https://api.outreach.io/api/v2/roles
  • Watch out for: Role IDs are needed when assigning roles during user create/update via relationship objects.

Request example

GET /api/v2/roles
Authorization: Bearer {access_token}

Response example

{
  "data": [
    {"type":"role","id":"1","attributes":{"name":"Admin"}},
    {"type":"role","id":"2","attributes":{"name":"User"}}
  ]
}

List Profiles

  • Method: GET
  • URL: https://api.outreach.io/api/v2/profiles
  • Watch out for: Profiles control feature-level permissions. Must be fetched separately to map names to IDs before assigning to users.

Request example

GET /api/v2/profiles
Authorization: Bearer {access_token}

Response example

{
  "data": [
    {"type":"profile","id":"10","attributes":{"name":"Sales Rep"}}
  ]
}

Filter Users by Email

  • Method: GET
  • URL: https://api.outreach.io/api/v2/users?filter[email]={email}
  • Watch out for: Filter parameters follow JSON:API filter syntax. Not all fields are filterable; email and locked are supported.

Request example

GET /api/v2/users?filter[email]=jane@example.com
Authorization: Bearer {access_token}

Response example

{
  "data": [
    {"type":"user","id":"123","attributes":{"email":"jane@example.com"}}
  ]
}

Rate limits, pagination, and events

  • Rate limits: Outreach enforces per-application rate limits on API requests. Limits are applied per OAuth application per org.
  • Rate-limit headers: Yes
  • Retry-After header: Yes
  • Rate-limit notes: Response headers include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. When limit is exceeded, API returns HTTP 429. Retry-After header is included on 429 responses.
  • Pagination method: offset
  • Default page size: 50
  • Max page size: 1000
  • Pagination pointer: page[size] and page[offset]
Plan Limit Concurrent
Standard/Professional 10,000 requests per hour 0
Enterprise 10,000 requests per hour (higher limits available by request) 0
  • Webhooks available: Yes
  • Webhook notes: Outreach supports webhooks (called 'Webhooks' in their platform) that can fire on object events. Webhook subscriptions can be created via the API or UI.
  • Alternative event strategy: Poll GET /users with filter[updatedAt][gt]= for change detection if webhooks are not available on the plan.
  • Webhook events: user.created, user.updated, user.deleted

SCIM API status

  • SCIM available: Yes

  • SCIM version: 2.0

  • Plan required: Enterprise

  • Endpoint: https://api.outreach.io/scim/v2

  • Supported operations: GET /Users, GET /Users/{id}, POST /Users, PUT /Users/{id}, PATCH /Users/{id}, DELETE /Users/{id}, GET /Groups, POST /Groups, PATCH /Groups/{id}, DELETE /Groups/{id}

Limitations:

  • Requires Enterprise plan with SSO enabled as a prerequisite
  • SCIM and SSO must be configured as separate applications in the IdP (e.g., Okta)
  • SCIM token is a long-lived bearer token generated in Outreach admin settings, not an OAuth token
  • Group push maps to Outreach Teams, not Roles or Profiles
  • Deprovisioning sets user to inactive; hard delete via SCIM DELETE may not permanently remove user data
  • Google Workspace is not listed as a supported IdP for SCIM; Okta, Entra ID, and OneLogin are supported

Common scenarios

Provisioning a new rep requires four sequential calls: authenticate for an access token with users. write, `roles.

read, and profiles. readscopes; GET/api/v2/rolesto resolve the role ID; GET/api/v2/profilesto resolve the profile ID; then POST/api/v2/users` with the relationship objects included.

User creation does not trigger a welcome email by default - org settings must be configured separately to enable that behavior.

Deprovisioning starts with a lookup: GET /api/v2/users?filter[email]=departing@example.com to retrieve the integer user ID, then PATCH /api/v2/users/{id} with attributes: { locked: true }. Hard deletion is not available via REST; locked users may continue to occupy a licensed seat until removed by Outreach support or via SCIM DELETE on Enterprise. Sequence and prospect reassignment is not handled by the API deactivation call and must be addressed separately.

For SCIM automation via Okta, SSO and SCIM must be configured as two distinct Okta applications - a single combined app is explicitly unsupported and will cause provisioning failures. The SCIM base URL is https://api.outreach.io/scim/v2; group push maps to Outreach Teams, not to Roles or Profiles. Google Workspace is not listed as a supported SCIM IdP; Okta, Entra ID, and OneLogin are confirmed.

Provision a new sales rep via REST API

  1. Authenticate via OAuth 2.0 and obtain access_token with users.write, roles.read, profiles.read scopes
  2. GET /api/v2/roles to retrieve the 'User' role ID
  3. GET /api/v2/profiles to retrieve the target profile ID (e.g., 'Sales Rep')
  4. POST /api/v2/users with firstName, lastName, email, and relationship objects for role and profile
  5. Verify response returns HTTP 201 with the new user id and active=true

Watch out for: User creation does not automatically send a welcome/invite email unless org settings are configured to do so. Confirm with Outreach admin settings.

Deprovision a user when they leave the org

  1. GET /api/v2/users?filter[email]=departing@example.com to retrieve the user id
  2. PATCH /api/v2/users/{id} with attributes: {locked: true} to deactivate the account
  3. Optionally reassign the user's sequences/tasks to another rep via the Outreach UI or API before deactivation

Watch out for: Hard deletion is not available via REST API. Locked users still consume a license seat until fully removed by Outreach support or via SCIM DELETE on Enterprise.

Automate user provisioning via SCIM with Okta

  1. Confirm Enterprise plan is active and SSO is already configured in a separate Okta app
  2. In Outreach admin, navigate to Security > SCIM and generate a SCIM bearer token
  3. In Okta, create a new SCIM 2.0 app (separate from the SSO SAML app) with base URL https://api.outreach.io/scim/v2 and the bearer token
  4. Configure attribute mappings: userName→email, givenName→firstName, familyName→lastName, active→active
  5. Assign Okta groups to the SCIM app; group push maps to Outreach Teams
  6. Test provisioning by assigning a test user in Okta and verifying creation in Outreach

Watch out for: SCIM and SSO must be separate Okta applications. Combining them into one app is not supported and will cause provisioning failures.

Why building this yourself is a trap

The rate limit of 10,000 requests per hour is applied per OAuth application per org. At the default page size of 50, paginating a large user list burns requests quickly; always set page[size]=1000 for bulk reads.

The JSON:API filter syntax (filter[fieldName]=value) is not universal across fields - only email and locked are confirmed filterable on the users endpoint; attempting unsupported filters may return unfiltered results or errors without clear indication.

Relationship object IDs for roles and profiles are not stable across orgs and must be resolved at runtime - hardcoding them will cause failures in multi-org or re-provisioned environments. The id field is an integer in the URL path but is serialized as a string in JSON:API response bodies; type coercion bugs are common here.

Webhooks for user.created, user.updated, and user.deleted are available, but if webhooks are unavailable on the plan, poll GET /users with filter[updatedAt][gt]= as a fallback for change detection.

Automate Outreach 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 11, 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