SCIM Filter Syntax¶
SCIM filters allow clients to query resources with attribute-based conditions as defined in RFC 7644 §3.4.2.
Basic syntax¶
URL encoding
Values must be URL-encoded when using HTTP. String values use double quotes. See URL encoding →
Comparison operators¶
| Operator | Meaning | Example |
|---|---|---|
eq |
Equal | userName eq "john.doe" |
ne |
Not equal | userName ne "admin" |
co |
Contains | displayName co "John" |
sw |
Starts with | userName sw "john" |
ew |
Ends with | emails.value ew "@acme.com" |
gt |
Greater than | id gt "5" |
ge |
Greater than or equal | id ge "5" |
lt |
Less than | id lt "10" |
le |
Less than or equal | id le "10" |
pr |
Present (has value) | phoneNumbers pr |
Logical operators¶
| Operator | Example |
|---|---|
and |
active eq true and userName sw "admin" |
or |
userName eq "john" or userName eq "jane" |
not |
not (active eq false) |
Examples¶
User filters¶
# Exact match on userName (Entra ID lookup pattern)
curl -H "Authorization: Bearer $TOKEN" \
"https://localhost:7001/scim/Users?filter=userName%20eq%20%22jane.doe%40acme.com%22"
# Active users only
curl -H "Authorization: Bearer $TOKEN" \
"https://localhost:7001/scim/Users?filter=active%20eq%20true"
# Active users with email domain
curl -H "Authorization: Bearer $TOKEN" \
"https://localhost:7001/scim/Users?filter=emails.value%20ew%20%22%40acme.com%22%20and%20active%20eq%20true"
# Exact match on userName (Entra ID lookup pattern)
filter=userName eq "jane.doe@acme.com"
# Active users only
filter=active eq true
# Users whose email ends with domain
filter=emails.value ew "@acme.com"
# Active users in engineering
filter=active eq true and title eq "Engineer"
# Users with given name present
filter=name.givenName pr
# Complex with grouping
filter=(active eq true) and (title eq "Manager" or title eq "Lead")
# All active users except service accounts
filter=active eq true and not (userName sw "svc-")
$headers = @{ Authorization = "Bearer $TOKEN" }
# Exact match on userName
$filter = 'userName eq "jane.doe@acme.com"'
$uri = "https://localhost:7001/scim/Users?filter=$([uri]::EscapeDataString($filter))"
Invoke-RestMethod -Uri $uri -Headers $headers
# Active users only
$filter = 'active eq true'
$uri = "https://localhost:7001/scim/Users?filter=$([uri]::EscapeDataString($filter))"
Invoke-RestMethod -Uri $uri -Headers $headers
Group filters¶
# Exact group name (Entra ID lookup pattern)
filter=displayName eq "Engineering Team"
# Groups containing "Admin" in the name
filter=displayName co "Admin"
# Groups starting with "Team"
filter=displayName sw "Team"
Pagination¶
# First page, 50 items
GET /scim/Users?filter=active%20eq%20true&startIndex=1&count=50
# Second page
GET /scim/Users?filter=active%20eq%20true&startIndex=51&count=50
Pagination rules
startIndexis 1-based (not 0-based)- Default
count: 100 - Maximum recommended: 1000
URL encoding¶
Filters must be URL-encoded in HTTP requests. Common encodings:
| Character | Encoded |
|---|---|
| space | %20 |
" |
%22 |
@ |
%40 |
( |
%28 |
) |
%29 |
# Original: filter=emails.value ew "@acme.com" and active eq true
# Encoded: filter=emails.value%20ew%20%22%40acme.com%22%20and%20active%20eq%20true
curl -H "Authorization: Bearer $TOKEN" \
"https://localhost:7001/scim/Users?filter=emails.value%20ew%20%22%40acme.com%22%20and%20active%20eq%20true"
PowerShell auto-encodes filters
Response format¶
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 150,
"itemsPerPage": 50,
"startIndex": 1,
"Resources": [
{
"id": "user-001",
"userName": "jane.doe@acme.com",
"displayName": "Jane Doe",
"active": true,
"emails": [
{ "value": "jane.doe@acme.com", "type": "work", "primary": true }
],
"meta": {
"resourceType": "User",
"created": "2024-01-15T10:00:00Z",
"lastModified": "2024-03-01T09:00:00Z",
"location": "/scim/Users/user-001"
}
}
]
}
Error responses¶
Invalid filter syntax — 400 Bad Request¶
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail": "Invalid filter syntax: unexpected character at position 12",
"status": 400
}
How filters map to your entity¶
EzSCIM uses [ScimProperty] annotations to resolve SCIM attribute names to C# property names.
public class Employee
{
[ScimProperty("userName", "string")]
public string Email { get; set; } // SCIM: userName → C#: Email
[ScimProperty("active", "boolean")]
public bool IsEnabled { get; set; } // SCIM: active → C#: IsEnabled
}
SCIM filter: active eq true and userName co "@acme.com"
LINQ: e => e.IsEnabled == true && e.Email.Contains("@acme.com")
SQL: WHERE IsEnabled = 1 AND Email LIKE '%@acme.com%'
Implementation notes¶
Behavior details
- String comparisons via
co,sw,eware case-insensitive by default (SQLLIKE) - Attribute names are case-sensitive per SCIM spec (
userName≠UserName) prgenerates.IsNotNull()/.IsNotEmpty()in LINQ- Nested attributes (e.g.
name.givenName,emails.value) require the property's[ScimProperty]name to include the dot notation ("name.givenName")