Users and credentials

Identity Store API

Stores the identities (users) of a tenant and the schema that describes their attributes. Every other service that needs a user looks it up here.

https://{tenant-host}/identity-store/api/v1audience identity-store18 operations
Last checked against a live tenant: 28 October 2026checked live called on a tenantfrom source read in the service codenot confirmed not confirmed

When to use it

  • Create, read, update or delete users from a backend or an IO flow.
  • Search users by attribute: user name, email, any attribute marked searchable.
  • Add a custom attribute to the user schema before a flow stores it.

Connect

Base URL
https://{tenant-host}/identity-store/api/v1
Token
POST https://{tenant-host}/oauth/v1/token with grant_type=client_credentials. The client ID and secret go in the form body.checked live
Client to create
Access admin → Web clients → a client with the grant type Client credentials. Not an API client: those are only for Access's own configuration API.checked live
Default audiences
must include identity-storechecked live
Default scopes
One of the scopes each operation lists below. Keep the client's scopes, joined with spaces, within 1024 characters: past that Access fails to issue tokens.checked live
curl -s https://{tenant-host}/oauth/v1/token \
  -d grant_type=client_credentials \
  -d client_id=$CLIENT_ID \
  -d client_secret=$CLIENT_SECRET

curl -s "https://{tenant-host}/identity-store/api/v1/identities?pageSize=5&filter=isSoftDeleted%20eq%20false" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Operations

Open an operation to see its parameters and code, and send it to your tenant. The token needs any one of the listed scopes.

Connect to your tenant

Then open any operation below and send it.

Sends grant_type=client_credentials to https://{tenant-host}/oauth/v1/token through this site's server. The secret and token stay in this tab only; host and client ID are remembered.

What trips people up

PATCH returns 200 with the identity, not 204

from source

Older references say 204. The service returns the updated identity with HTTP 200, so read the body instead of discarding it.

PATCH takes an object with operations, not a bare JSON Patch array

from source

Send {"operations":[{"op":"replace","path":"displayName","value":"New name"}]}. op is add, remove or replace.

PUT resets what you leave out

from source

PUT replaces the identity: attributes you omit can fall back to their schema defaults. Use PATCH for a partial change.

name and displayName are not system attributes any more

from source

They moved to the custom attributes map. Read the tenant schema (GET /config/data-model/identity) before deciding which attributes to send.

Sort is "<attribute> asc|desc", not a minus prefix

checked live

sort=userName asc works. sort=-userName returns 400 IDS-400.

Only searchable attributes can be filtered

checked live

Filters accept eq, ne, co, sw, ew, gt, ge, lt, le, pr with and / or and parentheses, e.g. isSoftDeleted eq false and (userName co "sar" or emails.value co "sar"). An attribute without isSearchable: true returns 400.

Contains and starts-with can be case-sensitive

checked live

co / sw / ew follow the attribute's isCaseSensitive flag in the schema. On tenants where userName and emails.value are case-sensitive, search a few casings or lower-case the value you store.

Filter out soft-deleted users in the query

checked live

Add isSoftDeleted eq false to the filter. Filtering afterwards makes totalElements and totalPages wrong. totalPages is 0 when nothing matches.

pageSize in the reply is the number of items returned

from source

Keep the page size you asked for yourself. Use pageNumber or startIndex (both start at 1), never both.

A search can succeed with a different filter

from source

With an OR in the filter, an invalid id or status clause can be dropped instead of failing. The reply then carries warnings (IDS-WARN-…) and the filter actually applied. Check warnings before trusting the result.

Errors

Error bodies carry id (trace id), code, message and details. 401 and 403 come from the security layer and have no IDS code.

400IDS-400Invalid argument or state, including unknown or not-searchable filter attributes.
404IDS-404Identity or primary contact not found. A PATCH on a soft-deleted identity also returns 404.
409IDS-409Duplicate value on a unique attribute. Wins over 400 when validation collects both.
412IDS-412Canonical schema missing.
500IDS-500Unexpected failure. Quote the id field (trace id) when you report it.

When a call fails

ReplyMeansWhat to change
The service answers 401The token lacks this service's audience, or it expired.Add the audience to the client's Default audiences (Access admin → Web clients → the client), then get a new token.
The service answers 403 and the token has the audienceA scope the operation needs is missing.Add one of the operation's scopes to the client's Default scopes. Use the scope names your tenant lists under Access admin → Scopes.
Token endpoint: 401 invalid_clientUnknown client ID or wrong secret.Check the client ID and paste the secret again.
Token endpoint: 400 unauthorized_clientThe client may not use client credentials.Add the grant type Client credentials to the web client.
Token endpoint: 400 invalid_request about an audienceYou asked for an audience the client doesn't have.Add it to Default audiences, or stop asking for it.
Token endpoint: 500 right after scopes were addedThe client's Default scopes, joined with spaces, are over about 1024 characters.Move scopes to Additional scopes and request them per call, or split the work over two clients.
{"code":"not_found","message":"The requested location was not found"}That service isn't deployed on this tenant.Nothing to change in the client. Ask whoever runs the tenant.

Two kinds of client exist in Access. Service APIs like this one take a web client with the Client credentials grant. Access's own configuration API takes an API client: a web client sent there gets 401 invalid_credentials.