Skip to main content

End-User Field & Endpoint Matrix

This is the single reference for which end-user attributes Zyphr stores, which endpoint returns each one, and at which credential scope. If you are trying to determine whether a field exists — or where to read it from — start here rather than probing endpoints.

Credential scopes

Every row in the matrix is tagged with the scope that can read (or write) it. There are three distinct credentials in Auth-as-a-Service, and they are not interchangeable:

ScopeCredentialRunsReads
End-user tokenX-Application-Key (za_live_pub_* / za_test_pub_*) + Authorization: Bearer <access_token>Browser / mobile / any clientThe signed-in user's own profile and sign-in state
Application key/secretX-Application-Key (za_live_pub_*) + X-Application-Secret (za_live_sec_*)Server-side onlyAny user in the authenticating application (admin scope)
Dashboard JWTAuthorization: Bearer <dashboard JWT>The Zyphr dashboard UIAccount-scoped management. Not for integrators — this is what our own dashboard uses.
Never ship the secret key to a client

X-Application-Secret and the dashboard JWT are server-side only. Client apps use the publishable key (za_live_pub_* / za_test_pub_*) plus the end user's own access token — never the secret. See Client-side Auth for the credential boundary.

Attribute matrix

Scope uses the abbreviations above: app-key = application key/secret (server-side admin), user-token = end-user token (self).

AttributeEndpoint(s)ScopeRead/Write
idGET /auth/users/:id, GET /auth/users/meapp-key, user-tokenRead
emailGET /auth/users/:id, GET /auth/users/me, PATCH /auth/users/:idapp-key, user-tokenRead; write (app-key PATCH)
nameGET /auth/users/:id, GET /auth/users/meapp-key, user-tokenRead; write (PATCH /auth/users/me, app-key PATCH)
avatar_urlGET /auth/users/:id, GET /auth/users/meapp-key, user-tokenRead; write (PATCH /auth/users/me, app-key PATCH)
statusGET /auth/users/:idapp-keyRead; write (app-key PATCH, active/suspended)
is_anonymousGET /auth/users/:idapp-keyRead
metadataGET /auth/users/:id, GET /auth/users/meapp-key, user-tokenRead; write (PATCH /auth/users/me, app-key PATCH)
email_verifiedGET /auth/users/:id, GET /auth/users/:id/auth-methods, GET /auth/users/meapp-key, user-tokenRead
phone_verifiedGET /auth/users/:id, GET /auth/users/:id/auth-methodsapp-keyRead
mfa_enabledGET /auth/users/:id, GET /auth/users/:id/auth-methodsapp-keyRead
first_activity_atGET /auth/users/:idapp-keyRead
last_login_atGET /auth/users/:id, GET /auth/users/meapp-key, user-tokenRead
created_atGET /auth/users/:id, GET /auth/users/meapp-key, user-tokenRead
updated_atGET /auth/users/:idapp-keyRead
has_passwordGET /auth/users/:id/auth-methodsapp-keyRead
oauth_providersGET /auth/users/:id/auth-methods, GET /auth/oauth/connectionsapp-key; user-token (self)Read
passkeys (count)GET /auth/users/:id/auth-methodsapp-keyRead

Notes

  • GET /auth/users/:id is the application-key-scoped directory lookup (the SDK's getEndUserById). It returns the core profile and verification flags but not has_password, oauth_providers, or the passkey count — those live on the sign-in-methods endpoint below.
  • GET /auth/users/me is the self endpoint (end-user token). It returns the subset of profile fields the user is allowed to see about themselves. It does not return status, is_anonymous, or updated_at.
  • metadata is not trusted for authorization. It is writable by the end user through their own token. For authorization data use trusted custom claims.

Sign-in methods: GET /auth/users/:id/auth-methods

The single, application-key-scoped endpoint that answers "how can this user sign in?" — everything you need to build a sign-in methods settings screen without stitching together several calls. It returns:

{
"data": {
"has_password": true,
"oauth_providers": ["google", "apple"],
"mfa_enabled": false,
"email_verified": true,
"phone_verified": false,
"passkeys": 2
}
}
FieldTypeMeaning
has_passwordbooleanUser has a password credential (false for OAuth-only / passwordless users)
oauth_providersstring[]Distinct linked OAuth providers (e.g. google, apple)
mfa_enabledbooleanMulti-factor authentication is enabled
email_verifiedbooleanEmail address is verified
phone_verifiedbooleanPhone number is verified
passkeysintegerNumber of registered WebAuthn passkeys
curl https://api.zyphr.dev/v1/auth/users/USER_ID/auth-methods \
-H "X-Application-Key: za_live_pub_xxxx" \
-H "X-Application-Secret: za_live_sec_xxxx"
has_password, oauth_providers, and the passkey count are only here

These three are not on GET /auth/users/:id. If you need any of them, call auth-methods. An end user can read their own linked providers via the self-scoped GET /auth/oauth/connections (end-user token) — see OAuth.

Application self-metadata: GET / PATCH /auth/application

Application-secret-scoped read and write of the authenticating application's own metadata — both GET and PATCH require X-Application-Key and X-Application-Secret. GET returns it; PATCH sets the test_recipients allowlist. Both are scoped to the calling application via its credentials — there is no application id in the path or body, so there is no cross-tenant reach.

{
"data": {
"id": "app_abc123",
"name": "My SaaS App",
"environment": "live",
"signing_algorithm": "HS256",
"test_recipients": ["qa@example.com", "dev@example.com"]
}
}
FieldReadWriteMeaning
idThe application ID
nameThe application's display name
environmentlive or test (from the credentials that authenticated the request); null for legacy application-level keys
signing_algorithmHS256 (default), RS256, or ES256 — the algorithm your end-user tokens are signed with
test_recipients✓ (PATCH)The auth-email allowlist — see below
# Read your application's metadata (including the current allowlist)
curl https://api.zyphr.dev/v1/auth/application \
-H "X-Application-Key: za_live_pub_xxxx" \
-H "X-Application-Secret: za_live_sec_xxxx"
Confirming your token signing algorithm

signing_algorithm is the authoritative way to check whether your app issues symmetric (HS256) or asymmetric (RS256/ES256) tokens. Do not infer it from the presence of a JWKS — see Verifying tokens & JWKS.

Setting the auth-email allowlist from config: PATCH /auth/application

test_recipients is the per-application auth-email allowlist. When non-empty, it gates all auth emails — only the listed addresses receive them, which is how you keep test/staging apps from mailing real users. Historically this was set by clicking through the dashboard; it is now settable directly from your own infrastructure config with a single application-secret-scoped PATCH:

# Set the allowlist from your deploy pipeline / IaC (application secret required)
curl -X PATCH https://api.zyphr.dev/v1/auth/application \
-H "X-Application-Key: za_live_pub_xxxx" \
-H "X-Application-Secret: za_live_sec_xxxx" \
-H "Content-Type: application/json" \
-d '{ "test_recipients": ["qa@example.com", "dev@example.com"] }'
# Pass an EMPTY array to clear the allowlist and disable the gate
curl -X PATCH https://api.zyphr.dev/v1/auth/application \
-H "X-Application-Key: za_live_pub_xxxx" \
-H "X-Application-Secret: za_live_sec_xxxx" \
-H "Content-Type: application/json" \
-d '{ "test_recipients": [] }'

The PATCH response is identical to GET /auth/application, so you can read back exactly what you set. Notes:

  • Application-SECRET scoped — requires X-Application-Secret, so this is a server-side / CI operation, never a client one.
  • GET and PATCH are symmetrictest_recipients now appears in the GET response too, so config-management tooling can diff desired vs. actual state.
  • An empty array clears the allowlist (disables the gate). A malformed email, a non-array body, or a non-string entry returns 400 validation_error.
  • This is the same allowlist the dashboard manages and that gates the auth-email test send endpoint — see Test send allowlist.
Infrastructure-as-code

Because the allowlist is now a single secret-scoped PATCH, you can commit it to your deploy pipeline and set it per environment — no dashboard clicks. For a staging app, list only your QA addresses; for production, send an empty array to turn the gate off.

Required credential by endpoint

Which credential each end-user endpoint requires. Use this to design your client/server split up front instead of discovering it per 401. The three credentials (see Credential scopes above):

  • publishableX-Application-Key only (za_*_pub_*). Safe for browser / mobile.
  • secretX-Application-Key + X-Application-Secret (za_*_sec_*). Server-side only.
  • + end-user token — additionally requires Authorization: Bearer <access_token> (the signed-in user acting on themselves).
Where the secret is required, the operation is server-side by design

Endpoints marked secret (login, register, magic-link, phone, email-OTP send/verify, the user directory, claims) must run from your backend. refresh is the exception — it is publishable, because the refresh token is the credential, so client apps can keep a session alive without a backend. This table is derived from the route middleware and reflects the shipped behavior.

Sessions & tokens

EndpointRequired credential
POST /auth/users/loginsecret
POST /auth/users/registersecret
POST /auth/sessions/refreshpublishable
POST /auth/sessions/revokesecret
POST /auth/sessions/revoke-allsecret + end-user token
GET /auth/sessionspublishable + end-user token

Profile (self)

EndpointRequired credential
GET /auth/users/mepublishable + end-user token
PATCH /auth/users/mepublishable + end-user token
DELETE /auth/users/mepublishable + end-user token
POST /auth/users/change-passwordpublishable + end-user token
GET /auth/password-requirementspublishable

Directory & claims (admin, server-side)

EndpointRequired credential
GET /auth/users, GET /auth/users/by-email, GET /auth/users/:idsecret
GET /auth/users/:id/auth-methodssecret
PATCH /auth/users/:id, DELETE /auth/users/:idsecret
POST /auth/users/invitesecret
GET / PUT /auth/users/:id/claimssecret

Passwordless & alternate methods

EndpointRequired credential
POST /auth/magic-link/send, /magic-link/verifysecret
POST /auth/forgot-password, /reset-password, /validate-reset-tokensecret
POST /auth/verify-email/send, /verify-email/resendsecret + end-user token
POST /auth/verify-email/confirmsecret
POST /auth/phone/{register,login}/{send,verify}secret
POST /auth/email-otp/{register,login}/{send,verify}secret
GET /auth/phone/available, /email-otp/availablepublishable
POST /auth/users/anonymous, /game-center, /google-play-gamespublishable
POST /auth/users/convertpublishable + end-user token

OAuth & WebAuthn

EndpointRequired credential
GET /auth/oauth/providers, /oauth/:provider/authorizepublishable
GET /auth/oauth/connections, DELETE /auth/oauth/:providerpublishable + end-user token
GET /auth/oauth/tokens/:provider, POST /oauth/tokens/:provider/refreshsecret
GET /auth/webauthn/credentials, /webauthn/statuspublishable + end-user token
POST /auth/webauthn/registration/*secret + end-user token
POST /auth/webauthn/authentication/*secret

See also