https://dash.square1.dev and accept either the
ws-session cookie or a Bearer API key.
Change your password
POST /api/user/me/password — 5 requests/minute.
Errors
The
409 fires after the current-password check has already run
against a dummy hash, so the response time doesn’t reveal whether a
password exists. Both success and failure are written to the account’s
audit trail.Passkeys
Four endpoints under/api/user/me/passkeys, holding up to 5 WebAuthn
credentials per account.
List — GET /api/user/me/passkeys
id is the WebAuthn
credential id. When you didn’t name a passkey, label falls back to a
recognized device name for its authenticator. deviceType is the
authenticator’s WebAuthn device type (singleDevice or multiDevice), and
is an empty string when the authenticator didn’t report one.
Register — two steps
Registration is the standard WebAuthn ceremony split across two calls. 1.POST /api/user/me/passkeys/options
optionsJSON straight to navigator.credentials.create(). The
response also sets a ws-pk cookie — a browser-session key, separate
from ws-session, that binds the challenge to this tab. It lives 10
minutes; the challenge behind it expires after 5.
A 409 (no code) means the challenge could not be started — most often
because you already hold max passkeys. The cap is enforced here, at the
start of the ceremony, not at the finish.
2. POST /api/user/me/passkeys
label is optional. Both a missing response and a missing/expired ws-pk
cookie return 400 passkey_challenge_invalid, as does a response that fails
verification.
Because the challenge is keyed to the
ws-pk cookie rather than to your
account, two browser tabs can register independently without one
overwriting the other’s challenge. It also means the two calls must come
from the same cookie jar — this ceremony is not scriptable with a Bearer
key alone.Revoke — DELETE /api/user/me/passkeys/:id
:id is the credential id from the list. 404 if it isn’t yours or is
already revoked. Revocations are audited.