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.
Which part of the tester to use
Filter (RFC 7644 section 3.4.2.2)

Add a condition to the expression:

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, false and null stay bare.
  • Case. Attribute names and operators are not case sensitive.
  • Precedence. not binds tighter than and, and and binds tighter than or.

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.1
Host: scim.acme.example
Accept: application/scim+json
Authorization: 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.

  1. Paste that answer into Check a response.
  2. 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 status of 409 instead of "409" in an Error message. The standard defines it as a string.
  • A PATCH remove with no path, or an Operations key spelled operations.
  • 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 status of "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:

  1. Enter that base URL and a client token.
  2. Send discovery requests.
  3. 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?
A SCIM tester is a tool that sends SCIM 2.0 requests to a service provider and checks the answers against RFC 7643 and RFC 7644. It confirms that create, read, patch and delete calls work and that the returned JSON uses the correct schema URNs, attribute types and error format.
How do I test a SCIM endpoint?
Start with GET /ServiceProviderConfig to see what the server supports. Then create a test user with POST /Users, read it back, change it with PATCH, filter for it and delete it. Check each answer: status code, schemas, id, and meta. Use a test tenant and a test token.
What content type does SCIM use?
SCIM defines the media type application/scim+json. Send it as Content-Type on requests with a body and as Accept on requests. Many servers also accept application/json, but a strict server can refuse a request that does not use the SCIM media type, so the tester always uses it.
Is the SCIM startIndex zero-based or one-based?
The startIndex is one-based. RFC 7644 defines it as the 1-based index of the first result, so the first page of a list uses startIndex=1. A server that returns startIndex 0 in a ListResponse breaks the standard, and a client that sends 0 may get an error or an empty page.
How do I filter users in SCIM?
Add a filter query parameter to GET /Users with an attribute, an operator and a quoted value, for example filter=userName eq “maria.lopez@acme.example”. Percent-encode the whole expression. Operators include eq, co, sw, pr, and, or and not. A server may support only some operators and answers 400 invalidFilter for the rest.
Why does my SCIM request fail when sent from the browser?
Browsers enforce cross-origin rules. The SCIM server must answer the preflight OPTIONS request and allow the Authorization header from this origin. Most do not, because identity providers call SCIM from servers. The request itself is usually fine, so run the curl command from a terminal instead.

Where to go next

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).