Skip to content
Start with Identity
Free tool · SCIM 2.0 · RFC 7643 / 7644

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 Created
    Body 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 Conflict
    userName (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 Request
    Missing 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 Unauthorized
    Missing 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.

What are you pasting?

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 schemas URI, and any extension used (such as the enterprise User extension) is listed too.
  • User has userName; Group has displayName; active is a JSON boolean; id is not sent on create.
  • PatchOp has an Operations array; 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", sends active as the string "False", and removes group members with a value array, unless the aadOptscim062020 flag 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

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.