SSOGEN / Free tools / SCIM Tester: Build SCIM 2.0 Requests and Validate Responses
Free tool
SCIM Tester: Build SCIM 2.0 Requests and Validate Responses
A SCIM tester builds the HTTP requests a SCIM 2.0 client sends and checks the JSON a SCIM server returns. Build a request or paste a response below; checks follow RFC 7643 and RFC 7644 and run in your browser.
Test a SCIM endpoint here
- Build a request. Creates the raw HTTP request, the curl command, a
fetch()snippet and the JSON body for an operation. - Check a response. Validates a document a server returned.
- Fill in an Acme example. Shows both with sample data.
Off by default. When ticked, the Send button makes the one network request this tool can make. It goes from your browser straight to the base URL you entered, with your token, and never to ssogen.ai. It works only if that SCIM server allows cross-origin requests (CORS) from this site and answers the preflight check. Otherwise the browser blocks it; run the curl command instead.
Private by design. Building and checking run in this page and nothing is uploaded or logged. Use a test token from a test tenant: a token pasted here is held only in this page, but a production token does not belong in any web form. The Send button is the only feature that contacts a server, and only the one you type.
Free, in your browser: nothing is uploaded, and the only request the tool can make is the optional Send button, which you switch on yourself.
What a SCIM tester is
A SCIM tester exercises a SCIM service provider the way an identity provider or HR system would.
It sends the standard operations (create, read, list, replace, patch, delete) and checks that the answers follow the schema in RFC 7643 and the protocol in RFC 7644.
Mistakes in either surface as failed provisioning jobs that are hard to read from the client side.
This tester has two parts that work together:
- The builder. It produces correct requests, including URL-encoded filters and PatchOp bodies.
- The validator. It reads the answer and reports each rule it passes or breaks.
What the request builder produces
| Operation | Method and path | Notes |
|---|---|---|
| Create user | POST /Users |
Body carries the User schema URN and userName |
| Get user | GET /Users/{id} |
The id is issued by the server |
| List users | GET /Users?filter=... |
Optional filter, startIndex, count |
| Replace user | PUT /Users/{id} |
Sends the whole resource |
| Change user | PATCH /Users/{id} |
add, replace or remove in a PatchOp |
| Delete user | DELETE /Users/{id} |
Success is 204 with no body |
| Create group | POST /Groups |
displayName and optional members |
| Add or remove a member | PATCH /Groups/{id} |
add on members, or remove with a members[value eq "..."] path |
| Discovery | GET /ServiceProviderConfig, /Schemas, /ResourceTypes |
Shows what the server supports |
Every request carries Authorization: Bearer <token> and Accept: application/scim+json. A request with a body also carries Content-Type: application/scim+json.
A PatchOp body always has the schema urn:ietf:params:scim:api:messages:2.0:PatchOp and an Operations array. The remove operation requires a path; add and replace require a value.
By default the output shows a placeholder in place of the token ($SCIM_TOKEN in the curl command), so a copied command does not carry a secret.
Use a test token from a test tenant.
Build and check a SCIM filter
The filter parameter selects resources with the grammar in section 3.4.2.2 of RFC 7644.
The checker parses the expression with that grammar and reports the first error with its position. The builder adds conditions for you and encodes the result for the URL.
| Operator | Meaning |
|---|---|
eq, ne |
Equal, not equal |
co, sw, ew |
Contains, starts with, ends with |
pr |
The attribute has a value (takes no operand) |
gt, ge, lt, le |
Greater, greater or equal, less, less or equal |
and, or, not |
Logical operators; not requires parentheses |
( ), [ ] |
Grouping, and a filter inside a multi-valued attribute |
- Quoting. Strings use double quotes. Numbers,
true,falseandnullstay bare. - Case. Attribute names and operators are not case sensitive.
- Precedence.
notbinds tighter thanand, andandbinds tighter thanor.
The filter userName eq "maria.lopez@acme.example" becomes filter=userName%20eq%20%22maria.lopez%40acme.example%22 in the URL. Spaces, quotes, brackets and the at sign are all percent-encoded.
What the response validator checks
| Document | Checks |
|---|---|
| User | schemas contains the User URN; userName present; id and meta.resourceType on a server response; active is a boolean; emails and phoneNumbers have at most one primary: true; type values; no password in a response |
| Group | displayName present; each member has a value; $ref matches the member id |
| ListResponse | totalResults present; startIndex at least 1; itemsPerPage matches the page; Resources present when totalResults is not zero; every resource checked |
| Error | status is a string; it matches the HTTP status; scimType is a defined keyword |
| PatchOp | Schema URN; Operations array; valid op; path syntax; remove has a path |
| Discovery | ServiceProviderConfig flags and authentication schemes; ResourceType; Schema attribute definitions |
Attribute names are case-insensitive in SCIM, so Username is accepted with a warning that names the canonical spelling.
Optional inputs add protocol expectations: a create answers 201, a delete answers 204, and a PATCH answers 200 with the resource or 204 without a body.
Worked example: create a user at Acme
Build Create a user with the base URL https://scim.acme.example/v2. The tester prints this request:
POST /v2/Users HTTP/1.1Host: scim.acme.exampleAccept: application/scim+jsonAuthorization: Bearer <token>Content-Type: application/scim+json{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "maria.lopez@acme.example", "externalId": "E-10442", "name": { "givenName": "Maria", "familyName": "Lopez" }, "displayName": "Maria Lopez", "emails": [{ "value": "maria.lopez@acme.example", "type": "work", "primary": true }], "active": true}A correct server answers 201 Created and returns the same resource with an id and a meta object.
- Paste that answer into Check a response.
- Choose POST and enter 201.
A response that lacks id, returns "active": "true" as text, or marks two emails primary is reported as a problem with the rule that it breaks.
Send the request from your browser
The Send button is off until you tick Send this request from my browser.
- The call. It makes one
fetch()call from your browser to the base URL you typed. It never goes to ssogen.ai. - The result. The tester then validates the answer it receives.
A browser sends that call only if the SCIM server allows cross-origin requests. Because the call carries an Authorization header, the server must also answer the browser’s preflight OPTIONS request.
Most production SCIM servers do not, since identity providers call them from servers rather than browsers. When the browser blocks the call, run the curl command from a terminal and paste the body into the validator.
Mistakes the tester catches
startIndex=0. The index is 1-based, so the first page starts at 1.- A bare word in a filter, such as
userName eq maria. The value needs double quotes. - A
statusof409instead of"409"in an Error message. The standard defines it as a string. - A PATCH
removewith nopath, or anOperationskey spelledoperations. - A filter value sent unencoded, which breaks on spaces and quotes.
- Two emails with
primary: true. At most one value may be primary.
What the RFC examples contain
The RFC text is not always a clean test vector.
- Section 3.12 of RFC 7644. It prints an error example that lacks a comma after
scimType, so it is not valid JSON. - Section 7.5.2. It pairs HTTP 403 with a body
statusof"404". - Figure 4 of RFC 7643. It wraps long strings across lines and includes a
password, which the schema marks as never returned.
The tester reports each of these. Use the sample menu to load RFC 7643 sections 8.1 and 8.4 as clean vectors.
Use it with SSOGEN provisioning
SSOGEN offers a SCIM endpoint at https://<your host>/scim, authenticated with a bearer token created as a provisioning client in the Admin Console.
To test it:
- Enter that base URL and a client token.
- Send discovery requests.
- Send user requests.
The endpoint supports PATCH and filtering with eq on userName, externalId, emails.value and displayName. The steps are in inbound provisioning with SCIM.
What is a SCIM tester?
How do I test a SCIM endpoint?
What content type does SCIM use?
Is the SCIM startIndex zero-based or one-based?
How do I filter users in SCIM?
Why does my SCIM request fail when sent from the browser?
Where to go next
- Provisioning and sign-in. Read SCIM vs SAML for how they differ.
- The resource model. Read what SCIM provisioning is.
- Connect an HR system. Follow inbound provisioning with SCIM.
- Push accounts out. Use outbound provisioning.
- More tools. See the free SSO tools page.
Sources, all read 2026-10-27: RFC 7643, SCIM Core Schema (sections 3.1, 4.1, 8.1, 8.2, 8.4); RFC 7644, SCIM Protocol (sections 3.3, 3.4.2, 3.4.2.2, 3.5.2, 3.12, 7.5.2).