Stitchflow
Vercel logo

Vercel 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

Vercel's REST API exposes full team member lifecycle management under the /v1/teams/{teamId}/members and /v2/teams/{teamId}/members endpoint families, authenticated via Bearer token (personal access token or OAuth 2.0). The API is versioned per-endpoint - v1 and v2 are not interchangeable across all operations - so callers must verify the correct version for each call.

Most member endpoints require the numeric teamId (team_xxx), not the team slug; retrieve it via GET /v2/teams before building any identity graph that maps Vercel membership to upstream directory records. Rate limits are communicated via X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp) headers; on 429, a Retry-After header is included.

Pro tokens are limited to approximately 3,000 requests/minute on general REST endpoints.

API quick reference

Has user APIYes
Auth methodBearer token (personal access token or OAuth 2.0 access token)
Base URLOfficial docs
SCIM availableYes
SCIM plan requiredEnterprise (native); Pro with SCIM add-on ($150/month)

Authentication

Auth method: Bearer token (personal access token or OAuth 2.0 access token)

Setup steps

  1. Navigate to Vercel Dashboard → Settings → Tokens to create a personal access token.
  2. Select token scope (full account or specific team) and expiration.
  3. Pass the token in the Authorization header: 'Authorization: Bearer '.
  4. For OAuth 2.0: register an integration at https://vercel.com/docs/integrations, implement the authorization code flow, and exchange the code for an access token at https://api.vercel.com/v2/oauth/access_token.

Required scopes

Scope Description Required for
team Read and write access to team settings and membership List, invite, update, and remove team members
user Read access to the authenticated user's profile GET /v2/user

User object / data model

Field Type Description On create On update Notes
uid string Unique user identifier system-generated immutable Used as path param in member endpoints
email string User's email address required (for invite) not updatable via API Used as invite target
username string Vercel username/handle optional read-only via team member API
name string Display name of the user optional read-only via team member API
avatar string Avatar image hash system-generated read-only Construct URL: https://vercel.com/api/www/avatar/
role string (enum) Team role: OWNER, MEMBER, DEVELOPER, BILLING, VIEWER required patchable OWNER role can only be set by existing owners
confirmed boolean Whether the user has confirmed their email system-set read-only
joinedFrom object Source of team join (e.g., invite, SAML, SCIM) system-set read-only Contains origin field
createdAt number (Unix ms) Timestamp when user joined the team system-set read-only
accessRequestedAt number (Unix ms) Timestamp of access request if pending system-set read-only

Core endpoints

Get authenticated user

  • Method: GET
  • URL: https://api.vercel.com/v2/user
  • Watch out for: Returns the token owner's profile only; not a directory of all users.

Request example

GET /v2/user
Authorization: Bearer <token>

Response example

{
  "user": {
    "uid": "usr_abc123",
    "email": "user@example.com",
    "username": "jdoe",
    "name": "Jane Doe"
  }
}

List team members

  • Method: GET
  • URL: https://api.vercel.com/v2/teams/{teamId}/members
  • Watch out for: Requires a team-scoped token or OAuth token with team access. Personal tokens on Hobby plan have no team context.

Request example

GET /v2/teams/team_xyz/members?limit=20
Authorization: Bearer <token>

Response example

{
  "members": [{"uid":"usr_1","email":"a@b.com","role":"MEMBER"}],
  "pagination": {"count":1,"next":null}
}

Invite user to team

  • Method: POST
  • URL: https://api.vercel.com/v1/teams/{teamId}/members
  • Watch out for: Sends an email invite; user is not active until they accept. SCIM-provisioned users bypass this flow.

Request example

POST /v1/teams/team_xyz/members
Content-Type: application/json

{"email":"new@example.com","role":"MEMBER"}

Response example

{
  "uid": "usr_new123",
  "username": null,
  "email": "new@example.com",
  "role": "MEMBER"
}

Update team member role

  • Method: PATCH
  • URL: https://api.vercel.com/v1/teams/{teamId}/members/{userId}
  • Watch out for: Only OWNER-role callers can promote another member to OWNER.

Request example

PATCH /v1/teams/team_xyz/members/usr_abc123
Content-Type: application/json

{"role":"DEVELOPER"}

Response example

{
  "uid": "usr_abc123",
  "role": "DEVELOPER"
}

Remove team member

  • Method: DELETE
  • URL: https://api.vercel.com/v1/teams/{teamId}/members/{userId}
  • Watch out for: Removing the last OWNER is blocked. SCIM-managed users should be deprovisioned via IdP, not this endpoint.

Request example

DELETE /v1/teams/team_xyz/members/usr_abc123
Authorization: Bearer <token>

Response example

{
  "id": "usr_abc123"
}

Get team member

  • Method: GET
  • URL: https://api.vercel.com/v2/teams/{teamId}/members/{userId}
  • Watch out for: userId can be the uid or username.

Request example

GET /v2/teams/team_xyz/members/usr_abc123
Authorization: Bearer <token>

Response example

{
  "uid": "usr_abc123",
  "email": "a@b.com",
  "role": "MEMBER",
  "confirmed": true
}

List access request (pending invites)

  • Method: GET
  • URL: https://api.vercel.com/v1/teams/{teamId}/request
  • Watch out for: Only returns users who requested access, not email-invited pending users.

Request example

GET /v1/teams/team_xyz/request
Authorization: Bearer <token>

Response example

{
  "accessRequests": [{"uid":"usr_pending","email":"p@b.com"}]
}

Join team (accept invite)

  • Method: POST
  • URL: https://api.vercel.com/v1/teams/{teamId}/members/teams/join
  • Watch out for: inviteCode is extracted from the invite email link. Not applicable for SCIM-provisioned users.

Request example

POST /v1/teams/team_xyz/members/teams/join
Content-Type: application/json

{"inviteCode":"<code>"}

Response example

{
  "uid": "usr_abc123",
  "role": "MEMBER"
}

Rate limits, pagination, and events

  • Rate limits: Vercel enforces per-token rate limits. Limits vary by plan and endpoint category. Rate limit state is communicated via response headers.
  • Rate-limit headers: Yes
  • Retry-After header: Yes
  • Rate-limit notes: Headers returned: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (Unix timestamp). On 429, Retry-After header is included. Exact per-endpoint limits are not fully published; the above are approximate general limits from community and official sources.
  • Pagination method: cursor
  • Default page size: 20
  • Max page size: 100
  • Pagination pointer: until (cursor from previous response pagination.next), limit
Plan Limit Concurrent
Hobby 60 requests/minute (general REST API) 0
Pro 3,000 requests/minute (general REST API) 0
Enterprise Higher limits negotiated; contact Vercel 0
  • Webhooks available: Yes
  • Webhook notes: Vercel supports webhooks for deployment and project events. There are no dedicated user/member lifecycle webhook events (e.g., member-added, member-removed) documented in the official REST API as of early 2025.
  • Alternative event strategy: Poll GET /v2/teams/{teamId}/members on a schedule to detect membership changes, or use SCIM provisioning events via your IdP.
  • Webhook events: deployment.created, deployment.succeeded, deployment.failed, deployment.cancelled, deployment.error, project.created, project.removed, integration-configuration.removed, domain.created

SCIM API status

  • SCIM available: Yes

  • SCIM version: 2.0

  • Plan required: Enterprise (native); Pro with SCIM add-on ($150/month)

  • Endpoint: https://api.vercel.com/scim/v2

  • Supported operations: GET /Users – list provisioned users, GET /Users/{id} – get single user, POST /Users – provision user, PUT /Users/{id} – replace user attributes, PATCH /Users/{id} – update user (activate/deactivate), DELETE /Users/{id} – deprovision user, GET /Groups – list groups (teams), POST /Groups – create group, PATCH /Groups/{id} – add/remove group members, DELETE /Groups/{id} – delete group

Limitations:

  • Requires SSO (SAML) to be configured before enabling SCIM.
  • Powered by WorkOS; supported IdPs are Okta, Microsoft Entra ID (Azure AD), and Google Workspace.
  • SCIM-provisioned users cannot be managed via the standard REST member endpoints without risk of sync conflicts.
  • Group-to-team mapping behavior depends on IdP group push configuration.
  • Role mapping from IdP groups to Vercel roles requires manual configuration in the Vercel dashboard.

Common scenarios

Three scenarios cover the majority of programmatic access management needs:

  • Invite and role-assign: POST /v1/teams/{teamId}/members with {"email": "user@example.com", "role": "DEVELOPER"}. The user is not active until they accept the email invite; poll GET /v2/teams/{teamId}/members filtering by email and confirmed=true to detect acceptance. Do not use this flow if SCIM is active - provision through the IdP to avoid sync conflicts.

  • Bulk audit: GET /v2/teams/{teamId}/members?limit=100, then paginate via the until cursor from pagination.next until exhausted. Collect uid, email, role, confirmed, joinedFrom.origin, and createdAt per member to build or refresh an identity graph against your directory of record. Default page size is 20; always set limit=100 to minimize round-trips.

  • SCIM deprovision (Enterprise or Pro add-on): Remove the user from the Vercel application assignment in your IdP (Okta, Entra ID, or Google Workspace). The IdP sends SCIM PATCH /Users/{id} with active=false or DELETE /Users/{id} to https://api.vercel.com/scim/v2. Verify via GET /v2/teams/{teamId}/members. Never call the REST DELETE member endpoint in parallel with SCIM - doing so can produce inconsistent state on the next IdP sync cycle.

Programmatically invite and assign a role to a new team member

  1. Obtain a team-scoped Bearer token from Vercel Dashboard → Settings → Tokens.
  2. Retrieve the teamId via GET https://api.vercel.com/v2/teams (match on slug).
  3. POST https://api.vercel.com/v1/teams/{teamId}/members with body {"email":"user@example.com","role":"DEVELOPER"}.
  4. User receives an email invite; poll GET /v2/teams/{teamId}/members filtering by email to confirm confirmed=true after acceptance.

Watch out for: The user is not active until they accept the invite. If SSO/SCIM is enabled, provision through the IdP instead to avoid sync conflicts.

Bulk-list and audit all team members

  1. GET https://api.vercel.com/v2/teams/{teamId}/members?limit=100.
  2. If pagination.next is non-null, repeat with ?until={pagination.next}&limit=100.
  3. Collect uid, email, role, confirmed, joinedFrom.origin, and createdAt for each member.
  4. Compare against your identity provider's directory to identify orphaned accounts.

Watch out for: Default page size is 20; always set limit=100 to minimize requests. Cursor-based pagination means you cannot jump to an arbitrary page.

Deprovision a user via SCIM (Enterprise/Pro add-on)

  1. Ensure SAML SSO and SCIM are configured in Vercel Dashboard → Settings → Security.
  2. In your IdP (Okta/Entra/Google Workspace), remove the user from the Vercel application assignment.
  3. The IdP sends a SCIM PATCH /Users/{id} with active=false (or DELETE /Users/{id}) to https://api.vercel.com/scim/v2.
  4. Verify removal by calling GET https://api.vercel.com/v2/teams/{teamId}/members and confirming the user is absent.

Watch out for: Do not also call the REST DELETE member endpoint; doing so while SCIM is active can cause inconsistent state on the next IdP sync cycle.

Why building this yourself is a trap

The most consequential caveat is SCIM/REST co-management: if SCIM is active, REST-side member changes may be silently overwritten on the next IdP sync. Teams that mix both management planes without a clear ownership boundary will encounter ghost memberships or unexpected re-provisioning. Establish a single authoritative plane before automating.

Webhooks do not cover member lifecycle events - there are no documented member-added or member-removed webhook triggers as of early 2025. Detecting membership changes programmatically requires polling GET /v2/teams/{teamId}/members on a schedule, which has rate limit implications at scale.

Personal access tokens carry the full permissions of the creating user and are not OAuth-scoped; treat them as high-privilege credentials and rotate on a defined schedule.

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