Summary and recommendation
Sentry exposes a REST API at https://sentry.io/api/0 and a SCIM 2.0 endpoint at https://sentry.io/scim/v2/. Authentication uses Bearer tokens - either a User Auth Token or an Internal Integration Token - with explicit scope requirements per operation: member:read for reads, member:write for invites and role changes, org:admin for destructive operations and SCIM token generation.
The SCIM token is provisioned separately under Settings > Auth > SCIM Setup and is not interchangeable with standard API tokens. Both surfaces are relevant when building an identity graph that maps Sentry organization membership, team assignments, and role state back to a canonical user directory.
API quick reference
| Has user API | Yes |
| Auth method | Bearer token (User Auth Token or Internal Integration Token) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Business or Enterprise (SAML SSO must be configured first) |
Authentication
Auth method: Bearer token (User Auth Token or Internal Integration Token)
Setup steps
- Navigate to Settings > Account > API > Auth Tokens in the Sentry UI.
- Click 'Create New Token' and select the required scopes (e.g., member:read, member:write, org:read).
- Copy the generated token; it is shown only once.
- Pass the token in the Authorization header: 'Authorization: Bearer
'. - For organization-level automation, create an Internal Integration under Settings > Developer Settings > New Internal Integration and assign scopes there.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| member:read | Read organization member list and individual member details. | GET /organizations/{org_slug}/members/ |
| member:write | Invite, update role, or remove organization members. | POST/PUT/DELETE /organizations/{org_slug}/members/ |
| org:read | Read organization-level metadata. | GET /organizations/{org_slug}/ |
| org:write | Modify organization settings. | PUT /organizations/{org_slug}/ |
| org:admin | Full administrative access including member management and SSO settings. | Destructive member operations, SCIM token generation |
| team:read | Read team membership. | GET /organizations/{org_slug}/teams/ |
| team:write | Add or remove members from teams. | POST/DELETE /organizations/{org_slug}/teams/{team_slug}/members/ |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique member ID within the organization. | system-assigned | immutable | Used as path parameter for member-specific operations. |
| string | Email address of the member. | required | not updatable via REST (use SCIM) | Used as the invite target. | |
| role | string | Organization-level role: member, admin, manager, owner, billing. | optional (defaults to member) | updatable | Roles are organization-scoped, not project-scoped. |
| orgRole | string | Alias for role in newer API responses. | optional | updatable | Prefer orgRole in API v0 responses. |
| teamRoles | array | List of team slugs and per-team roles assigned to the member. | optional | updatable | Each entry: {teamSlug, role}. |
| pending | boolean | True if the member invitation has not yet been accepted. | system-assigned | read-only | Pending members count against seat limits on paid plans. |
| expired | boolean | True if the invitation link has expired. | system-assigned | read-only | |
| user | object|null | Nested user object with name, username, avatarUrl, dateJoined, etc. Null if invite is still pending. | system-assigned | read-only | Contains user.id (global Sentry user ID), user.email, user.name. |
| inviterName | string|null | Display name of the member who sent the invitation. | system-assigned | read-only | |
| dateCreated | string (ISO 8601) | Timestamp when the membership record was created. | system-assigned | read-only | |
| flags | object | Boolean flags such as sso:linked, sso:invalid, idp:provisioned, idp:role-restricted. | system-assigned | read-only | idp:provisioned=true indicates the member was created via SCIM/SSO. |
| projects | array | List of project slugs the member has explicit access to. | optional | updatable |
Core endpoints
List organization members
- Method: GET
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/ - Watch out for: Returns cursor-paginated results. Pending (unaccepted) invites are included in the list.
Request example
GET /api/0/organizations/my-org/members/
Authorization: Bearer <token>
Response example
[
{
"id": "123",
"email": "alice@example.com",
"role": "member",
"pending": false,
"user": {"id": "456", "name": "Alice"}
}
]
Get a single organization member
- Method: GET
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/{member_id}/ - Watch out for: Use the member ID (not the global user ID) as the path parameter.
Request example
GET /api/0/organizations/my-org/members/123/
Authorization: Bearer <token>
Response example
{
"id": "123",
"email": "alice@example.com",
"role": "member",
"teamRoles": [{"teamSlug": "backend", "role": "contributor"}],
"flags": {"sso:linked": true}
}
Invite a new member
- Method: POST
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/ - Watch out for: Sends an invitation email. The member is pending until they accept. Requires member:write scope. On SSO-enforced orgs, the user must log in via SSO to activate.
Request example
POST /api/0/organizations/my-org/members/
Authorization: Bearer <token>
Content-Type: application/json
{"email":"bob@example.com","role":"member","teams":["backend"]}
Response example
{
"id": "789",
"email": "bob@example.com",
"role": "member",
"pending": true
}
Update a member's role or teams
- Method: PUT
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/{member_id}/ - Watch out for: Cannot downgrade the last owner. Role changes take effect immediately.
Request example
PUT /api/0/organizations/my-org/members/123/
Authorization: Bearer <token>
Content-Type: application/json
{"role":"admin","teamRoles":[{"teamSlug":"backend","role":"admin"}]}
Response example
{
"id": "123",
"role": "admin",
"teamRoles": [{"teamSlug": "backend", "role": "admin"}]
}
Remove a member from the organization
- Method: DELETE
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/{member_id}/ - Watch out for: Irreversible via API. The user loses access immediately. Cannot delete the sole owner.
Request example
DELETE /api/0/organizations/my-org/members/123/
Authorization: Bearer <token>
Response example
HTTP 204 No Content
List teams
- Method: GET
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/teams/ - Watch out for: Cursor-paginated. Use team slug (not ID) in subsequent team-member endpoints.
Request example
GET /api/0/organizations/my-org/teams/
Authorization: Bearer <token>
Response example
[
{"id": "1", "slug": "backend", "name": "Backend", "memberCount": 5}
]
Add member to a team
- Method: POST
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/{member_id}/teams/{team_slug}/ - Watch out for: Uses member_id (org-scoped), not global user ID. Returns updated member object.
Request example
POST /api/0/organizations/my-org/members/123/teams/backend/
Authorization: Bearer <token>
Response example
{
"id": "123",
"teams": ["backend"]
}
Remove member from a team
- Method: DELETE
- URL:
https://sentry.io/api/0/organizations/{organization_slug}/members/{member_id}/teams/{team_slug}/ - Watch out for: Returns 200 (not 204) with updated member object on success.
Request example
DELETE /api/0/organizations/my-org/members/123/teams/backend/
Authorization: Bearer <token>
Response example
HTTP 200 OK
{"id": "123", "teams": []}
Rate limits, pagination, and events
- Rate limits: Sentry enforces per-token and per-organization rate limits. Limits vary by endpoint category. The API returns HTTP 429 when limits are exceeded.
- Rate-limit headers: Yes
- Retry-After header: Yes
- Rate-limit notes: Sentry returns X-Sentry-Rate-Limit and Retry-After headers on 429 responses. Exact numeric limits are not publicly documented per plan tier. Respect Retry-After before retrying.
- Pagination method: cursor
- Default page size: 100
- Max page size: 100
- Pagination pointer: cursor
| Plan | Limit | Concurrent |
|---|---|---|
| All plans (default) | ~100 requests per 10 seconds per token (documented as a general guideline; exact limits not publicly specified per plan) | 0 |
- Webhooks available: Yes
- Webhook notes: Sentry supports webhooks via Internal Integrations and the Sentry integration platform. Webhooks fire on issue, error, and workflow events but do not natively emit user/member lifecycle events (invite accepted, member removed).
- Alternative event strategy: Poll GET /organizations/{org_slug}/members/ on a schedule to detect membership changes. For provisioning events, use SCIM with an IdP that supports push groups.
- Webhook events: issue.created, issue.resolved, issue.assigned, issue.ignored, error.created, comment.created, comment.updated, comment.deleted, metric_alert.open, metric_alert.resolved
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Business or Enterprise (SAML SSO must be configured first)
Endpoint: https://sentry.io/scim/v2/
Supported operations: GET /Users - list provisioned users, POST /Users - provision a new user, GET /Users/{id} - retrieve a user, PATCH /Users/{id} - update user attributes or deactivate (active=false), DELETE /Users/{id} - deprovision a user, GET /Groups - list teams as SCIM groups, POST /Groups - create a team, GET /Groups/{id} - retrieve a team, PATCH /Groups/{id} - add/remove members from a team, DELETE /Groups/{id} - delete a team
Limitations:
- SCIM is only available on Business and Enterprise plans.
- SAML SSO must be fully configured before enabling SCIM.
- Not available on Trial plans.
- SCIM token is a separate token generated under Settings > Auth > SCIM - not a standard API auth token.
- PATCH /Users supports only active attribute for deprovisioning; full attribute updates are limited.
- JIT (Just-In-Time) provisioning via SSO creates users on first login independently of SCIM.
- SCIM Groups map to Sentry Teams; group display names must match existing team slugs or a new team is created.
- Deprovisioning sets active=false but does not immediately delete the member record in all IdP flows.
Common scenarios
Three automation scenarios cover the majority of lifecycle operations.
Bulk invitations require member:write scope; POST to /api/0/organizations/{org_slug}/members/ with role and teams array per user, then poll the returned member_id for pending status - on SSO-enforced orgs, acceptance happens via SSO login, not the email link. Role promotion (e.
g. , Member → Admin) uses PUT to /api/0/organizations/{org_slug}/members/{member_id}/ with a lowercase role string; tokens from callers without owner or manager org role receive a 403.
Deprovisioning via SCIM is the preferred offboarding path: the IdP sends PATCH /scim/v2/Users/{id} with active=false, revoking access immediately - but if the user was JIT-provisioned via SSO without a prior SCIM push, the SCIM user ID may not exist and the fallback is DELETE /api/0/organizations/{org_slug}/members/{member_id}/ via REST.
Bulk invite new team members and assign to a team
- Authenticate with a token scoped to member:write and team:read.
- GET /api/0/organizations/{org_slug}/teams/ to retrieve the target team slug.
- For each user email, POST /api/0/organizations/{org_slug}/members/ with {email, role: 'member', teams: [team_slug]}.
- Store the returned member id for each invite.
- Poll GET /api/0/organizations/{org_slug}/members/{member_id}/ to check pending status until accepted.
Watch out for: Each invite sends an email. On SSO-enforced orgs, users must accept via SSO login, not the email link directly.
Deprovision a departing employee via SCIM
- Ensure SCIM is configured in the IdP (Okta/Entra) pointing to https://sentry.io/scim/v2/ with the SCIM Bearer token.
- In the IdP, remove the user from the Sentry application assignment.
- The IdP sends PATCH /scim/v2/Users/{id} with {op: replace, path: active, value: false}.
- Sentry deactivates the member, revoking access immediately.
- Verify by calling GET /api/0/organizations/{org_slug}/members/ and confirming the member no longer appears or is marked inactive.
Watch out for: If JIT provisioning was used (user logged in via SSO without SCIM push), the SCIM user ID may not exist; fall back to DELETE /api/0/organizations/{org_slug}/members/{member_id}/ via REST API.
Promote a member to admin role
- Authenticate with a token scoped to member:write and org:admin.
- GET /api/0/organizations/{org_slug}/members/ to find the target member's id.
- PUT /api/0/organizations/{org_slug}/members/{member_id}/ with body {"role": "admin"}.
- Confirm the response returns role: 'admin'.
Watch out for: Only users with 'owner' or 'manager' role can promote others to 'admin'. Tokens from users without sufficient org role will receive a 403.
Why building this yourself is a trap
Several non-obvious behaviors create integration risk. Member IDs are organization-scoped integers distinct from the global user.id nested in the user object - conflating them breaks lookups and corrupts identity graph joins between Sentry membership records and canonical directory profiles.
Pagination uses Link header cursor values, not page or offset parameters; implementations that ignore the Link: rel="next" header will silently truncate results on large orgs. Rate limits return HTTP 429 with Retry-After and X-Sentry-Rate-Limit headers, but exact per-plan numeric thresholds are not publicly documented - exponential backoff is required.
Webhooks do not emit member lifecycle events (invite accepted, member removed), so membership state must be derived by polling GET /organizations/{org_slug}/members/ on a schedule or by consuming SCIM push events from the IdP.
Finally, the Owner role is fully excluded from SCIM management; any workflow that assumes SCIM covers all role transitions will silently leave Owner assignments unmanaged.
Automate Sentry 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.