Skip to content
authreads Docs

Users & teams

You always create people in authreads — it's the source of truth for identity. Where they end up depends on which surface they use.

Two kinds of user

 Operators (admin/management team)Product / end-users
UseYour admin / management surfaceYour product app
Access gateRole only (read live from the token)role ∩ org-type ∩ package
Local product rowNever — kept in authreads onlyMirrored on first login

Create a user (Management API)

Get a machine token, then create the identity. Organization and role are optional; include both when the user should immediately join a workspace:

1 · get a machine token
curl -X POST https://auth.example.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&client_id=...&client_secret=..."
# → { "access_token": "...", ... }
2 · create the user
curl -X POST https://auth.example.com/api/v1/management/users \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"email":"user@acme.com","password":"..."}'
# → { "id": "<user id>", "email": "...", "email_verified": false,
#     "set_password": { "link": "..." } | null }
The returned id is the user's authreads id. You don't copy it anywhere — your product resolves the user by that id automatically on login. Omit password to get a set-password link instead.

Email verification

New users are unverified unless you explicitly assert evidence. Omit email_verified during creation to assert nothing. Authreads automatically records first-hand proof when the user redeems a login or step-up code, invite/onboarding link, or reset link delivered by Authreads email. A raw set-password link returned through this API does not verify the address.

Assert verification later
curl -X PATCH \
  https://auth.example.com/api/v1/management/users/<user-id>/email-verification \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"email_verified":true}'
# → { "id":"…", "email_verified":true,
#     "email_verified_method":"tenant_asserted", "email_verified_at":"…" }
Set this only when your tenant has actually verified control of the address. A false request revokes only your own tenant_asserted evidence; it cannot downgrade authreads_otp or authreads_token proof. Every transition is tenant-scoped and durably audited.

Products can create users too

Your product's own backend can create users by calling the same Management API with its machine credential — so your users are added from your app, and your product sends the onboarding email. Either way the user is created in authreads; product/end-users are then mirrored into your product on their first login (no manual sync).

Operators (admin team) stay in authreads only — never stored in your product. Only product/end-users get a local record, created on first login.