Summary and recommendation
Typeform's REST API (base URL: `https://api.typeform.com`) supports OAuth 2.0 and Personal Access Tokens via Bearer auth.
Workspace membership is the primary identity surface: members are listed, added, and removed at the workspace level via `/workspaces/{workspace_id}/members`, scoped with `accounts:read` and `workspaces:write`.
Critical constraint: there is no REST endpoint to create a net-new Typeform user account.
`POST /workspaces/{workspace_id}/members` requires the target user to already hold a Typeform account.
Account creation via API is only possible through SCIM on Enterprise.
The `/me` endpoint returns only the authenticated token owner's profile - there is no admin-scoped endpoint to enumerate all users across an account via REST.
Rate limit is 2 requests/second per token across all plans.
Pagination uses offset-based `page` and `page_size` parameters;
`page_size` caps at 200.
HTTP 429 is returned on rate limit breach;
specific retry-after headers are not documented publicly.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 or Personal Access Token (Bearer token) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise (custom pricing; SSO prerequisite required) |
Authentication
Auth method: OAuth 2.0 or Personal Access Token (Bearer token)
Setup steps
- For Personal Access Token: Log in to Typeform, go to Account > Personal tokens, generate a token with required scopes.
- For OAuth 2.0: Register an application at https://www.typeform.com/developers/apps/, obtain client_id and client_secret, implement authorization code flow to obtain access token.
- Pass the token in the Authorization header as 'Bearer
' on all API requests.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| accounts:read | Read account and workspace member information | Listing workspace members |
| workspaces:read | Read workspace details | GET /workspaces and GET /workspaces/{workspace_id} |
| workspaces:write | Create and modify workspaces | POST /workspaces, PATCH /workspaces/{workspace_id} |
| forms:read | Read form definitions | GET /forms, GET /forms/{form_id} |
| forms:write | Create and modify forms | POST /forms, PATCH /forms/{form_id}, DELETE /forms/{form_id} |
| responses:read | Read form responses | GET /forms/{form_id}/responses |
| webhooks:read | Read webhook configurations | GET /forms/{form_id}/webhooks |
| webhooks:write | Create and modify webhooks | PUT /forms/{form_id}/webhooks/{tag} |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| account_id | string | Unique identifier for the Typeform account | system-assigned | immutable | Returned in /me endpoint |
| string | Email address of the account holder | required | not updatable via API | Returned in /me endpoint | |
| alias | string | Display name / alias for the account | optional | not documented as updatable via API | Returned in /me endpoint |
| language | string | Preferred language for the account UI | optional | not documented | Returned in /me endpoint |
| id | string | Workspace member identifier | system-assigned | immutable | Present in workspace members list |
| role | string | Member role within a workspace (e.g., owner, admin, member) | assigned on invite | patchable via workspace member endpoint | Workspace-scoped, not global |
Core endpoints
Get current authenticated user (me)
- Method: GET
- URL:
https://api.typeform.com/me - Watch out for: Returns only the authenticated user's own account; no endpoint to list all account users via REST API.
Request example
GET /me
Authorization: Bearer <token>
Response example
{
"account_id": "abc123",
"email": "user@example.com",
"alias": "Jane Doe",
"language": "en"
}
List workspaces
- Method: GET
- URL:
https://api.typeform.com/workspaces - Watch out for: Workspaces are the primary organizational unit; user membership is managed at workspace level.
Request example
GET /workspaces?page=1&page_size=10
Authorization: Bearer <token>
Response example
{
"page_count": 2,
"total_items": 12,
"items": [
{"id": "ws_abc", "name": "My Workspace", "self": {"href": "..."}}
]
}
Get workspace
- Method: GET
- URL:
https://api.typeform.com/workspaces/{workspace_id} - Watch out for: Members are returned as a link (HATEOAS), not inline; requires a separate call to /members.
Request example
GET /workspaces/ws_abc
Authorization: Bearer <token>
Response example
{
"id": "ws_abc",
"name": "My Workspace",
"members": {"href": "https://api.typeform.com/workspaces/ws_abc/members"}
}
List workspace members
- Method: GET
- URL:
https://api.typeform.com/workspaces/{workspace_id}/members - Watch out for: Requires accounts:read scope. Only members of workspaces accessible to the token are returned.
Request example
GET /workspaces/ws_abc/members
Authorization: Bearer <token>
Response example
{
"items": [
{"id": "usr_xyz", "email": "member@example.com", "role": "member"}
]
}
Add member to workspace
- Method: POST
- URL:
https://api.typeform.com/workspaces/{workspace_id}/members - Watch out for: User must already have a Typeform account; this does not create a new Typeform account.
Request example
POST /workspaces/ws_abc/members
Content-Type: application/json
{"email": "newuser@example.com", "role": "member"}
Response example
HTTP 204 No Content
Remove member from workspace
- Method: DELETE
- URL:
https://api.typeform.com/workspaces/{workspace_id}/members/{member_id} - Watch out for: Cannot remove the workspace owner. Workspace owner must be transferred before deletion.
Request example
DELETE /workspaces/ws_abc/members/usr_xyz
Authorization: Bearer <token>
Response example
HTTP 204 No Content
Create workspace
- Method: POST
- URL:
https://api.typeform.com/workspaces - Watch out for: Workspace limits depend on plan tier; exceeding limits returns 403.
Request example
POST /workspaces
Content-Type: application/json
{"name": "New Team Workspace"}
Response example
{
"id": "ws_new123",
"name": "New Team Workspace"
}
Configure webhook
- Method: PUT
- URL:
https://api.typeform.com/forms/{form_id}/webhooks/{tag} - Watch out for: Webhooks fire on form response submission, not on user/member changes.
Request example
PUT /forms/abc123/webhooks/my-hook
Content-Type: application/json
{"url": "https://example.com/hook", "enabled": true}
Response example
{
"id": "wh_xyz",
"form_id": "abc123",
"tag": "my-hook",
"url": "https://example.com/hook",
"enabled": true
}
Rate limits, pagination, and events
- Rate limits: Typeform enforces rate limits on API requests. The official docs note a limit of 2 requests per second per token for most endpoints. Burst behavior and per-plan differences are not explicitly documented in public API docs.
- Rate-limit headers: Unknown
- Retry-After header: Unknown
- Rate-limit notes: When rate limited, the API returns HTTP 429. Specific header names for rate limit state are not documented in official public docs.
- Pagination method: offset
- Default page size: 10
- Max page size: 200
- Pagination pointer: page_size, page
| Plan | Limit | Concurrent |
|---|---|---|
| All plans (documented default) | 2 requests/second per token | 0 |
- Webhooks available: Yes
- Webhook notes: Typeform webhooks notify an external URL when a new form response is submitted. They are form-scoped and do not fire on user provisioning, workspace membership changes, or account events.
- Alternative event strategy: For user/member change notifications, polling the /workspaces/{id}/members endpoint is the only documented approach via the REST API. SCIM provisioning (Enterprise) handles lifecycle events via IdP.
- Webhook events: form_response
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise (custom pricing; SSO prerequisite required)
Endpoint: Not publicly documented as a static base URL; endpoint is provisioned through the IdP (Okta or Microsoft Entra ID) connector configuration in Typeform Enterprise settings.
Supported operations: Create user, Deactivate user, Update user attributes, Push groups (Okta)
Limitations:
- SCIM is only available on Enterprise plan with SSO enabled
- Supported IdPs are Okta and Microsoft Entra ID only (Google Workspace and OneLogin not supported per context data)
- SCIM endpoint URL is not a generic public endpoint; it is generated within the Typeform Enterprise SSO settings and provided to the IdP
- Group/team provisioning support may vary by IdP connector
- No public SCIM API reference documentation available; configuration is UI-driven
Common scenarios
Audit workspace membership: Authenticate with accounts:read + workspaces:read, paginate GET /workspaces, then call GET /workspaces/{workspace_id}/members for each workspace.
Aggregate role and email fields to produce a full membership snapshot.
Caveat: only workspaces accessible to the token owner are returned - a single-token audit will miss workspaces not shared with that account.
Add a user to a workspace: Confirm the target user has an existing Typeform account (no REST path to create one), then POST /workspaces/{workspace_id}/members with {"email": "user@example.com", "role": "member"}.
Expect HTTP 204 on success;
a 422 indicates the user account does not exist in Typeform.
Automate lifecycle via SCIM (Enterprise only): SCIM 2.0 is available on Enterprise with SSO as a hard prerequisite.
Supported IdPs are Okta and Microsoft Entra ID only.
The SCIM base URL is instance-specific - generated inside Typeform's Enterprise SSO settings, not a generic public endpoint.
Configure the IdP connector with the provisioned URL and bearer token;
the IdP then drives create, update, and deactivate operations.
No public SCIM API reference exists;
setup is UI-driven through the IdP connector.
Webhooks: Webhook events are scoped to form_response (submission) only.
No user lifecycle or workspace membership webhook events exist.
For membership change detection, polling GET /workspaces/{workspace_id}/members is the only documented REST approach.
Audit workspace membership
- Authenticate with a PAT or OAuth token with accounts:read and workspaces:read scopes.
- GET /workspaces to retrieve all workspaces accessible to the token (paginate with page/page_size).
- For each workspace, GET /workspaces/{workspace_id}/members to list all members and their roles.
- Aggregate results to produce a full membership report.
Watch out for: Token must have access to each workspace; workspaces not shared with the token owner will not appear.
Add a user to a workspace
- Confirm the target user already has a Typeform account (no API to create accounts via REST).
- Authenticate with a token holding workspaces:write and accounts:read scopes.
- POST /workspaces/{workspace_id}/members with body {"email": "user@example.com", "role": "member"}.
- Expect HTTP 204 on success; handle 404 if workspace not found or 422 if user does not exist.
Watch out for: If the user does not have a Typeform account, the API will return an error. Account creation must happen via SCIM (Enterprise) or UI invitation.
Automate user lifecycle via SCIM on Enterprise
- Ensure Typeform Enterprise plan is active with SSO configured (Okta or Entra ID).
- In Typeform Enterprise admin settings, navigate to SSO/SCIM configuration and retrieve the SCIM base URL and bearer token.
- In the IdP (e.g., Okta), configure the Typeform SCIM app connector with the provided endpoint URL and token.
- Assign users/groups in the IdP; the IdP will call Typeform SCIM endpoints to provision, update, and deprovision users automatically.
- Test provisioning by assigning a test user in the IdP and verifying their appearance in Typeform.
Watch out for: SCIM endpoint URL is instance-specific and generated by Typeform; it is not a generic public URL. SSO must be fully configured before SCIM activation.
Why building this yourself is a trap
The most common integration trap is assuming the REST API provides full identity lifecycle control - it does not. There is no endpoint to create users, no admin-scoped user list, and no webhook for membership changes.
Any integration that needs to provision new Typeform accounts programmatically will hit a hard wall unless the org is on Enterprise with SCIM configured.
For teams building identity graph pipelines or connecting Typeform into a broader SaaS access model, the workspace-scoped member endpoints are the only REST surface available.
An MCP server with 60+ deep IT/identity integrations can normalize this workspace-member model into a unified identity graph alongside other SaaS tools, but the underlying API constraints - no cross-workspace user enumeration, no account creation, no lifecycle webhooks - remain and must be handled explicitly in any sync or reconciliation logic.
OAuth 2.0 tokens expire and require refresh token handling by the integrating application; Personal Access Tokens do not expire but carry the full permission scope of the generating user. Scope selection matters: requesting workspaces:write without accounts:read will allow workspace creation but block member listing.
Always validate scope combinations against the specific operations your integration requires before deploying.
Automate Typeform 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.