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 operationsWhen 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/tokenwithgrant_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 sourceOlder 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 sourceSend {"operations":[{"op":"replace","path":"displayName","value":"New name"}]}. op is add, remove or replace.
PUT resets what you leave out
from sourcePUT 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 sourceThey 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 livesort=userName asc works. sort=-userName returns 400 IDS-400.
Only searchable attributes can be filtered
checked liveFilters 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 liveco / 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 liveAdd 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 sourceKeep 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 sourceWith 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.
| 400 | IDS-400 | Invalid argument or state, including unknown or not-searchable filter attributes. |
| 404 | IDS-404 | Identity or primary contact not found. A PATCH on a soft-deleted identity also returns 404. |
| 409 | IDS-409 | Duplicate value on a unique attribute. Wins over 400 when validation collects both. |
| 412 | IDS-412 | Canonical schema missing. |
| 500 | IDS-500 | Unexpected failure. Quote the id field (trace id) when you report it. |
When a call fails
| Reply | Means | What to change |
|---|---|---|
| The service answers 401 | The 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 audience | A 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_client | Unknown client ID or wrong secret. | Check the client ID and paste the secret again. |
| Token endpoint: 400 unauthorized_client | The client may not use client credentials. | Add the grant type Client credentials to the web client. |
| Token endpoint: 400 invalid_request about an audience | You 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 added | The 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.