Stitchflow
Freshdesk logo

Freshdesk User Management API Guide

API workflow

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

UpdatedMar 9, 2026

Summary and recommendation

Freshdesk's v2 REST API covers the full agent and contact lifecycle at `https://<domain>.freshdesk.com/api/v2`. Authentication is HTTP Basic Auth using an API key as the username and any non-empty string as the password - there is no OAuth 2.0 for the v2 API.

Rate limits are enforced per account (not per key), meaning all integrations sharing an account draw from the same bucket: 100 req/min on Free, up to 700 req/min on Enterprise. The API exposes `X-RateLimit-Total`, `X-RateLimit-Remaining`, and `X-RateLimit-Used-CurrentRequest` headers on every response; implement exponential backoff on HTTP 429.

For teams building identity graph pipelines, the agent object's `role_ids`, `group_ids`, and `ticket_scope` fields provide the access-layer data needed to reconstruct a user's effective permission surface across the helpdesk.

API quick reference

Has user APIYes
Auth methodHTTP Basic Auth with API key (API key as username, any string as password)
Base URLOfficial docs
SCIM availableYes
SCIM plan requiredEnterprise

Authentication

Auth method: HTTP Basic Auth with API key (API key as username, any string as password)

Setup steps

  1. Log in to your Freshdesk account.
  2. Navigate to Profile Settings (top-right avatar menu).
  3. Copy the API key displayed under 'Your API Key'.
  4. In API requests, use HTTP Basic Auth: set the username to your API key and the password to any non-empty string (e.g., 'X').
  5. Encode credentials as Base64 and pass in the Authorization header: 'Authorization: Basic <base64(api_key:X)>'.

User object / data model

Field Type Description On create On update Notes
id integer Unique agent/contact identifier auto-assigned read-only Used in URL path for targeted operations
name string Full name of the agent or contact required optional
email string Primary email address required (unique) optional Must be unique across agents
phone string Phone number optional optional
mobile string Mobile number optional optional
job_title string Agent's job title optional optional Agent object only
role_ids array[integer] List of role IDs assigned to the agent optional optional Agent object only; defaults to Agent role
group_ids array[integer] Groups the agent belongs to optional optional Agent object only
ticket_scope integer Agent ticket permission scope: 1=Global, 2=Group, 3=Restricted optional optional Agent object only
type string Agent type: 'support_agent' or 'field_agent' optional optional Agent object only
available boolean Agent availability status optional optional Agent object only
occasional boolean Whether agent is an occasional (collaborator) agent optional optional Agent object only
active boolean Whether the agent account is active auto read-only Becomes true after email confirmation
created_at datetime Timestamp of record creation (UTC) auto-assigned read-only ISO 8601 format
updated_at datetime Timestamp of last update (UTC) auto-assigned auto-assigned ISO 8601 format
avatar object Agent avatar image metadata optional optional Multipart form upload required
contact.name string Nested contact name on agent object derived from name read-only via agent endpoint Agent object embeds a contact sub-object
custom_fields object Key-value map of custom contact/agent fields optional optional Field keys defined in account settings
tags array[string] Tags associated with a contact optional optional Contact object only
company_id integer Primary company the contact belongs to optional optional Contact object only

Core endpoints

List all agents

  • Method: GET
  • URL: https://<domain>.freshdesk.com/api/v2/agents
  • Watch out for: Returns only active agents by default. Use ?active=false to include deactivated agents. Max 100 per page.

Request example

GET /api/v2/agents?page=1&per_page=100
Authorization: Basic <base64(api_key:X)>

Response example

[
  {
    "id": 1,
    "name": "Jane Doe",
    "email": "jane@example.com",
    "active": true,
    "role_ids": [1],
    "created_at": "2023-01-10T08:00:00Z"
  }
]

Get a single agent

  • Method: GET
  • URL: https://<domain>.freshdesk.com/api/v2/agents/{agent_id}
  • Watch out for: Returns 404 if agent_id does not exist or belongs to a different account.

Request example

GET /api/v2/agents/1
Authorization: Basic <base64(api_key:X)>

Response example

{
  "id": 1,
  "name": "Jane Doe",
  "email": "jane@example.com",
  "ticket_scope": 1,
  "role_ids": [1],
  "group_ids": [2]
}

Create an agent

  • Method: POST
  • URL: https://<domain>.freshdesk.com/api/v2/agents
  • Watch out for: Newly created agents are inactive (active=false) until they confirm their email. Agent seat limits apply; exceeding them returns HTTP 400.

Request example

POST /api/v2/agents
Content-Type: application/json

{
  "name": "John Smith",
  "email": "john@example.com",
  "ticket_scope": 1,
  "role_ids": [1]
}

Response example

{
  "id": 42,
  "name": "John Smith",
  "email": "john@example.com",
  "active": false,
  "created_at": "2024-06-01T10:00:00Z"
}

Update an agent

  • Method: PUT
  • URL: https://<domain>.freshdesk.com/api/v2/agents/{agent_id}
  • Watch out for: Uses PUT (full-style), but only supplied fields are updated. Email cannot be changed via this endpoint after creation.

Request example

PUT /api/v2/agents/42
Content-Type: application/json

{
  "job_title": "Support Lead",
  "group_ids": [3, 5]
}

Response example

{
  "id": 42,
  "name": "John Smith",
  "job_title": "Support Lead",
  "group_ids": [3, 5],
  "updated_at": "2024-06-02T09:00:00Z"
}

Delete (deactivate) an agent

  • Method: DELETE
  • URL: https://<domain>.freshdesk.com/api/v2/agents/{agent_id}
  • Watch out for: DELETE deactivates the agent (sets active=false) rather than permanently deleting the record. The agent's contact record is retained.

Request example

DELETE /api/v2/agents/42
Authorization: Basic <base64(api_key:X)>

Response example

HTTP 204 No Content

List all contacts

  • Method: GET
  • URL: https://<domain>.freshdesk.com/api/v2/contacts
  • Watch out for: Supports filter params: email, mobile, phone, company_id, updated_since. Deleted contacts require ?deleted=true.

Request example

GET /api/v2/contacts?page=1&per_page=100
Authorization: Basic <base64(api_key:X)>

Response example

[
  {
    "id": 101,
    "name": "Alice",
    "email": "alice@customer.com",
    "active": true,
    "company_id": 5
  }
]

Create a contact

  • Method: POST
  • URL: https://<domain>.freshdesk.com/api/v2/contacts
  • Watch out for: At least one of email, phone, mobile, or twitter_id is required. Duplicate email returns HTTP 409.

Request example

POST /api/v2/contacts
Content-Type: application/json

{
  "name": "Bob Jones",
  "email": "bob@customer.com",
  "phone": "+14155550100"
}

Response example

{
  "id": 202,
  "name": "Bob Jones",
  "email": "bob@customer.com",
  "active": true,
  "created_at": "2024-06-01T11:00:00Z"
}

Convert contact to agent

  • Method: PUT
  • URL: https://<domain>.freshdesk.com/api/v2/contacts/{contact_id}/make_agent
  • Watch out for: Consumes an agent seat. New agent is inactive until email is confirmed. Fails if seat limit is reached.

Request example

PUT /api/v2/contacts/202/make_agent
Content-Type: application/json

{
  "ticket_scope": 1,
  "role_ids": [1]
}

Response example

{
  "id": 43,
  "email": "bob@customer.com",
  "active": false,
  "ticket_scope": 1
}

Rate limits, pagination, and events

  • Rate limits: Rate limits are plan-based and applied per account. Limits are expressed as requests per minute (RPM). Freshdesk returns rate-limit headers on every response.
  • Rate-limit headers: Yes
  • Retry-After header: No
  • Rate-limit notes: Headers returned: X-RateLimit-Total (limit), X-RateLimit-Remaining (remaining), X-RateLimit-Used-CurrentRequest (cost of last request). When limit is exceeded, HTTP 429 is returned. Retry after the current minute window resets.
  • Pagination method: offset
  • Default page size: 30
  • Max page size: 100
  • Pagination pointer: page (1-based) and per_page
Plan Limit Concurrent
Free (Sprout) 100 req/min 0
Growth (Blossom/Garden) 200 req/min 0
Pro (Estate) 400 req/min 0
Enterprise (Forest) 700 req/min 0
  • Webhooks available: Yes
  • Webhook notes: Freshdesk supports webhooks via Automation rules (Ticket automations and Observer rules). Webhooks can be triggered on ticket events but are not natively available for agent/contact lifecycle events (create, update, delete) directly.
  • Alternative event strategy: For agent/contact change events, poll the List Agents or List Contacts endpoints using the updated_since filter parameter, or use Freshdesk's native SCIM provisioning for identity lifecycle events via your IdP.
  • Webhook events: ticket.created, ticket.updated, ticket.resolved, ticket.closed, ticket.reopened

SCIM API status

  • SCIM available: Yes

  • SCIM version: 2.0

  • Plan required: Enterprise

  • Endpoint: https://.freshdesk.com/scim/v2

  • Supported operations: GET /Users (list users), GET /Users/{id} (get user), POST /Users (provision user), PUT /Users/{id} (replace user), PATCH /Users/{id} (update user), DELETE /Users/{id} (deprovision user)

Limitations:

  • Requires SSO (SAML) to be configured before enabling SCIM.
  • Only available on the Enterprise plan ($79/agent/month billed annually).
  • Group (team) provisioning support depends on IdP integration; not all IdPs support Freshdesk SCIM Groups.
  • SCIM token is separate from the REST API key and is generated in the Security Settings page.
  • Supported IdPs include Okta, Microsoft Entra ID (Azure AD), and OneLogin.

Common scenarios

Three scenarios cover the majority of programmatic user management needs. For agent onboarding: POST /api/v2/agents with name, email, ticket_scope, and role_ids; the agent is created with active=false until email confirmation, so poll GET /api/v2/agents/{id} before treating the account as usable.

Seat limits are enforced at creation time - exceeding them returns HTTP 400, so verify available capacity before bulk provisioning. For contact sync from an external CRM: paginate GET `/api/v2/contacts?

updated_since=&per_page=100, deduplicate by email before posting (duplicate email returns HTTP 409), and track X-RateLimit-Remaining` to avoid throttling.

For SCIM-based deprovisioning on Enterprise: generate a SCIM bearer token separately from Admin > Security (it is not the REST API key), configure your IdP to send DELETE /scim/v2/Users/{id}, and confirm deactivation via GET /api/v2/agents/{id} checking active=false.

Onboard a new support agent

  1. POST /api/v2/agents with name, email, ticket_scope, and role_ids to create the agent record.
  2. Agent receives an invitation email; account is inactive (active=false) until confirmed.
  3. Optionally PUT /api/v2/agents/{id} to assign group_ids and job_title after creation.
  4. Poll GET /api/v2/agents/{id} to check active=true once the agent confirms their email.

Watch out for: Agent seat limits are enforced at creation time. Verify available seats before bulk provisioning to avoid HTTP 400 errors.

Bulk-sync contacts from an external CRM

  1. GET /api/v2/contacts?updated_since=&page=1&per_page=100 to fetch recently changed contacts.
  2. Paginate through all pages until a page returns fewer than per_page results.
  3. For each contact not in Freshdesk, POST /api/v2/contacts with at minimum name and email.
  4. For existing contacts, PUT /api/v2/contacts/{id} with changed fields.
  5. Track X-RateLimit-Remaining and pause if approaching zero to avoid HTTP 429.

Watch out for: Duplicate email addresses return HTTP 409. Deduplicate by email before posting. The updated_since filter uses UTC ISO 8601 and is inclusive.

Deprovision an agent via SCIM (Enterprise)

  1. Ensure SSO (SAML) is configured and SCIM is enabled in Admin > Security.
  2. Generate a SCIM bearer token from the Security Settings page.
  3. In your IdP (Okta, Entra ID, OneLogin), unassign the user from the Freshdesk SCIM application.
  4. The IdP sends DELETE /scim/v2/Users/{scim_user_id} to Freshdesk automatically.
  5. Freshdesk deactivates the agent; verify by GET /api/v2/agents/{id} and confirming active=false.

Watch out for: SCIM deprovisioning requires the Enterprise plan and an active SSO configuration. Removing SCIM access does not delete the agent's historical ticket data.

Why building this yourself is a trap

Several API behaviors are non-obvious and will cause silent failures if not handled explicitly. DELETE on /api/v2/agents/{id} deactivates the agent rather than permanently removing the record - the contact record is retained and the agent continues to appear in historical data.

The List Agents endpoint returns only active agents by default; pass ?active=false to include deactivated accounts, which matters for identity graph reconciliation where stale access must be detected. Pagination is 1-based with no cursor and no total-count header - the only termination signal is a page returning fewer results than per_page.

Freshdesk does not emit webhooks for agent or contact lifecycle events; change detection requires polling with the updated_since filter. Custom agent and contact fields must be pre-created in the admin UI before they can be written via API, making field-level provisioning dependent on out-of-band configuration.

Finally, SCIM provisioning requires an active SAML SSO configuration as a prerequisite - SCIM cannot be enabled independently.

Automate Freshdesk 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 9, 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