SCIM 2.0 reference
Every SCIM 2.0 endpoint, filter, response shape, and deprovision rule — the complete reference for what your identity provider can send and expect back.
For setup and identity-provider walkthroughs, see SCIM provisioning.
Base URL and auth
https://chgrkvftjfibufoopmav.supabase.co/functions/v1All requests except schema discovery require Authorization: Bearer tqc_scim_…. The tenant is resolved from the token — see authentication.
Endpoints
| Operation | Method | Path | Success |
|---|---|---|---|
| List users | GET | /scim-users | 200 |
| Read user | GET | /scim-users/{id} | 200 |
| Create user | POST | /scim-users | 201 |
| Replace user | PUT | /scim-users/{id} | 200 |
| Patch user | PATCH | /scim-users/{id} | 200 |
| Deprovision user | DELETE | /scim-users/{id} | 204 |
| List groups | GET | /scim-groups | 200 |
| Read group | GET | /scim-groups/{id} | 200 |
| Create group | POST | /scim-groups | 201 |
| Replace group | PUT | /scim-groups/{id} | 200 |
| Patch group / members | PATCH | /scim-groups/{id} | 200 |
| Delete group | DELETE | /scim-groups/{id} | 204 |
| Service provider config | GET | /scim-schemas/ServiceProviderConfig | 200 (no auth) |
| Resource types | GET | /scim-schemas/ResourceTypes | 200 (no auth) |
| Schemas | GET | /scim-schemas/Schemas | 200 (no auth) |
Provision a user
Create a user with POST /scim-users. The body is a SCIM User resource sent as application/scim+json; a successful create returns 201 with the stored resource, including its server-assigned id.
curl https://chgrkvftjfibufoopmav.supabase.co/functions/v1/scim-users \
-H "Authorization: Bearer tqc_scim_…" \
-H "Content-Type: application/scim+json" \
-d '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "alice@acme.com",
"name": { "givenName": "Alice", "familyName": "Janssen" },
"emails": [{ "value": "alice@acme.com", "primary": true }],
"externalId": "00u1abcd2EFGHIJKL345",
"active": true
}'const res = await fetch(
'https://chgrkvftjfibufoopmav.supabase.co/functions/v1/scim-users',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.TQC_SCIM_TOKEN}`,
'Content-Type': 'application/scim+json',
},
body: JSON.stringify({
schemas: ['urn:ietf:params:scim:schemas:core:2.0:User'],
userName: 'alice@acme.com',
name: { givenName: 'Alice', familyName: 'Janssen' },
emails: [{ value: 'alice@acme.com', primary: true }],
externalId: '00u1abcd2EFGHIJKL345',
active: true,
}),
},
);
const created = await res.json(); // 201 — the stored User, with server idimport os
import requests
res = requests.post(
"https://chgrkvftjfibufoopmav.supabase.co/functions/v1/scim-users",
headers={
"Authorization": f"Bearer {os.environ['TQC_SCIM_TOKEN']}",
"Content-Type": "application/scim+json",
},
json={
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "alice@acme.com",
"name": {"givenName": "Alice", "familyName": "Janssen"},
"emails": [{"value": "alice@acme.com", "primary": True}],
"externalId": "00u1abcd2EFGHIJKL345",
"active": True,
},
)
created = res.json() # 201 — the stored User, with server idA duplicate userName or externalId returns 409 with scimType: uniqueness.
Filters
List endpoints accept the subset that mainstream identity providers emit: userName eq, externalId eq, id eq, active eq true|false, emails eq, emails.value eq, and the bracketed emails[type eq "work"].value eq form (the selector is treated as the inner attribute). Groups additionally support displayName eq, members eq, and members.value eq.
curl -G https://chgrkvftjfibufoopmav.supabase.co/functions/v1/scim-users \
--data-urlencode 'filter=userName eq "alice@acme.com"' \
-H "Authorization: Bearer tqc_scim_…"const url = new URL(
'https://chgrkvftjfibufoopmav.supabase.co/functions/v1/scim-users',
);
url.searchParams.set('filter', 'userName eq "alice@acme.com"');
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.TQC_SCIM_TOKEN}` },
});
const list = await res.json(); // SCIM ListResponseimport os
import requests
res = requests.get(
"https://chgrkvftjfibufoopmav.supabase.co/functions/v1/scim-users",
params={"filter": 'userName eq "alice@acme.com"'},
headers={"Authorization": f"Bearer {os.environ['TQC_SCIM_TOKEN']}"},
)
listing = res.json() # SCIM ListResponseUnsupported filters return:
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "400",
"detail": "Filter not supported: …",
"scimType": "invalidFilter"
}Response shapes
List responses follow RFC 7644 ListResponse:
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 1,
"startIndex": 1,
"itemsPerPage": 1,
"Resources": [
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"id": "5f3a…",
"userName": "alice@acme.com",
"name": { "givenName": "Alice", "familyName": "Janssen" },
"displayName": "Alice Janssen",
"emails": [{ "value": "alice@acme.com", "primary": true }],
"externalId": "00u1abcd2EFGHIJKL345",
"active": true,
"meta": {
"resourceType": "User",
"created": "2026-01-15T09:12:00Z",
"lastModified": "2026-06-01T14:03:00Z",
"location": "https://…/scim-users/5f3a…"
}
}
]
}The enterprise user extension (urn:ietf:params:scim:schemas:extension:enterprise:2.0:User) is accepted, stored, and returned verbatim; only the core attributes above project onto platform profiles.
Deprovision semantics
DELETE /scim-users/{id} returns 204 and:
- Removes the SCIM binding for the user — subsequent SCIM
GETfor that id returns404, per RFC 7644. - Suspends the underlying account; sign-in is blocked.
- Retains the profile for audit. Deprovisioning is not data erasure — see GDPR for deletion.
PATCH with active: false suspends without removing the binding; active: true reactivates.
Errors
| HTTP | scimType | Cause |
|---|---|---|
| 401 | invalidCredentials | Missing, revoked, expired, or wrong-tenant token |
| 400 | invalidValue | Missing userName on create or patch |
| 400 | invalidFilter | Unsupported filter expression |
| 400 | invalidSyntax | Malformed PATCH Operations array |
| 409 | uniqueness | userName or externalId already provisioned |
| 429 | — | Per-token limit (1,200/hour) exceeded — see rate limits |
Not supported
Bulk operations (/Bulk), password synchronization (by design — passwords are never copied across the wire), and SCIM v1.
GET /scim-users?count=1 with your token returns a ListResponse with an integer totalResults.
Rate limits
Know exactly what a 429 means here, why authentication surfaces fail closed, and how to retry so your integration recovers cleanly.
Webhooks
Build a receiver that verifies signatures, acknowledges fast, and survives retries — everything delivery expects from your endpoint, with working code.

