Users and credentials

Password Store API

Stores password hashes for identities and the policies that rule them: length, composition, expiry, history, lockout. Verifies and changes passwords at sign-in.

https://{tenant-host}/password-storeaudience password-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

  • Verify or change a user's password from a backend or an IO flow.
  • Set, reset, unlock or delete the password of an identity from an admin tool.
  • Import pre-hashed passwords when you migrate users from another system.
  • Read or change the tenant's password policies.

Connect

Base URL
https://{tenant-host}/password-store
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 password-storechecked live
Default scopes
The password:* scope each operation lists below, e.g. password:policy:get for policy reads. Not password-store-admin, which the published spec names. Keep the client's scopes, joined with spaces, within 1024 characters.checked live
Tenant-Id header
Send Tenant-Id: <tenant-uuid>. The service rejects a missing or invalid one with INVALID_TENANT_ID. The challenge reset calls require it explicitly.from source
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}/password-store/api/v1/configuration/policies/default \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Tenant-Id: $TENANT_ID"

Operations

Open an operation to see its parameters and code, and send it to your tenant. Two prefixes: verify and change live under /auth/v1, everything else under /api/v1. The token needs the listed scope.

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

Verify and change are under /auth/v1, not /api/v1

from source

Call /password-store/auth/v1/verify/password. There is no /api/v1/verify/password route: only the password and policy management APIs use /api/v1.

Scopes are password:*, not password-store-admin

checked live

The published spec names one scope, password-store-admin. The service checks one scope per operation instead: password:policy:get for policy reads, password:verify for verify, and so on.

A wrong password is HTTP 422, not 401 or 404

from source

Verify and change answer 422 with a code and a verificationResult: PST-411 / INCORRECT, PST-422 / LOCKED, PST-466 / POLICY_BLOCKED. A user without a password is PST-413, also 422. Branch on code, not on the status alone.

Verify can succeed and still ask for a reset

from source

A correct password that breaks the current policy (expired, too short) returns 200 VERIFIED with mustReset: true. mustReset is left out when false. Send the user to a change-password step when it is there.

A locked password fails even when it is right

from source

After lockAttempts wrong tries, every verify returns PST-422 until autoUnlockSeconds pass. Each locked attempt moves that window forward. The unlock call answers 409 PST-417 when the password isn't locked.

Admin reset takes password, not newPassword

from source

PUT /api/v1/identities/{identityId}/password takes {"password": "..."} and checks neither the old password nor a challenge: your flow must prove who the user is. newPassword belongs to the challenge reset completion. Create is not an upsert: a second create answers 409 PST-415.

Policy values are strings; updates need the current version

checked live

Rules come back as strings ("lengthMin": "8", "isDefault": "true") and version as a number. PATCH and PUT go to /policies/{policyId}/version/{version} with the version from your last GET. A stale version answers 500 PST-555, not 409.

The default policy can be the root policy

checked live

On a tenant without stored policies, the list is {"policies": []} and /policies/default returns the root rules, without id or version. Root defaults: length 8–64, one lower, upper, digit and special character, expiry 90 days, lock after 5, unlock after 300 s.

Stored policies don't inherit root rules

from source

A custom policy only enforces the rules it contains. Put every rule you need into it. Setting a new default doesn't move passwords that already point to another policy.

Breach checks run later

from source

With pwnedCheckOnStore or pwnedCheckOnAuth set, the breach check runs asynchronously. A hit sets mustReset on the stored password afterwards, so a 201 or 200 doesn't prove the password is clean.

Errors

Error bodies carry code, message, and when relevant verificationResult and details. The status depends on the API: verify, change and challenge reset use 422 for password problems, the management APIs use 409. 401 and 403 come from the security layer and have no PST code.

422PST-411Wrong password (verify, change). verificationResult: INCORRECT.
422PST-422Password locked. verificationResult: LOCKED.
422PST-466Blocked by policy. verificationResult: POLICY_BLOCKED.
422PST-413No password for this identity (verify, change).
409PST-420New password breaks the policy. 422 on change and challenge reset.
409PST-424New password was used before (history check).
409PST-415The identity already has a password. Create is not an upsert.
409PST-416Import over a password that isn't marked migrated.
409PST-417Unlock called on a password that isn't locked.
404PST-431Policy not found.
409PST-432Policy still used by passwords: it can't be deleted.
409PST-434A policy with this name exists.
500PST-555Stale policy version on PATCH or PUT. Read the policy again.
400PST-234Unknown challenge policy alias on reset init.
422PST-235Challenge verification token invalid, expired, reused or for another identity.

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.