Summary and recommendation
Wiz exposes a GraphQL-only API for user management - there is no REST surface.
All operations are HTTP POST to the single tenant-specific endpoint https://api.<tenant>.wiz.io/graphql, authenticated via OAuth 2.0 client credentials obtained from auth.app.wiz.io (not the tenant subdomain).
The user object includes id, name, email, role (enum), identityProviderType, createdAt, lastLoginAt, and isActive.
Pagination is cursor-based using pageInfo.endCursor, with a maximum page size of 500.
Wiz does not publicly document rate limit thresholds or expose Retry-After headers;
contact Wiz support for tenant-specific limits.
For teams building an identity graph across cloud security tooling, Wiz's user and role data - particularly identityProviderType and project-scoped role assignments - are the fields that anchor cross-system identity correlation.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 client credentials (service account) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise |
Authentication
Auth method: OAuth 2.0 client credentials (service account)
Setup steps
- Navigate to Settings > Service Accounts in the Wiz portal.
- Create a new service account and assign the required API scopes.
- Note the Client ID and Client Secret.
- POST to https://auth.app.wiz.io/oauth/token with grant_type=client_credentials, client_id, client_secret, and audience=wiz-api to obtain a Bearer token.
- Include the Bearer token in the Authorization header for all GraphQL API requests.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| read:users | Read user accounts and their attributes. | Listing and retrieving user details via GraphQL |
| write:users | Create, update, and delete user accounts. | User provisioning and deprovisioning via GraphQL |
| read:service_accounts | Read service account details. | Listing service accounts |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique Wiz-assigned user identifier. | system-generated | immutable | Used as the primary key in GraphQL queries. |
| name | string | Full display name of the user. | required | optional | |
| string | User's email address; used as login identifier. | required | optional | Must be unique within the tenant. | |
| role | enum | Wiz RBAC role assigned to the user (e.g., GlobalAdmin, ProjectReader). | required | optional | Role names are tenant-configurable; built-in roles documented in Wiz RBAC docs. |
| identityProviderType | enum | Authentication provider type (e.g., SAML, LOCAL). | optional | optional | |
| createdAt | datetime | ISO 8601 timestamp of user creation. | system-generated | immutable | |
| lastLoginAt | datetime | ISO 8601 timestamp of last login. | system-generated | system-managed | |
| isActive | boolean | Whether the user account is active. | defaults to true | optional | Set to false to deactivate without deleting. |
Core endpoints
List Users
- Method: POST
- URL:
https://api.<tenant>.wiz.io/graphql - Watch out for: All API calls are GraphQL POSTs to the same endpoint; use pageInfo.endCursor for cursor-based pagination.
Request example
{
"query": "query { users(first: 100) { nodes { id name email role { name } isActive } pageInfo { endCursor hasNextPage } } }"
}
Response example
{
"data": {
"users": {
"nodes": [{"id":"usr-123","name":"Jane Doe","email":"jane@example.com","role":{"name":"GlobalReader"},"isActive":true}],
"pageInfo": {"endCursor":"abc123","hasNextPage":false}
}
}
}
Get User by ID
- Method: POST
- URL:
https://api.<tenant>.wiz.io/graphql - Watch out for: Returns null in data.user if the ID does not exist rather than an HTTP 404.
Request example
{
"query": "query { user(id: \"usr-123\") { id name email role { name } isActive createdAt } }"
}
Response example
{
"data": {
"user": {"id":"usr-123","name":"Jane Doe","email":"jane@example.com","role":{"name":"GlobalReader"},"isActive":true,"createdAt":"2024-01-15T10:00:00Z"}
}
}
Create User
- Method: POST
- URL:
https://api.<tenant>.wiz.io/graphql - Watch out for: Role must match an existing Wiz role name exactly; invalid role names return a GraphQL error, not an HTTP error.
Request example
{
"query": "mutation { createUser(input: {name:\"Jane Doe\", email:\"jane@example.com\", role:\"GlobalReader\"}) { user { id name email } } }"
}
Response example
{
"data": {
"createUser": {
"user": {"id":"usr-456","name":"Jane Doe","email":"jane@example.com"}
}
}
}
Update User
- Method: POST
- URL:
https://api.<tenant>.wiz.io/graphql - Watch out for: Only fields included in the input object are updated; omitted fields retain their current values.
Request example
{
"query": "mutation { updateUser(id:\"usr-456\", input: {role:\"ProjectAdmin\"}) { user { id role { name } } } }"
}
Response example
{
"data": {
"updateUser": {
"user": {"id":"usr-456","role":{"name":"ProjectAdmin"}}
}
}
}
Delete User
- Method: POST
- URL:
https://api.<tenant>.wiz.io/graphql - Watch out for: Deletion is permanent. Consider deactivating (isActive: false) instead for audit trail preservation.
Request example
{
"query": "mutation { deleteUser(id:\"usr-456\") { _stub } }"
}
Response example
{
"data": {
"deleteUser": {"_stub": null}
}
}
List Service Accounts
- Method: POST
- URL:
https://api.<tenant>.wiz.io/graphql - Watch out for: Client secrets are only shown once at creation time and cannot be retrieved again via API.
Request example
{
"query": "query { serviceAccounts(first: 50) { nodes { id name scopes createdAt } pageInfo { endCursor hasNextPage } } }"
}
Response example
{
"data": {
"serviceAccounts": {
"nodes": [{"id":"sa-789","name":"CI Pipeline SA","scopes":["read:users"],"createdAt":"2024-03-01T00:00:00Z"}],
"pageInfo": {"endCursor":null,"hasNextPage":false}
}
}
}
Rate limits, pagination, and events
Rate limits: Wiz does not publicly document specific rate limit thresholds or tiers in official docs as of this research.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: No explicit rate limit values, headers, or Retry-After behavior documented publicly. Contact Wiz support for tenant-specific limits.
Pagination method: cursor
Default page size: 500
Max page size: 500
Pagination pointer: after (endCursor from pageInfo)
Webhooks available: No
Webhook notes: Wiz does not publicly document a webhook system for user-management events as of this research.
Alternative event strategy: Poll the GraphQL API on a schedule to detect user changes, or use SCIM provisioning events managed by your IdP.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise
Endpoint: https://api.
.wiz.io/scim/v2 Supported operations: GET /Users, GET /Users/{id}, POST /Users, PUT /Users/{id}, PATCH /Users/{id}, DELETE /Users/{id}, GET /Groups, POST /Groups, PATCH /Groups/{id}, DELETE /Groups/{id}
Limitations:
- SSO must be configured and active before SCIM provisioning can be enabled.
- Enterprise plan required; not available on lower tiers.
- SCIM token is generated within Wiz Settings and must be provided as a Bearer token to the IdP connector.
- Tenant-specific subdomain must be used in the SCIM base URL; a generic shared URL does not exist.
- Group push maps to Wiz user groups; role assignment via SCIM group membership depends on Wiz RBAC configuration.
Common scenarios
Three primary automation scenarios are supported by the API.
For direct provisioning, POST a createUser GraphQL mutation with name, email, and role;
the role value must exactly match a role name defined in your tenant - mismatches return a GraphQL error with HTTP 200, not an HTTP 4xx.
For IdP-driven bulk sync, use SCIM 2.0 at https://api.
SSO must be fully active before SCIM can be enabled, and the SCIM token is shown only once at generation.
For deprovisioning a departed user, prefer an updateUser mutation setting isActive: false over deleteUser - deactivation preserves audit history, while deletion is permanent and removes the user record entirely.
In all cases, GraphQL errors (invalid input, permission denied) are returned with HTTP 200 inside an errors array;
always inspect the response body, not just the HTTP status code.
Provision a new user via GraphQL API
- Obtain a Bearer token via POST to https://auth.app.wiz.io/oauth/token with client_credentials grant.
- POST a createUser GraphQL mutation to https://api.
.wiz.io/graphql with name, email, and role in the input. - Capture the returned user.id for future reference.
- Verify creation by querying the user by ID.
Watch out for: The role value must exactly match a role name defined in your Wiz tenant; mismatches return a GraphQL error with HTTP 200.
Bulk-sync users from an IdP using SCIM
- Confirm SSO is active in Wiz Settings.
- Navigate to Settings > SCIM Provisioning and generate a SCIM token.
- In your IdP (e.g., Okta, Entra ID), configure a SCIM 2.0 connector with base URL https://api.
.wiz.io/scim/v2 and the generated Bearer token. - Map IdP user attributes to Wiz SCIM attributes (userName → email, displayName → name).
- Enable provisioning and run an initial sync; monitor IdP provisioning logs for errors.
Watch out for: SCIM token is shown only once at generation; store it securely. Re-generating invalidates the previous token immediately.
Deactivate a departed user
- Obtain a Bearer token with write:users scope.
- Query users by email to retrieve the user's id.
- POST an updateUser mutation setting isActive: false for the retrieved id.
- Optionally, revoke any service accounts associated with the user separately.
Watch out for: Deactivation (isActive: false) preserves audit history; deleteUser is permanent and removes the user record.
Why building this yourself is a trap
The most common integration failure points with the Wiz API are schema and token assumptions. GraphQL mutation and query names are not guaranteed to be identical across tenant versions - always validate against your tenant's introspection endpoint rather than assuming field names from documentation.
The OAuth token endpoint (auth.app.wiz.io) is separate from the GraphQL endpoint (api.
over-broad scope requests may be rejected by tenant policy, and the principle of least privilege is enforced.
Finally, if SCIM and manual portal management are used simultaneously, removing a user only in the portal while SCIM is active will result in re-provisioning on the next IdP sync - deprovisioning must be initiated from the IdP to be durable.
Automate Wiz 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.