Stitchflow
Gusto logo

Gusto 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

Gusto's REST API (base: `https://api.gusto.com/v1`) uses OAuth 2.0 authorization code flow. The company UUID is not embedded in the token - it must be retrieved via `GET /v1/me` after authorization.

All employee lifecycle operations (create, update, terminate) are available, but each carries non-obvious side effects: employee creation does not trigger onboarding emails, termination via `POST /v1/employees/{employee_id}/terminations` is irreversible through the API, and `PUT` on employee records behaves as a near-full replace rather than a partial update.

There is no inbound SCIM 2.0 endpoint; IdP-driven provisioning into Gusto must use the REST API directly or rely on JIT SSO.

For teams building identity graph pipelines, Gusto employee records - including `uuid`, `department`, `manager_uuid`, `start_date`, and `termination_date` - provide the HR node of the identity graph, but compensation and SSN fields require careful scope and masking handling.

API quick reference

Has user APIYes
Auth methodOAuth 2.0 (authorization code flow); API key tokens available for embedded partner integrations
Base URLOfficial docs
SCIM availableNo
SCIM plan requiredNot available; Gusto does not offer inbound SCIM provisioning as of early 2025. Outbound provisioning (Gusto → Slack, Zoom, etc.) is available on Plus/Premium plans.

Authentication

Auth method: OAuth 2.0 (authorization code flow); API key tokens available for embedded partner integrations

Setup steps

  1. Register an application in the Gusto Developer Portal (https://dev.gusto.com) to obtain a client_id and client_secret.
  2. Redirect the user to https://api.gusto.com/oauth/authorize with response_type=code, client_id, redirect_uri, and desired scopes.
  3. Exchange the returned authorization code for an access_token and refresh_token via POST https://api.gusto.com/oauth/token.
  4. Include the access token in all API requests as: Authorization: Bearer {access_token}.
  5. Refresh the access token using the refresh_token before expiry; access tokens expire after a short window (exact TTL not publicly documented).

Required scopes

Scope Description Required for
employees:read Read employee records including personal info, job details, and status. GET /v1/companies/{company_id}/employees
employees:write Create and update employee records. POST /v1/companies/{company_id}/employees, PUT /v1/employees/{employee_id}
companies:read Read company information and metadata. GET /v1/companies/{company_id}
jobs:read Read job and compensation data for employees. GET /v1/employees/{employee_id}/jobs
jobs:write Create and update job and compensation records. POST /v1/employees/{employee_id}/jobs

User object / data model

Field Type Description On create On update Notes
uuid string Unique identifier for the employee. system-generated immutable Use this as the stable employee ID.
first_name string Employee's first name. required optional
last_name string Employee's last name. required optional
email string Work email address; used for Gusto account login invitation. required optional Must be unique across the company.
date_of_birth string (YYYY-MM-DD) Employee's date of birth. optional optional Required for payroll processing.
ssn string Social Security Number (masked in responses). optional optional Returned masked (e.g., XXX-XX-1234) in GET responses.
phone string Employee phone number. optional optional
preferred_first_name string Preferred first name if different from legal name. optional optional
start_date string (YYYY-MM-DD) Employee's hire/start date. required optional
termination_date string (YYYY-MM-DD) Date of termination if applicable. n/a set via termination endpoint Set via POST /v1/employees/{id}/terminations, not direct field update.
department string Department name the employee belongs to. optional optional
manager_uuid string UUID of the employee's manager. optional optional
onboarded boolean Whether the employee has completed onboarding. system-set read-only
has_ssn boolean Indicates if SSN has been provided. system-set read-only
jobs array List of job/compensation objects associated with the employee. optional via jobs endpoint Managed via /v1/employees/{id}/jobs sub-resource.
home_address object Employee's home address (street, city, state, zip, country). optional optional Required for payroll tax calculations.
garnishments array Wage garnishment records. n/a via garnishments endpoint Managed via sub-resource endpoint.
custom_fields array Company-defined custom fields for the employee. optional optional Field definitions must exist in company settings first.

Core endpoints

List employees for a company

  • Method: GET
  • URL: https://api.gusto.com/v1/companies/{company_id}/employees
  • Watch out for: Returns all employees including terminated ones by default. Filter with ?terminated=false to get only active employees.

Request example

GET /v1/companies/abc-123/employees?page=1&per=25
Authorization: Bearer {token}

Response example

[
  {
    "uuid": "emp-uuid-001",
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "onboarded": true
  }
]

Get a single employee

  • Method: GET
  • URL: https://api.gusto.com/v1/employees/{employee_id}
  • Watch out for: SSN is always masked in responses regardless of scope.

Request example

GET /v1/employees/emp-uuid-001
Authorization: Bearer {token}

Response example

{
  "uuid": "emp-uuid-001",
  "first_name": "Jane",
  "last_name": "Doe",
  "email": "jane@example.com",
  "start_date": "2023-01-15",
  "onboarded": true
}

Create an employee

  • Method: POST
  • URL: https://api.gusto.com/v1/companies/{company_id}/employees
  • Watch out for: Creating an employee does NOT automatically send an onboarding invitation. A separate onboarding flow or invitation must be triggered. The employee will have onboarded=false until they complete self-onboarding.

Request example

POST /v1/companies/abc-123/employees
Content-Type: application/json
{
  "first_name": "John",
  "last_name": "Smith",
  "email": "john@example.com",
  "start_date": "2024-06-01"
}

Response example

{
  "uuid": "emp-uuid-002",
  "first_name": "John",
  "last_name": "Smith",
  "email": "john@example.com",
  "onboarded": false
}

Update an employee

  • Method: PUT
  • URL: https://api.gusto.com/v1/employees/{employee_id}
  • Watch out for: Uses PUT (full-ish update), not PATCH. Omitting optional fields may clear them. Verify field behavior before bulk updates.

Request example

PUT /v1/employees/emp-uuid-002
Content-Type: application/json
{
  "first_name": "Jonathan",
  "department": "Engineering"
}

Response example

{
  "uuid": "emp-uuid-002",
  "first_name": "Jonathan",
  "last_name": "Smith",
  "department": "Engineering"
}

Terminate an employee

  • Method: POST
  • URL: https://api.gusto.com/v1/employees/{employee_id}/terminations
  • Watch out for: Termination is irreversible via API. run_termination_payroll=true triggers a final payroll run which has billing implications.

Request example

POST /v1/employees/emp-uuid-002/terminations
Content-Type: application/json
{
  "effective_date": "2024-12-31",
  "run_termination_payroll": true
}

Response example

{
  "employee_uuid": "emp-uuid-002",
  "active": false,
  "effective_date": "2024-12-31",
  "run_termination_payroll": true
}

Get company details

  • Method: GET
  • URL: https://api.gusto.com/v1/companies/{company_id}
  • Watch out for: The company UUID is required for most employee endpoints. Retrieve it from the token's associated company after OAuth.

Request example

GET /v1/companies/abc-123
Authorization: Bearer {token}

Response example

{
  "uuid": "abc-123",
  "name": "Acme Corp",
  "ein": "XX-XXXXXXX",
  "entity_type": "LLC",
  "tier": "plus"
}

List jobs for an employee

  • Method: GET
  • URL: https://api.gusto.com/v1/employees/{employee_id}/jobs
  • Watch out for: Compensation data (rate, payment_unit) is nested within the job object. An employee can have multiple jobs; only one can be primary=true.

Request example

GET /v1/employees/emp-uuid-001/jobs
Authorization: Bearer {token}

Response example

[
  {
    "uuid": "job-uuid-001",
    "title": "Software Engineer",
    "rate": "120000.00",
    "payment_unit": "Year",
    "primary": true
  }
]

Get current user (authenticated)

  • Method: GET
  • URL: https://api.gusto.com/v1/me
  • Watch out for: Returns the authenticated user's role and associated company UUIDs. Use this to discover company_id after OAuth rather than hardcoding it.

Request example

GET /v1/me
Authorization: Bearer {token}

Response example

{
  "email": "admin@example.com",
  "roles": {
    "payroll_admin": {
      "companies": [{"uuid": "abc-123", "name": "Acme Corp"}]
    }
  }
}

Rate limits, pagination, and events

  • Rate limits: Gusto does not publicly document specific numeric rate limits in its developer docs as of early 2025. Limits are enforced but thresholds are not published.
  • Rate-limit headers: Yes
  • Retry-After header: No
  • Rate-limit notes: HTTP 429 is returned when limits are exceeded. Gusto recommends implementing exponential backoff. Specific header names for rate limit state are not documented publicly.
  • Pagination method: offset
  • Default page size: 25
  • Max page size: 100
  • Pagination pointer: page and per (e.g., ?page=1&per=25)
Plan Limit Concurrent
All API partners Not publicly documented 0
  • Webhooks available: Yes
  • Webhook notes: Gusto supports webhooks for event-driven notifications. Webhook subscriptions are configured via the API or Developer Portal. Events are delivered via HTTP POST to a registered endpoint.
  • Alternative event strategy: Poll GET /v1/companies/{company_id}/employees with updated_since parameter if webhooks are not feasible.
  • Webhook events: employee.created, employee.updated, employee.terminated, payroll.created, payroll.updated, company.updated

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: Not available; Gusto does not offer inbound SCIM provisioning as of early 2025. Outbound provisioning (Gusto → Slack, Zoom, etc.) is available on Plus/Premium plans.
  • Endpoint: Not documented

Limitations:

  • No inbound SCIM 2.0 endpoint for provisioning users into Gusto from an IdP.
  • JIT (Just-in-Time) provisioning is supported via Okta and OneLogin SSO integrations.
  • Gusto has indicated SCIM support is under exploration but not yet released.
  • Outbound provisioning from Gusto to third-party apps requires Plus ($80/mo + $12/person) or Premium plan.

Common scenarios

Three core automation scenarios are well-supported by the API.

First, new-hire onboarding: POST /v1/companies/{company_id}/employees creates the record, followed by POST /v1/employees/{employee_id}/jobs for compensation, but the employee remains onboarded=false until they complete self-service steps in Gusto - payroll cannot run until that flag flips.

Second, directory sync: GET /v1/companies/{company_id}/employees? terminated=false&per=100 with page iteration covers full pulls; subscribe to `employee.

created, employee. updated, and employee.

terminatedwebhooks for delta sync to avoid full re-pulls. Third, offboarding:POST /v1/employees/{employee_id}/terminationswithrun_termination_payroll=falseif final pay is handled separately - setting it totrue` initiates a payroll run immediately with billing implications.

Downstream deprovisioning (Slack, Zoom) can be triggered by the employee. terminated webhook if outbound provisioning is configured on Plus/Premium.

Onboard a new hire via API

  1. POST /v1/companies/{company_id}/employees with first_name, last_name, email, start_date to create the employee record.
  2. POST /v1/employees/{employee_id}/jobs to assign a job title and compensation.
  3. PATCH or PUT /v1/employees/{employee_id} to add home_address and date_of_birth required for payroll.
  4. Trigger the Gusto self-onboarding invitation from the Gusto admin UI or via the onboarding flow endpoint (if available under your partner agreement) so the employee can complete I-9, W-4, and direct deposit setup.
  5. Poll GET /v1/employees/{employee_id} or listen for employee.updated webhook until onboarded=true.

Watch out for: API employee creation alone does not complete onboarding. The employee must complete self-service steps in Gusto before payroll can run for them.

Sync active employees to an external directory

  1. GET /v1/me to retrieve the company UUID for the authenticated token.
  2. GET /v1/companies/{company_id}/employees?terminated=false&page=1&per=100 to fetch the first page of active employees.
  3. Iterate pages (increment page param) until the response array is empty or fewer than per records are returned.
  4. Map Gusto employee fields (uuid, first_name, last_name, email, department, manager_uuid) to the target directory schema.
  5. Subscribe to employee.created, employee.updated, and employee.terminated webhooks to receive real-time delta updates instead of full re-syncs.

Watch out for: Without the terminated=false filter, terminated employees are included in list responses and must be filtered client-side, inflating payload size.

Offboard (terminate) an employee

  1. Confirm the employee UUID via GET /v1/companies/{company_id}/employees or GET /v1/me.
  2. POST /v1/employees/{employee_id}/terminations with effective_date and run_termination_payroll (set false if final pay is handled separately).
  3. Listen for employee.terminated webhook event to trigger downstream deprovisioning in connected systems (e.g., revoke SSO sessions, disable accounts in Slack/Zoom via Gusto outbound provisioning on Plus/Premium).
  4. Verify termination by checking active=false on GET /v1/employees/{employee_id}.

Watch out for: Termination via API cannot be undone through the API. Coordinate with HR before automating terminations. run_termination_payroll=true will initiate a payroll run immediately.

Why building this yourself is a trap

The most common integration traps in Gusto's API are scope and state assumptions. Rate limits are enforced via HTTP 429 but thresholds are not publicly documented - exponential backoff is required, not optional.

The PUT endpoint for employee updates is not a safe partial-update operation; omitting fields can clear existing values, making it dangerous for bulk operations without prior field-behavior testing. Multi-company access requires a separate OAuth authorization flow per company - a single token does not span companies.

SSN is always masked in read responses regardless of granted scopes, which affects identity verification workflows. Finally, there is no inbound SCIM support; any integration that assumes a SCIM endpoint exists will fail silently at the provisioning layer.

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

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste