Changelog#
[0.11.2] - 2026-10-02#
Fixed#
attributesandexcludedAttributesare 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
TestSCIMClientare added to the headers of itsenviron, instead of replacing them. Since 0.8, theIf-Matchheader ofreplace,modifyanddeletedropped headers such asAuthorization.
[0.11.0] - 2026-10-01#
Added#
Cursor-based pagination (RFC 9865). Pass
cursorinSearchRequestand read the next cursor innext_cursor. When the server advertises cursor pagination, a response withouttotalResultsis accepted. A response with an invalidnextCursororpreviousCursorraisesResponsePayloadValidationException.The
requestmethod 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,deleteandsearchcan be aResourceType, or its name or id. It reaches a resource type that serves the same schema as another one, such as/Employeesnext to/Users:query("Employee", "123"),create("Employee", user).searchthen sends the request to the endpoint of the resource type, and accepts a model too:search(User, request).The second argument of
query,modifyanddeletecan be a resource object instead of an id, as inquery("Employee", user). The query parameters, or the patch operation, may directly follow a resource object:query(user, parameters).createandreplaceread adictpayload with the model passed first:create(User, payload).BaseAsyncSCIMClientcan be imported fromscim2_client.query,search,createandreplaceare typed after their arguments.query(User, "123")gives aUser,query(User)aListResponse[User], andquery("Employee")aListResponse[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
ResourceTypeobject passed first designates its endpoint. To read a resource type from/ResourceTypes, passquery(ResourceType, "User").modifytakes the id before the patch operation:modify(User, "123", patch).modify(User, patch, id="123")raises aTypeError, pass the id first.create,replaceandsearchtake the resource type before the payload. Pass the parameters that follow the payload by keyword.The parameter of
resource_endpointis renamedtarget.Creations and replacements missing an extension that the resource type marks as required raise
InvalidValueExceptionbefore 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.modifyis removed. Use themodifymethod 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
dicttoqueryare sent to the server. They used to be dropped. An unknown parameter raises aSCIMException.createandreplaceraiseInvalidValueExceptionwhencheck_request_payloadisFalseand nourlis passed. Before, the httpx2 engine raised aTypeErrorand the Werkzeug engine sent the request to the SCIM prefix.A payload whose first schema is an extension raises
InvalidValueExceptionwith 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.resourceTypethat the client does not know also raises an error in 0.12.The
resourceparameter ofdeleteandmodifyis renamedtarget. 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
discoverfails, 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 withInvalidValueException.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.
InvalidServiceDescriptionExceptionis raised otherwise, including when a resource type has no endpoint.A response that is not a SCIM message raises
UnexpectedContentFormatExceptioninstead of anAttributeError, aTypeErroror aRecursionError: a body too deeply nested or holding an integer too long to decode, a JSON value that is not an object, orschemasthat are not a list of strings. The payload is still returned as sent when response checks are disabled.An
Errorobject that does not validate raisesResponsePayloadValidationException.discover()raises the errors the server returns and validates the objects it publishes, whateverraise_scim_errorsandcheck_response_payloadsay. A discovery endpoint answering without content raisesInvalidServiceDescriptionException.
[0.9.0] - 2026-09-21#
Added#
Support for bulk operations with
bulk(). #4 When theServiceProviderConfigis known, requests are checked against the bulk capabilities the server advertises, and a request the server would answer with a413is not sent.The service a client talks to is described by a
ScimProvider, passed asprovider. Two resource types built upon a same schema are told apart, soget_resource_model()andresource_endpoint()answer the model and the endpoint each one serves.The
ScimPolicytheprovidercarries rules the payloads the client reads and writes, so that a peer departing from the specification on one point can still be talked to.InvalidServiceDescriptionExceptionis 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 theproviderdoes not describe yet, where it used to replace everything it was given.A client given no
ResourceTypebuilds naive ones itself, where the endpoints used to be unknown untilregister_naive_resource_types()was called.
Deprecated#
The
resource_models,resource_typesandservice_provider_configparameters and attributes, in favor ofprovider. Will be removed in 1.0.register_naive_resource_types()andbuild_resource_models(), which aScimProviderdoes by itself. Will be removed in 1.0.
Removed#
Breaking: everything deprecated in 0.8.0.
The
httpxpackaging extra and thescim2_client.engines.httpxmodule. The engines require httpx2 and live inscim2_client.engines.httpx2. An application that cannot migrate all its dependencies at once can callhttpx2.alias_httpx()at the very top of its entrypoint, so thatimport httpxresolves to httpx2 process-wide.Passing a
httpx.Clientor ahttpx.AsyncClientto the request engines.The
resource_modelparameter ofquery,deleteandmodify. Pass the resource type or a resource object as the first parameter instead.The
search_requestparameter ofquery, replaced byquery_parameters.searchkeeps its ownsearch_requestparameter.The exceptions with a
*Errorsuffix, which pointed at their*Exceptioncounterparts.
[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 thehttpx2packaging extra. httpx is still used when httpx2 is not installed.query,deleteandmodifyalso accept aResourceobject in place of a resource type and an id. Objects without an id are rejected. #13replace,modifyanddeletesend anIf-Matchheader when the server advertises ETag support and the resource they are given carries a version. #47Resource versions are read from the
ETagresponse header when the server does not fill themeta.versionattribute. #47querysends anIf-None-Matchheader when it is given a versioned resource object and the server supports ETags. On a304 Not Modifiedanswer, the object that was passed is returned back. #47409is an expected status code fordelete, 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
Errorobjects now raiseSCIMExceptionsubclasses from scim2-models instead of scim2-client custom exceptions. #39
Deprecated#
The
resource_modelparameter ofquery,deleteandmodify, renamedtargetforqueryandresourcefor the two others, since it also accepts resource objects. Will be removed in 0.9.The
httpxpackaging extra, in favor of thehttpx2extra. Will be removed in 0.9.The
scim2_client.engines.httpxmodule, in favor ofscim2_client.engines.httpx2. Will be removed in 0.9.Passing a
httpx.Clientor ahttpx.AsyncClientto the request engines, in favor of their httpx2 counterparts. Will be removed in 0.9.The exceptions with a
*Errorsuffix, in favor of their*Exceptioncounterparts. The old names still point at the renamed classes, soexceptblocks written against them keep working. Will be removed in 0.9.
Removed#
Breaking:
SCIMRequestError,RequestPayloadValidationErrorandSCIMResponseErrorObject, which have no counterpart among the scim2-models exceptions. Code catching them must catchSCIMExceptioninstead, which is also what invalid request payloads and server errors now raise.
Fixed#
The
createandquerymethods 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
querymethod now acceptsResponseParametersin addition toSearchRequest.The
search_requestparameter ofqueryis renamed toquery_parameters. The old name is deprecated and will be removed in 0.9.
[0.7.3] - 2026-02-04#
Changed#
[0.7.2] - 2026-02-03#
Fixed#
Skip
Content-Typeheader validation for 204 responses. #34
[0.7.1] - 2026-01-25#
Fixed#
schemasis 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#
[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#
Added#
Add
clientandenvironTestSCIMClientparameters.
[0.4.3] - 2024-12-06#
Added#
Add
check_response_content_typeandcheck_response_status_codesparameters.
[0.4.2] - 2024-12-03#
Added#
discover()has parameters to select which objects to discover.
[0.4.1] - 2024-12-02#
Added#
TestSCIMClientcan handle absolute URLs.
Changed#
Avoid to initialize
resource_modelswith configuration resources.
[0.4.0] - 2024-12-02#
Warning
This version comes with breaking changes:
SCIMClienttakes a mandatoryresource_typesparameter.
Added#
Implement
register_naive_resource_types().Implement
discover()methods.
[0.3.3] - 2024-11-29#
Added#
TestSCIMClientraise aUnexpectedContentFormatexception when response is not JSON.
[0.3.2] - 2024-11-29#
Added#
Implement
SCIMClientcheck_request_payload,check_response_payloadandraise_scim_errorsparamibutes, to keep the same values for all the requests.
[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.SCIMClienthas moved toscim2_client.engines.httpx.SyncSCIMClient.The
resource_typesparameters has been renamedresource_models.
Added#
The Unknown resource type request error keeps a reference to the faulty payload.
New
TestSCIMClientrequest engine for application development purpose.New
scim2_client.engines.httpx.AsyncSCIMClientrequest 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#
[0.2.0] - 2024-09-01#
Added#
Replace
check_status_codeparameter byexpected_status_codes.
Changed#
raise_scim_errorsisTrueby default.
[0.1.11] - 2024-08-31#
Fixed#
[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#
SCIMResponseErrorObjectimplementation.
[0.1.5] - 2024-06-05#
Changed#
Merge
query()andquery_all.
Added#
Implement
delete()check_response_payload attribute.ServiceProviderConfig,ResourceTypeandSchemaare added to the default resource types list.Any custom URL can be used with all the
SCIMClientmethods.ResponsePayloadValidationErrorimplementation.RequestPayloadValidationErrorimplementation.RequestNetworkErrorimplementation.
Fixed#
Endpoint guessing for
ServiceProviderConfig.ServiceProviderConfigcannot have ids and are not returned inListResponse.
[0.1.4] - 2024-06-03#
Fixed#
resource_endpoint()could not correctly guess endpoints for resources with extensions.
[0.1.3] - 2024-06-03#
Added#
[0.1.2] - 2024-06-02#
Added#
check_response_payloadandcheck_status_codeparameters for all methods.check_request_payloadparameter 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