SCIM Request Builder
Generate the exact HTTP requests an identity provider sends to a SCIM 2.0 service: create a user, PATCH attributes, deactivate, search by userName, and change group membership. Each request is checked against RFC 7643 and RFC 7644, with the responses your server should return.
POST /scim/v2/Users HTTP/1.1
Host: api.example.com
Authorization: Bearer <token>
Accept: application/scim+json
Content-Type: application/scim+json
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
],
"externalId": "00u1a2b3c4d5e6f7g8h9",
"userName": "jane.doe@example.com",
"name": {
"givenName": "Jane",
"familyName": "Doe"
},
"emails": [
{
"value": "jane.doe@example.com",
"type": "work",
"primary": true
}
],
"active": true,
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"department": "Engineering"
}
}Validation against RFC 7643 / RFC 7644
0 problems, 0 warnings, 2 passed, 0 notes
- Passschemas includes 2.0:User
- PassuserName present
Expected responses
- 201 CreatedBody is the created resource with its server-assigned id; the Location header carries meta.location.
Example body
Content-Type: application/scim+json { "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User" ], "id": "2819c223-7f76-453a-919d-413861904646", "externalId": "00u1a2b3c4d5e6f7g8h9", "userName": "jane.doe@example.com", "name": { "givenName": "Jane", "familyName": "Doe" }, "emails": [ { "value": "jane.doe@example.com", "type": "work", "primary": true } ], "active": true, "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": { "department": "Engineering" }, "meta": { "resourceType": "User", "created": "2026-11-05T10:00:00Z", "lastModified": "2026-11-05T10:00:00Z", "location": "https://api.example.com/scim/v2/Users/2819c223-7f76-453a-919d-413861904646", "version": "W/\"3694e05e9dff590\"" } } - 409 ConflictuserName (or another unique attribute) already exists. IdPs then search for the user and link or update it.
Example body
Content-Type: application/scim+json { "schemas": [ "urn:ietf:params:scim:api:messages:2.0:Error" ], "scimType": "uniqueness", "detail": "userName is already in use", "status": "409" } - 400 Bad RequestMissing required attribute or bad value.
Example body
Content-Type: application/scim+json { "schemas": [ "urn:ietf:params:scim:api:messages:2.0:Error" ], "scimType": "invalidValue", "detail": "userName is required", "status": "400" } - 401 UnauthorizedMissing or invalid bearer token.
Validate your own request
Paste a body your IdP or client sent (for example from your SCIM server logs) or a filter expression.
How it works and what to check
SCIM is a REST protocol with two documents: RFC 7643 defines the User and Group resources and their attributes, RFC 7644 defines the endpoints, PATCH semantics, filtering and errors. Requests and responses use the application/scim+json media type. A provisioning integration mostly lives on five calls: search by userName or externalId, create, PATCH, deactivate and group membership PATCH.
What the validator checks
- Every body lists the right
schemasURI, and any extension used (such as the enterprise User extension) is listed too. - User has
userName; Group hasdisplayName;activeis a JSON boolean;idis not sent on create. - PatchOp has an
Operationsarray; each op is add, remove or replace; remove has a path; add and replace have a value, and a value object when there is no path. - Filters use a valid operator (eq, ne, co, sw, ew, gt, lt, ge, le, pr) and double-quoted strings.
Status codes your server should return
201 with the created resource for POST, 200 for GET and PUT, 200 with the resource or 204 for PATCH, 204 for DELETE, and 200 with an empty ListResponse when a filter matches nothing. Errors use the SCIM Error schema with a status string and, where relevant, a scimType such as uniqueness (409), invalidFilter, invalidPath, invalidValue or noTarget (400).
Documented IdP quirks
- Microsoft Entra ID sends
"op": "Replace","Add"and"Remove", sendsactiveas the string"False", and removes group members with a value array, unless theaadOptscim062020flag is added to the tenant URL. Microsoft lists these in its SCIM 2.0 compliance known issues. Toggle the Entra option above to generate those shapes and test your parser. - Okta uses PUT for most user updates on new Okta Integration Network apps, PATCH for activation, deactivation and group membership, and checks for an existing user with
filter=userName eq "...", per its SCIM 2.0 implementation guide. PUT replaces the whole resource, so attributes Okta does not send can be cleared.
For the admin side, see the SCIM provisioning recipe.
Related
- SCIM 2.0 standard guide
- What SCIM is
- Recipe: set up SCIM provisioning
- MFA matrix, which also records which SaaS apps offer SCIM
Frequently asked questions
- How do I deactivate a user with SCIM?
- Send PATCH /Users/{id} with the PatchOp schema and one operation: op replace, path active, value false. The server returns 200 with the resource or 204 No Content. Deactivation keeps the account for audit, unlike DELETE, and is what most identity providers send when a user is unassigned or disabled.
- What is the SCIM filter to find a user by userName?
- GET /Users?filter=userName eq "jane@example.com", URL-encoded. String values must be in double quotes. RFC 7643 defines userName as case-insensitive, and a query with no match must return 200 with totalResults 0, not 404.
- Why does Microsoft Entra ID send "Replace" with a capital R?
- Microsoft documents that its provisioning service sends capitalized op values (Add, Replace, Remove) and the string "False" for active unless the aadOptscim062020 feature flag is added to the tenant URL. A SCIM server that Entra connects to should compare op values case-insensitively and accept both booleans and "True"/"False" strings.
- Does Okta use PUT or PATCH for SCIM?
- Per Okta's SCIM 2.0 guide, for new Okta Integration Network apps Okta sends profile updates with PUT, which replaces the whole user, and uses PATCH for activation, deactivation and group membership. Custom App Integration Wizard apps use PUT for those as well. Support both methods.
- Does this tool send requests to my SCIM server?
- No. It only builds and validates request text in your browser. Copy the HTTP or curl output and run it yourself against a test tenant. Nothing you type is sent anywhere or stored.