UsherStats Docs Contents usherstats.com Start free

Accounts and sign-in

People sign in with an email and password; the API answers with a session cookie, us_session (HttpOnly, Secure, SameSite=Lax, 30 days, extended while in use). Programs use API tokens instead. Every error is application/problem+json with a title that says what to do. The full reference is GET /v1/openapi.json (OpenAPI 3.1, generated from the routes the API serves).

The examples below run, in this order, in the API's test suite. They keep the cookie in cookies.txt with curl's -c (save) and -b (send).

RouteWhat it does
POST /v1/auth/signupCreate an account and its workspace; emails a confirmation link (24 hours)
POST /v1/auth/verifyConfirm the email address with the token from that link
POST /v1/auth/verify/resendSend a new confirmation link
POST /v1/auth/loginSign in; sets the cookie, or asks for a second factor
POST /v1/auth/login/2faThe second step: the authenticator code
POST /v1/auth/logoutEnd this session
GET /v1/auth/sessionsYour live sessions
DELETE /v1/auth/sessions/{id}End one of them
POST /v1/auth/password/changeChange your password (keeps this session, ends the others)
POST /v1/auth/password/reset-requestEmail a reset link (1 hour)
POST /v1/auth/password/resetSet a new password with that link; signs out everywhere
POST /v1/auth/2fa/enrollStart two-factor sign-in (TOTP)
POST /v1/auth/2fa/confirmTurn it on with a code
POST /v1/auth/2fa/disableTurn it off (password and code)
GET /v1/meWho you are: your account, workspaces, role and scopes
GET /v1/openapi.jsonThe API reference

Create an account

Passwords need at least 10 characters, and one that appears in a known data breach (checked against Have I Been Pwned without sending the password) is refused. The answer is the same whether or not the email already has an account.

curl https://api.usherstats.com/v1/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email": "ana@example.com", "password": "plum-orbit-71-lantern", "workspaceName": "Ana Sites"}'

The email holds a link to https://app.usherstats.com/verify?token=.... The app posts that token here with the password the account was signed up with (so a link opened by someone who did not sign up confirms nothing); it works once, and starts no session: sign in afterwards.

curl https://api.usherstats.com/v1/auth/verify \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{"token": "$VERIFY_TOKEN", "password": "plum-orbit-71-lantern"}
EOF

Lost the email? Ask for another (always 202, so it does not reveal who has an account):

curl https://api.usherstats.com/v1/auth/verify/resend \
  -H "Content-Type: application/json" \
  -d '{"email": "ana@example.com"}'

Sign in

Until the address is confirmed, sign-in answers 403 with type email-unverified. After five wrong passwords for one account from one address, sign-ins to that account from that address wait 30 seconds, doubling with each further failure up to 15 minutes; meanwhile they get the same 401 as a wrong password, and other addresses are not affected. The owner gets one email an hour about it. A password reset clears it at once.

curl https://api.usherstats.com/v1/auth/login -c cookies.txt \
  -H "Content-Type: application/json" \
  -d '{"email": "ana@example.com", "password": "plum-orbit-71-lantern"}'
curl https://api.usherstats.com/v1/me -b cookies.txt

/v1/me lists your workspaces. If you belong to more than one, choose the one a request acts on with the X-Workspace: ws_... header (or ?workspace=ws_...); without it, the oldest membership is used.

Sessions

curl https://api.usherstats.com/v1/auth/sessions -b cookies.txt
curl -X POST https://api.usherstats.com/v1/auth/password/change -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{"currentPassword": "plum-orbit-71-lantern", "newPassword": "cedar-quartz-58-harbor"}'

Two-factor sign-in

Enrolling returns a secret and an otpauth:// URI for an authenticator app (show the URI as a QR code). It is not on until a code from the app is confirmed. The secret is stored encrypted; each code works once.

curl -X POST https://api.usherstats.com/v1/auth/2fa/enroll -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{"password": "cedar-quartz-58-harbor"}'
curl -X POST https://api.usherstats.com/v1/auth/2fa/confirm -b cookies.txt \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{"code": "$TOTP_CODE"}
EOF

Sign out, then sign in again: now the password step returns a challenge instead of a cookie, and the code completes it (five guesses, five minutes).

curl -X POST https://api.usherstats.com/v1/auth/logout -b cookies.txt -c cookies.txt
curl https://api.usherstats.com/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "ana@example.com", "password": "cedar-quartz-58-harbor"}'
curl https://api.usherstats.com/v1/auth/login/2fa -c cookies.txt \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{"challenge": "$CHALLENGE", "code": "$TOTP_CODE"}
EOF
curl -X POST https://api.usherstats.com/v1/auth/2fa/disable -b cookies.txt \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{"password": "cedar-quartz-58-harbor", "code": "$TOTP_CODE"}
EOF

Forgotten password

Always 202. The link (https://app.usherstats.com/reset?token=...) works once, for one hour. Setting the new password signs out every session.

curl https://api.usherstats.com/v1/auth/password/reset-request \
  -H "Content-Type: application/json" \
  -d '{"email": "ana@example.com"}'
curl https://api.usherstats.com/v1/auth/password/reset \
  -H "Content-Type: application/json" \
  --data @- <<EOF
{"token": "$RESET_TOKEN", "password": "violet-anchor-93-meadow"}
EOF
curl https://api.usherstats.com/v1/me -b cookies.txt

Sign in with the new password, and end that session by its id:

curl https://api.usherstats.com/v1/auth/login -c cookies.txt \
  -H "Content-Type: application/json" \
  -d '{"email": "ana@example.com", "password": "violet-anchor-93-meadow"}'
curl https://api.usherstats.com/v1/auth/sessions -b cookies.txt
curl -X DELETE https://api.usherstats.com/v1/auth/sessions/$SESSION_ID -b cookies.txt -c cookies.txt

The reference

curl https://api.usherstats.com/v1/openapi.json

Limits

Sign-up, sign-in, the confirmation and reset emails are rate limited per address (and the emails per recipient); an API token may make 600 requests a minute. Past a limit the answer is 429 with Retry-After in seconds.

View this page as Markdown