Advanced UnSpot Plan from $100 $50 for Your Company Fix this Price

Promo deadline:
Help center / Administration / Integrations / User sync / External API: User sync via SCIM

External API: User sync via SCIM

UnSpot provides a SCIM 2.0 (System for Cross-domain Identity Management, RFC 7643/7644) API for automated user provisioning. Identity providers such as Microsoft Entra ID or Okta use it out of the box, but you can also call it directly from your own scripts and HR systems. This page is the API reference: every endpoint, its parameters, and ready-to-run examples. For connecting an identity provider step by step, see User sync with Microsoft 360 (Azure AD / Entra ID) SCIM API.

Base URL and authentication

When you enable SCIM in Administration > Access > Integrations > SCIM, UnSpot shows your personal base URL and a secret token:

Base URL:  https://<your-company-domain>/api/scim
Token:     <64-character secret>

Every request must include the token in the Authorization header:

Authorization: Bearer <token>

For POST, PUT and PATCH requests the Content-Type: application/scim+json header is required — any other value returns 415 Unsupported Media Type (Content-Type must be application/scim+json).

  • 401 Access denied — the header is missing, not in Bearer <token> format, or the token is wrong.
  • 400 Token is expired — the token validity period has passed; update it in the SCIM settings.

Resources at a glance

ResourceEndpointsWhat it is for
UsersGET/POST /Users, GET/PUT/PATCH/DELETE /Users/{id}, POST /Users/{id}/avatarCreate, read, update, deactivate and delete UnSpot accounts
GroupsGET/POST /Groups, GET/PUT/PATCH/DELETE /Groups/{id}Manage UnSpot groups and their membership
OrgUnitsPUT /OrgUnitsReplace the whole organizational structure tree
SchemasGET /SchemasMachine-readable description of all supported attributes

Pagination

List endpoints (/Users, /Groups) accept count (page size, default 20, maximum 1000) and startIndex (1-based index of the first result). Responses use the standard SCIM ListResponse envelope with totalResults, startIndex and itemsPerPage.

Users

List users — GET /Users

Returns all users of your workspace, including deactivated ones. Use it to audit provisioning or find a user’s UnSpot id.

Query parameterTypeDescription
countintegerPage size. Default 20, max 1000.
startIndexinteger1-based index of the first result.
filterstringOnly the form userName eq "email@example.com" is supported. Any other filter returns 400 Filter syntax error.
curl -H "Authorization: Bearer $TOKEN" \
  "https://acme.unspot.com/api/scim/Users?count=50&startIndex=1"

curl -G -H "Authorization: Bearer $TOKEN" \
  --data-urlencode 'filter=userName eq "jane.doe@example.com"' \
  https://acme.unspot.com/api/scim/Users

Response 200:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
  "totalResults": 128,
  "startIndex": 1,
  "itemsPerPage": 50,
  "Resources": [ { ...user objects, see below... } ]
}

Create a user — POST /Users

Creates an account. userName is the user’s email and must be unique. If the email belongs to an archived user, the account is restored instead of created. If the welcome email option is enabled in the SCIM settings, the new user receives an invitation.

Body attributeRequiredDescription
schemasyesMust contain urn:ietf:params:scim:schemas:core:2.0:User (plus the Unspot extension URN if you send extension attributes).
userNameyesEmail address, used for login.
name.givenName / name.familyNameyesFirst and last name.
externalIdnoYour system’s identifier, up to 36 characters, unique.
titlenoJob title.
activenoDefault true. false creates a deactivated account.
phoneNumbersnoArray; only the first element with type: "work" is used.
urn:...:enterprise:2.0:Usernodepartment and manager.value (manager’s UnSpot id or email).
urn:...:Unspot:2.0:Usernorole, orgUnit (overrides department), employeeId, numberPass, attendance (0–100).
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
  https://acme.unspot.com/api/scim/Users \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "jane.doe@example.com",
    "name": { "givenName": "Jane", "familyName": "Doe" },
    "title": "Product Manager",
    "externalId": "00u1abcd2EFGH3ij4x5",
    "active": true
  }'

Response 201 — the created user:

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "id": "5f1c9d2e-...-a1b2",
  "userName": "jane.doe@example.com",
  "name": { "givenName": "Jane", "familyName": "Doe", "formatted": "Jane Doe" },
  "active": true,
  "title": "Product Manager",
  "externalId": "00u1abcd2EFGH3ij4x5",
  "phoneNumbers": [ { "type": "work", "value": "+1 555 0100" } ],
  "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
    "department": "Product",
    "manager": { "value": "8a2b...-uuid", "displayName": "John Smith" }
  },
  "urn:ietf:params:scim:schemas:extension:Unspot:2.0:User": {
    "role": "user", "orgUnit": "Company/Product", "employeeId": "E-1042", "attendance": 60
  },
  "meta": { "resourceType": "User", "created": "2026-01-15T09:30:00.000Z", "lastModified": "2026-06-02T11:00:00.000Z" }
}
  • 409 This userName is already used — an active account with this email already exists.
  • 409 This externalId is already used — the externalId is taken.

Get a user — GET /Users/{id}

Returns one user by UnSpot id (UUID). Response 200 — the same user object as above.

curl -H "Authorization: Bearer $TOKEN" \
  https://acme.unspot.com/api/scim/Users/5f1c9d2e-...-a1b2

Replace a user — PUT /Users/{id}

Full update: send the complete user representation (same body as create). Attributes you omit are cleared. For partial changes prefer PATCH. Response 200 — the updated user.

Update user attributes — PATCH /Users/{id}

Partial update in the standard SCIM PatchOp format. This is what identity providers use to change a single field or deactivate a user.

curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
  https://acme.unspot.com/api/scim/Users/5f1c9d2e-...-a1b2 \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      { "op": "replace", "path": "title", "value": "Head of Product" },
      { "op": "replace", "path": "active", "value": false }
    ]
  }'

Supported path values and operations:

pathreplaceaddremove
name.givenName, name.familyName, userName
active
externalId, title, phoneNumbers[type eq "work"].value
urn:...:enterprise:2.0:User:department / :manager
urn:...:Unspot:2.0:User:orgUnit / :attendance
urn:...:Unspot:2.0:User:role / :numberPass / :employeeId
  • Setting active: false deactivates the user (bookings and access are blocked); true reactivates. Deactivation is ignored for administrators.
  • manager accepts a UnSpot user id (UUID) or an email.
  • An unsupported path or operation returns 400 with an explanation.

Response 200 — the updated user.

Delete a user — DELETE /Users/{id}

Removes the account from the workspace. Response 204 No Content. To temporarily block a user, use PATCH with active: false instead.

curl -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://acme.unspot.com/api/scim/Users/5f1c9d2e-...-a1b2

Upload an avatar — POST /Users/{id}/avatar

Sets the user’s profile photo. multipart/form-data with a file field: JPEG or PNG, up to 100 KB. Response 200.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -F "file=@avatar.png" \
  https://acme.unspot.com/api/scim/Users/5f1c9d2e-...-a1b2/avatar

Groups

List groups — GET /Groups

Returns workspace groups. Same pagination as /Users. Response 200, ListResponse of group objects:

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "id": "9c3d...-uuid",
  "displayName": "Product team",
  "externalId": "okta-grp-42",
  "meta": { "resourceType": "Group", "created": "...", "lastModified": "..." }
}

Create a group — POST /Groups

Creates a group, optionally with members (members[].value = user ids). displayName must be unique (max 255 characters). Unknown member id returns 404; duplicate displayName/externalId returns 409. Response 201.

curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
  https://acme.unspot.com/api/scim/Groups \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
    "displayName": "Product team",
    "members": [ { "value": "5f1c9d2e-...-a1b2" } ]
  }'

Get / replace / patch / delete a group

  • GET /Groups/{id} — one group, response 200.
  • PUT /Groups/{id} — full replace (displayName required, members = array of user ids), response 204.
  • PATCH /Groups/{id} — PatchOp; supported paths: displayName (replace), externalId (replace, add), members (add, replace, remove). Response 204.
  • DELETE /Groups/{id} — response 204.
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
  https://acme.unspot.com/api/scim/Groups/9c3d...-uuid \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      { "op": "add", "path": "members", "value": [ { "value": "5f1c9d2e-...-a1b2" } ] }
    ]
  }'

Organizational structure

Replace the org structure — PUT /OrgUnits

Replaces the whole department tree in one call. Each item is a node identified by its full path (levels separated by /, up to 4000 characters), with an optional manager (email) and description (max 255).

curl -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/scim+json" \
  https://acme.unspot.com/api/scim/OrgUnits \
  -d '{
    "items": [
      { "path": "Acme", "manager": "ceo@example.com" },
      { "path": "Acme/Product", "manager": "cpo@example.com", "description": "Product org" },
      { "path": "Acme/Product/Design" }
    ]
  }'

Response 200. Users are attached to org units via the orgUnit extension attribute (or department).

Schemas

GET /Schemas

Returns machine-readable definitions of all supported resources and attributes, including the UnSpot extension (urn:ietf:params:scim:schemas:extension:Unspot:2.0:User: role, numberPass, orgUnit, employeeId, attendance, read-only workMode). Useful for IdP connectors that discover attributes automatically.

Errors

Errors are returned as JSON with an explanatory message. Common status codes:

CodeMeaningTypical causes
400Bad requestInvalid schema URN, unsupported filter or PATCH path, expired token, validation errors
401Access deniedMissing or invalid Bearer token
404Not foundUnknown user/group id, unknown member in members
409ConflictDuplicate userName, externalId or displayName

Leave a request for a call and we will contact you

Loading