Changelog#

[0.11.2] - 2026-10-02#

Fixed#

  • attributes and excludedAttributes are sent in the query string as comma-separated values, per RFC 7644 Section 3.9. They used to be sent as repeated parameters, and some servers only read the first value.

[0.11.1] - 2026-10-01#

Fixed#

  • The headers of a request sent by TestSCIMClient are added to the headers of its environ, instead of replacing them. Since 0.8, the If-Match header of replace, modify and delete dropped headers such as Authorization.

[0.11.0] - 2026-10-01#

Added#

  • Cursor-based pagination (RFC 9865). Pass cursor in SearchRequest and read the next cursor in next_cursor. When the server advertises cursor pagination, a response without totalResults is accepted. A response with an invalid nextCursor or previousCursor raises ResponsePayloadValidationException.

  • The request method sends a raw request and returns the response of the HTTP library, without any SCIM processing. This helps to check how a server behaves, for instance with an unsupported HTTP method.

  • The first argument of query, create, replace, modify, delete and search can be a ResourceType, or its name or id. It reaches a resource type that serves the same schema as another one, such as /Employees next to /Users: query("Employee", "123"), create("Employee", user). search then sends the request to the endpoint of the resource type, and accepts a model too: search(User, request).

  • The second argument of query, modify and delete can be a resource object instead of an id, as in query("Employee", user). The query parameters, or the patch operation, may directly follow a resource object: query(user, parameters).

  • create and replace read a dict payload with the model passed first: create(User, payload).

  • BaseAsyncSCIMClient can be imported from scim2_client.

  • query, search, create and replace are typed after their arguments. query(User, "123") gives a User, query(User) a ListResponse[User], and query("Employee") a ListResponse[Resource].

Changed#

  • A model goes to the resource type named after its schema, and a resource object to the resource type in its meta.resourceType, instead of the first resource type serving the schema.

  • A ResourceType object passed first designates its endpoint. To read a resource type from /ResourceTypes, pass query(ResourceType, "User").

  • modify takes the id before the patch operation: modify(User, "123", patch). modify(User, patch, id="123") raises a TypeError, pass the id first.

  • create, replace and search take the resource type before the payload. Pass the parameters that follow the payload by keyword.

  • The parameter of resource_endpoint is renamed target.

  • Creations and replacements missing an extension that the resource type marks as required raise InvalidValueException before the request is sent.

  • The responses are read with the model of the resource type, extensions included, even when the request was made with the bare model.

  • scim2-models 0.10.1 is now the minimum supported version.

  • The package is checked with mypy in strict mode. The annotations of check_response() now match what it returns.

  • SCIMClient.modify is removed. Use the modify method of the synchronous or asynchronous clients.

  • An engine only has to implement request. The base clients perform every operation with it. Engines that implement the operations themselves keep working.

Fixed#

  • Query parameters given as a dict to query are sent to the server. They used to be dropped. An unknown parameter raises a SCIMException.

  • create and replace raise InvalidValueException when check_request_payload is False and no url is passed. Before, the httpx2 engine raised a TypeError and the Werkzeug engine sent the request to the SCIM prefix.

  • A payload whose first schema is an extension raises InvalidValueException with a clearer message.

  • Resources read from a resource type that shares its schema with another one are written back to their own resource type, instead of the first one serving the schema.

Deprecated#

  • A model with no resource type named after its schema, or whose resource type of that name does not serve it, still goes to a resource type serving its schema. Pass the resource type instead. This raises an error in 0.12. A meta.resourceType that the client does not know also raises an error in 0.12.

  • The resource parameter of delete and modify is renamed target. Will be removed in 0.12.

  • modify(User, patch, "123"), with the patch operation before the id. Pass the id first. Will be removed in 0.12.

[0.10.0] - 2026-09-27#

Changed#

  • Python 3.11 is now the minimum supported version.

Fixed#

  • When a query of the asynchronous discover fails, the failures of the other queries are no longer reported by asyncio as never retrieved.

Security#

  • Resource ids are percent-encoded as a single path segment, so an id holding /, .., ? or #, including one sent back by the server, can no longer lead a request to another resource, another resource type or outside of the base URL. The . and .. ids are refused with InvalidValueException.

  • The endpoints of the resource types must stay under the base URL of the client, with the same origin and the same path prefix, and without query nor fragment. A server can no longer send the requests of the client, and the credentials they carry, to another host. InvalidServiceDescriptionException is raised otherwise, including when a resource type has no endpoint.

  • A response that is not a SCIM message raises UnexpectedContentFormatException instead of an AttributeError, a TypeError or a RecursionError: a body too deeply nested or holding an integer too long to decode, a JSON value that is not an object, or schemas that are not a list of strings. The payload is still returned as sent when response checks are disabled.

  • An Error object that does not validate raises ResponsePayloadValidationException.

  • discover() raises the errors the server returns and validates the objects it publishes, whatever raise_scim_errors and check_response_payload say. A discovery endpoint answering without content raises InvalidServiceDescriptionException.

[0.9.0] - 2026-09-21#

Added#

  • Support for bulk operations with bulk(). #4 When the ServiceProviderConfig is known, requests are checked against the bulk capabilities the server advertises, and a request the server would answer with a 413 is not sent.

  • The service a client talks to is described by a ScimProvider, passed as provider. Two resource types built upon a same schema are told apart, so get_resource_model() and resource_endpoint() answer the model and the endpoint each one serves.

  • The ScimPolicy the provider carries rules the payloads the client reads and writes, so that a peer departing from the specification on one point can still be talked to.

  • InvalidServiceDescriptionException is raised when the objects a server publishes do not describe a coherent service, where the incoherence used to pass unnoticed.

Changed#

  • scim2-models 0.8.0 is the minimum supported version.

  • discover() only queries what the provider does not describe yet, where it used to replace everything it was given.

  • A client given no ResourceType builds naive ones itself, where the endpoints used to be unknown until register_naive_resource_types() was called.

Deprecated#

Removed#

  • Breaking: everything deprecated in 0.8.0.

  • The httpx packaging extra and the scim2_client.engines.httpx module. The engines require httpx2 and live in scim2_client.engines.httpx2. An application that cannot migrate all its dependencies at once can call httpx2.alias_httpx() at the very top of its entrypoint, so that import httpx resolves to httpx2 process-wide.

  • Passing a httpx.Client or a httpx.AsyncClient to the request engines.

  • The resource_model parameter of query, delete and modify. Pass the resource type or a resource object as the first parameter instead.

  • The search_request parameter of query, replaced by query_parameters. search keeps its own search_request parameter.

  • The exceptions with a *Error suffix, which pointed at their *Exception counterparts.

[0.8.0] - 2026-09-20#

Added#

  • The network request engines are built upon httpx2, which is maintained, and live in scim2_client.engines.httpx2. They are shipped in the httpx2 packaging extra. httpx is still used when httpx2 is not installed.

  • query, delete and modify also accept a Resource object in place of a resource type and an id. Objects without an id are rejected. #13

  • replace, modify and delete send an If-Match header when the server advertises ETag support and the resource they are given carries a version. #47

  • Resource versions are read from the ETag response header when the server does not fill the meta.version attribute. #47

  • query sends an If-None-Match header when it is given a versioned resource object and the server supports ETags. On a 304 Not Modified answer, the object that was passed is returned back. #47

  • 409 is an expected status code for delete, as RFC7644 §3.12 defines it for every write operation.

Changed#

  • scim2-models 0.8 is not supported yet, and 0.7.0 is now the minimum supported version.

  • Breaking: invalid requests and server Error objects now raise SCIMException subclasses from scim2-models instead of scim2-client custom exceptions. #39

Deprecated#

  • The resource_model parameter of query, delete and modify, renamed target for query and resource for the two others, since it also accepts resource objects. Will be removed in 0.9.

  • The httpx packaging extra, in favor of the httpx2 extra. Will be removed in 0.9.

  • The scim2_client.engines.httpx module, in favor of scim2_client.engines.httpx2. Will be removed in 0.9.

  • Passing a httpx.Client or a httpx.AsyncClient to the request engines, in favor of their httpx2 counterparts. Will be removed in 0.9.

  • The exceptions with a *Error suffix, in favor of their *Exception counterparts. The old names still point at the renamed classes, so except blocks written against them keep working. Will be removed in 0.9.

Removed#

  • Breaking: SCIMRequestError, RequestPayloadValidationError and SCIMResponseErrorObject, which have no counterpart among the scim2-models exceptions. Code catching them must catch SCIMException instead, which is also what invalid request payloads and server errors now raise.

Fixed#

  • The create and query methods attach the server response to the exceptions they raise, as the other methods do, instead of the request payload.

[0.7.5] - 2026-04-02#

Fixed#

  • Werkzeug engine now correctly serializes list query parameters (attributes, excludedAttributes).

[0.7.4] - 2026-04-02#

Changed#

  • The query method now accepts ResponseParameters in addition to SearchRequest.

  • The search_request parameter of query is renamed to query_parameters. The old name is deprecated and will be removed in 0.9.

[0.7.3] - 2026-02-04#

Changed#

  • SCIMResponseErrorObject now exposes a to_error() method returning the Error object from the server. #37

[0.7.2] - 2026-02-03#

Fixed#

  • Skip Content-Type header validation for 204 responses. #34

[0.7.1] - 2026-01-25#

Fixed#

  • schemas is no longer included in GET query parameters per RFC 7644 §3.4.2.

[0.7.0] - 2026-01-25#

Added#

  • Support for Python 3.14.

  • Compatibility with scim2-models 0.6.

Removed#

  • Support for Python 3.9.

[0.6.1] - 2025-08-01#

Fixed#

  • Discovery for models with several extensions. #30 #32

[0.6.0] - 2025-07-23#

Fixed#

  • Add support for PATCH operations with modify().

[0.5.2] - 2025-07-17#

Fixed#

  • Minor extension typing issue.

[0.5.1] - 2024-12-08#

Changed#

  • Check response return codes after the error state. This helps providing more useful error messages.

[0.5.0] - 2024-12-06#

Warning

This version comes with breaking changes:

Added#

[0.4.3] - 2024-12-06#

Added#

[0.4.2] - 2024-12-03#

Added#

  • discover() has parameters to select which objects to discover.

[0.4.1] - 2024-12-02#

Added#

Changed#

[0.4.0] - 2024-12-02#

Warning

This version comes with breaking changes:

Added#

[0.3.3] - 2024-11-29#

Added#

  • TestSCIMClient raise a UnexpectedContentFormat exception when response is not JSON.

[0.3.2] - 2024-11-29#

Added#

[0.3.1] - 2024-11-29#

Fixed#

  • Some variables were missing from the SCIM exception classes.

[0.3.0] - 2024-11-29#

Warning

This version comes with breaking changes:

  • httpx is no longer a direct dependency, it is shipped in the httpx packaging extra.

  • scim2_client.SCIMClient has moved to scim2_client.engines.httpx.SyncSCIMClient.

  • The resource_types parameters has been renamed resource_models.

Added#

  • The Unknown resource type request error keeps a reference to the faulty payload.

  • New TestSCIMClient request engine for application development purpose.

  • New scim2_client.engines.httpx.AsyncSCIMClient request engine. #1

Changed#

  • Separate httpx network code and SCIM code in separate file as a basis for async support (and other request engines).

[0.2.2] - 2024-11-12#

Added#

  • Mypy type checking and py.typed file #25

[0.2.1] - 2024-11-07#

Added#

  • Python 3.13 support.

Fixed#

  • RequestPayloadValidationError error message.

  • Don’t crash when servers don’t return content type headers. #22, #24

[0.2.0] - 2024-09-01#

Added#

  • Replace check_status_code parameter by expected_status_codes.

Changed#

  • raise_scim_errors is True by default.

[0.1.11] - 2024-08-31#

Fixed#

  • Support for content-types with charset information. #18, #19

[0.1.10] - 2024-08-18#

Changed#

  • Bump to scim2-models 0.2.0.

[0.1.9] - 2024-06-30#

Changed#

  • Fix httpx dependency versions.

[0.1.8] - 2024-06-30#

Changed#

  • Lower the httpx dependency to 0.24.0

[0.1.7] - 2024-06-28#

Fixed#

  • Support for scim2-models 0.1.8

[0.1.6] - 2024-06-05#

Added#

  • SCIMResponseErrorObject implementation.

[0.1.5] - 2024-06-05#

Changed#

Added#

  • Implement delete() check_response_payload attribute.

  • ServiceProviderConfig, ResourceType and Schema are added to the default resource types list.

  • Any custom URL can be used with all the SCIMClient methods.

  • ResponsePayloadValidationError implementation.

  • RequestPayloadValidationError implementation.

  • RequestNetworkError implementation.

Fixed#

[0.1.4] - 2024-06-03#

Fixed#

[0.1.3] - 2024-06-03#

Added#

[0.1.2] - 2024-06-02#

Added#

  • check_response_payload and check_status_code parameters for all methods.

  • check_request_payload parameter for all methods.

[0.1.1] - 2024-06-01#

Added#

  • Use of scim2-models request contexts to produce adequate payloads.

[0.1.0] - 2024-06-01#

Added#

  • Initial release