Summary and recommendation
Figma exposes two distinct API surfaces for identity and user management: a REST API (base URL https://api.figma.com/v1) authenticated via Personal Access Token or OAuth 2.0, and a SCIM 2.0 API (base URL https://www.figma.com/scim/v2) authenticated via a separately generated Admin panel token.
These are not interchangeable - the SCIM token is generated in Admin → Security, not in user account settings, and the REST API PAT cannot authenticate SCIM endpoints. Org-level member endpoints (/v1/orgs/:org_id/members) and all SCIM operations require Organization or Enterprise plan.
Integrating Figma into an identity graph requires combining both surfaces: REST for team-scoped membership reads, SCIM for full user lifecycle writes and email-level visibility.
API quick reference
| Has user API | Yes |
| Auth method | Personal Access Token (PAT) or OAuth 2.0 |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Organization or Enterprise |
Authentication
Auth method: Personal Access Token (PAT) or OAuth 2.0
Setup steps
- Personal Access Token: Log in to Figma → Settings → Account → Personal access tokens → Generate new token. Pass token in header: Authorization: Bearer
. - OAuth 2.0: Register an app at figma.com/developers/apps to obtain client_id and client_secret. Redirect users to https://www.figma.com/oauth?client_id=...&redirect_uri=...&scope=...&state=...&response_type=code. Exchange authorization code for access token at https://www.figma.com/api/oauth/token via POST with client credentials. Use returned access_token in Authorization: Bearer header.
- For SCIM: Generate a SCIM API token in the Figma Admin panel (Organization or Enterprise plan required). Use as Bearer token against the SCIM base URL.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| files:read | Read access to files, projects, and comments. | Reading file and project data |
| file_variables:read | Read access to local and published variables in files. | Reading variables |
| file_variables:write | Write access to local variables in files. | Creating/updating variables |
| webhooks:write | Create and manage webhooks for a team. | Webhook registration and management |
| org:read | Read organization-level data including members and teams. | Listing org members, teams (Enterprise/Org plan) |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique identifier for the user. | system-generated | immutable | Used as path param in /v1/users/:id |
| string | User's email address. | required | via SCIM only | Primary identifier for invitations and SCIM provisioning | |
| handle | string | User's display username. | set by user | user-managed | Returned in REST API user objects |
| img_url | string | URL of the user's profile image. | system/user-set | user-managed | Returned in REST API user objects |
| role | string | User's role within a team or organization (e.g., owner, admin, editor, viewer). | set on invite | patchable via REST or SCIM | Role values differ between team and org contexts |
| active | boolean | Whether the user account is active (SCIM field). | defaults true | PATCH via SCIM to deactivate | Setting active=false deprovisions the user via SCIM |
| userName | string | SCIM userName attribute, typically the user's email. | required for SCIM | patchable via SCIM | SCIM 2.0 core attribute |
| name.givenName | string | User's first name (SCIM). | optional | patchable via SCIM | Part of SCIM name object |
| name.familyName | string | User's last name (SCIM). | optional | patchable via SCIM | Part of SCIM name object |
| externalId | string | External identifier set by the IdP (SCIM). | set by IdP | managed by IdP | Used to correlate Figma users with IdP records |
Core endpoints
Get current authenticated user
- Method: GET
- URL:
https://api.figma.com/v1/me - Watch out for: Returns the user associated with the token only; cannot retrieve arbitrary users via this endpoint.
Request example
GET /v1/me
Authorization: Bearer <token>
Response example
{
"id": "12345",
"email": "user@example.com",
"handle": "jdoe",
"img_url": "https://..."
}
Get user by ID
- Method: GET
- URL:
https://api.figma.com/v1/users/:user_id - Watch out for: Email is not returned for users other than the authenticated user.
Request example
GET /v1/users/12345
Authorization: Bearer <token>
Response example
{
"id": "12345",
"handle": "jdoe",
"img_url": "https://..."
}
List team members
- Method: GET
- URL:
https://api.figma.com/v1/teams/:team_id/members - Watch out for: Requires the token owner to be a member of the team. Org-level member listing requires org:read scope and Organization/Enterprise plan.
Request example
GET /v1/teams/98765/members
Authorization: Bearer <token>
Response example
{
"members": [
{"id":"12345","role":"editor","handle":"jdoe"}
]
}
List organization members
- Method: GET
- URL:
https://api.figma.com/v1/orgs/:org_id/members - Watch out for: Organization/Enterprise plan required. Paginated via cursor parameter.
Request example
GET /v1/orgs/11111/members
Authorization: Bearer <token>
Response example
{
"members": [
{"id":"12345","email":"user@example.com","role":"admin"}
],
"cursor": "next_cursor_value"
}
SCIM – List users
- Method: GET
- URL:
https://www.figma.com/scim/v2/Users - Watch out for: SCIM token is separate from REST API PAT; generated in Admin panel. Requires Organization or Enterprise plan.
Request example
GET /scim/v2/Users?startIndex=1&count=50
Authorization: Bearer <scim_token>
Response example
{
"schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults":2,
"Resources":[{"id":"abc","userName":"user@example.com","active":true}]
}
SCIM – Create user
- Method: POST
- URL:
https://www.figma.com/scim/v2/Users - Watch out for: User must have a verified email domain matching the org's claimed domain. Provisioning sends an invite email unless SSO is enforced.
Request example
POST /scim/v2/Users
Authorization: Bearer <scim_token>
{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"user@example.com","active":true}
Response example
{
"id": "abc123",
"userName": "user@example.com",
"active": true
}
SCIM – Update user (deactivate)
- Method: PATCH
- URL:
https://www.figma.com/scim/v2/Users/:user_id - Watch out for: Deactivating a user removes their org seat but does not delete their Figma account or personal files.
Request example
PATCH /scim/v2/Users/abc123
Authorization: Bearer <scim_token>
{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":[{"op":"replace","path":"active","value":false}]}
Response example
{
"id": "abc123",
"userName": "user@example.com",
"active": false
}
SCIM – Delete user
- Method: DELETE
- URL:
https://www.figma.com/scim/v2/Users/:user_id - Watch out for: Behavior may differ from PATCH active=false; verify with Figma docs whether DELETE fully removes org membership or just deprovisions.
Request example
DELETE /scim/v2/Users/abc123
Authorization: Bearer <scim_token>
Response example
HTTP 204 No Content
Rate limits, pagination, and events
- Rate limits: Figma enforces rate limits per token. REST API limits are not fully published but documented as 'rate limited' with HTTP 429 responses. SCIM endpoints have separate limits.
- Rate-limit headers: Yes
- Retry-After header: Yes
- Rate-limit notes: When rate limited, Figma returns HTTP 429. Clients should respect Retry-After header if present and implement exponential backoff. Specific numeric limits are not published in official docs.
- Pagination method: cursor
- Default page size: 0
- Max page size: 0
- Pagination pointer: cursor
| Plan | Limit | Concurrent |
|---|---|---|
| All plans (REST API) | Not publicly specified; HTTP 429 returned when exceeded | 0 |
| SCIM (Organization/Enterprise) | Not publicly specified; HTTP 429 returned when exceeded | 0 |
- Webhooks available: Yes
- Webhook notes: Figma supports webhooks via the REST API for team-level events. Webhooks are registered per-team and deliver HTTP POST payloads to a configured endpoint.
- Alternative event strategy: No native user-lifecycle webhook events (e.g., user added/removed). Poll /v1/teams/:team_id/members or use SCIM with IdP-driven provisioning for user lifecycle automation.
- Webhook events: FILE_UPDATE, FILE_VERSION_UPDATE, FILE_DELETE, LIBRARY_PUBLISH, FILE_COMMENT
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Organization or Enterprise
Endpoint: https://www.figma.com/scim/v2
Supported operations: GET /Users (list users), GET /Users/:id (get user), POST /Users (create/invite user), PATCH /Users/:id (update user attributes, deactivate), DELETE /Users/:id (remove user), GET /Groups (list groups/teams), POST /Groups (create group), PATCH /Groups/:id (update group membership), DELETE /Groups/:id (delete group)
Limitations:
- SCIM token is generated separately from REST API PAT in the Admin panel.
- SAML SSO must be configured before enabling SCIM.
- Deactivating a user (active=false) removes org seat but does not delete the Figma account.
- User email domain must match a domain claimed by the organization.
- Full seat management via SCIM (including editor seat assignment) requires Enterprise plan; Organization plan has basic provisioning.
- March 2025 billing changes may require plan migration for existing customers.
Common scenarios
For IdP-driven provisioning, configure SAML SSO first, generate a SCIM token in Admin → Security, and point your IdP (Okta, Entra ID, etc. ) at POST /scim/v2/Users.
The user's email domain must match a domain claimed by the org or provisioning will fail - claim the domain in Admin → Security before attempting bulk provisioning.
For deprovisioning, the IdP sends PATCH /scim/v2/Users/:id with active=false; this removes the org seat but does not delete the user's personal Figma account or files outside the org. Transfer file ownership via the Admin panel before triggering deprovisioning if content continuity matters.
For membership audits via REST, call GET /v1/orgs/:org_id/members with org:read scope and handle cursor-based pagination - pass the cursor value from each response as ? cursor= on the next request until no cursor is returned.
Use SCIM GET /Users for full email visibility, as the REST API omits email for users other than the authenticated token owner.
Provision a new employee via SCIM (IdP-driven)
- Ensure SAML SSO is configured and SCIM is enabled in Figma Admin panel (Organization or Enterprise plan).
- Generate a SCIM API token in Admin → Security → SCIM and configure it in your IdP (Okta, Entra ID, etc.).
- Assign the user to the Figma app in the IdP; the IdP sends POST /scim/v2/Users with userName (email) and name attributes.
- Figma creates the user and sends an invite email (or auto-provisions if SSO is enforced).
- Verify user appears in /scim/v2/Users list and in the Figma Admin panel.
Watch out for: If the user's email domain is not claimed by the org, provisioning will fail. Claim the domain in Admin → Security first.
Deprovision a departing employee
- Remove the user from the Figma app assignment in the IdP.
- IdP sends PATCH /scim/v2/Users/:id with Operations: [{op: replace, path: active, value: false}].
- Figma removes the user's org seat; they lose access to org resources.
- Optionally transfer file ownership via Figma Admin panel before deprovisioning.
- Confirm user no longer appears as active in /scim/v2/Users.
Watch out for: Deactivation removes org access but does not delete the user's personal Figma account or files outside the org.
Audit current team membership via REST API
- Generate a PAT or use an OAuth 2.0 token with org:read scope.
- Call GET /v1/orgs/:org_id/members (Organization/Enterprise) or GET /v1/teams/:team_id/members.
- Handle cursor-based pagination: check response for cursor field and repeat request with ?cursor=
until no cursor is returned. - Collect id, email, role fields for each member.
- Cross-reference with IdP user list to identify orphaned accounts.
Watch out for: Email is only returned in org-level member responses for admins; team member responses may omit email. Use SCIM GET /Users for full email visibility.
Why building this yourself is a trap
The primary integration trap is assuming the REST API and SCIM API are equivalent paths to the same data - they are not.
The REST API does not expose email for users other than the authenticated token owner (/v1/me), making it insufficient alone for building an identity graph that maps Figma accounts to authoritative IdP identities.
SCIM provides email via userName and externalId for IdP correlation, but requires a separately provisioned token and an active SAML SSO configuration; attempting to enable SCIM without SSO in place is not supported.
Rate limits are undocumented numerically for both surfaces - HTTP 429 is returned when exceeded, and clients must implement exponential backoff with Retry-After header handling.
Webhook events are team-scoped and cover only file-level activity; there are no org-level or user-lifecycle webhook events, so user join and leave detection requires polling /v1/orgs/:org_id/members or relying on IdP-side SCIM push. Full SCIM seat management including Editor seat assignment is gated to Enterprise plan; Organization plan supports basic provisioning only.
Automate Figma 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.