Browser-direct profile and email management
These are SSO POST operations below the browser-direct base.
Every body includes selected session handles; every call needs JSON, admitted
Origin and a fresh endpoint DPoP proof. The selected session must be active,
activated and currently admitted. No caller-supplied member UUID is accepted.
These operations need no five-minute reauthentication requirement. Expired
access can be renewed once before retrying; a revoked session needs sign-in.
Profile
| Relative path | Scope | Additional input | Success |
|---|---|---|---|
/profile/get |
profile |
None | sub, display_name, avatar |
/profile/update |
profile |
Nonempty profile object |
Same projection after update |
Only display_name and avatar are editable. Display name is trimmed, at most
128 Unicode characters. Avatar is a valid HTTPS URL, at most 255 Unicode
characters, without userinfo, controls or backslashes. An empty string clears
a field; omission preserves it. Unset values return null. Unknown fields and
an empty patch are rejected with invalid_request; missing scope is
insufficient_scope (403). These updates do not rotate tokens or close sessions.
{"bd_carrier":"<carrier>","bd_session":"<session>","bd_key":"<carrier secret>","profile":{"display_name":"Sample Member","avatar":"https://images.example.org/avatar.png"}}
{"sub":"cccccccc-cccc-4ccc-8ccc-cccccccccccc","display_name":"Sample Member","avatar":"https://images.example.org/avatar.png"}
In the tenant me projection,
name remains the system login name, display_name is the editable name,
picture reflects avatar, and preferred_username is absent. Profile editing
does not rename the login, alter groups or grant manager permissions.
Email operations
All six require the email scope. An address's presence is distinct from verified
ownership, active status and primary selection. Adding an address does not send
mail automatically or assert ownership.
| Relative path | Additional input | Success |
|---|---|---|
/emails/list |
None | Email view |
/emails/add |
email (valid, trimmed/lowercased, ≤254 bytes) |
Email view plus email_id |
/emails/resend |
email_id UUID |
Email view after delivery request |
/emails/verify |
email_id UUID, code six-digit string |
Email view after proof |
/emails/primary |
email_id UUID |
Email view with chosen primary |
/emails/remove |
email_id UUID |
Email view after removal |
Every email view contains sub and emails. Rows contain only id, email,
status, boolean verified, primary_email, can_send, can_verify,
can_make_primary, can_remove, and numeric resend_after seconds. Archived
rows are omitted; disabled rows can be displayed but are not editable. Use
capabilities as a current UI hint and handle a later policy/state rejection.
{
"sub":"cccccccc-cccc-4ccc-8ccc-cccccccccccc",
"emails":[{
"id":"dddddddd-dddd-4ddd-8ddd-dddddddddddd",
"email":"member@example.org","status":"active","verified":true,
"primary_email":true,"can_send":false,"can_verify":false,
"can_make_primary":false,"can_remove":false,"resend_after":0
}]
}
{"bd_carrier":"<carrier>","bd_session":"<session>","bd_key":"<carrier secret>","email_id":"dddddddd-dddd-4ddd-8ddd-dddddddddddd","code":"123456"}
There can be at most ten stored addresses. Add creates pending, unverified, nonprimary email; repeating add for this member's current usable address returns its row. A disabled/archived row is not silently revived. Another unarchived member owning that address in the same organization conflicts; other organizations have separate ownership. Addresses are not account-merging instructions.
Explicit resend issues a ten-minute proof tied to member, address, application, origin, key and initiating selected session. Switching session requires a new send from that context. Resend replaces older proof, including from another carrier. Each challenge permits five attempts; the member has 20 attempts/hour, one send/minute and five sends/hour across apps/carriers. Failed delivery attempts also count. Successful proof consumes the challenge. Resend/verify on an already verified active row returns the current view without another proof consumption. After a lost response reload the list; if still unverified, resend rather than assume success. The first verified address becomes primary when no verified primary exists.
Only verified active email can become primary. Switch primary before removing
it; the final verified address is protected. Pending nonprimary addresses may
be removed. Choosing primary and removing email affect subsequent me, recovery
and email sign-in immediately. Missing/ambiguous primary state is not resolved
by arbitrary selection, and email login requires unique current verified
ownership. Password recovery can use another verified address as documented
in recovery.
Self-service email edits, including removing a verified nonprimary address, keep sessions. Manager removal has a different credential-revocation effect; see manager security. No dedicated universal self-service audit ledger is exposed by these responses.
| Error | Handling |
|---|---|
email_unavailable (409) |
Address conflict; select another address, never infer the other owner |
email_limit, email_not_verified, email_primary, email_last_verified (409) |
Resolve the ten-address, verification, primary or final-verified protection, then reload |
invalid_request (400/404) |
Malformed ID/code/address or unavailable row |
email_code_invalid (400) |
Wrong/expired code; reload/resend |
email_verification_required (409) |
Expired, exhausted or wrong-session challenge; request a new code within the member budget |
email_rate_limited (429) |
Respect member cooldown and send window |
access_denied (403) |
Organization-managed or inactive address; no self-service edit |
session_changed (409) |
Reload after changed selected authority or address |
temporarily_unavailable (503) |
Concurrent update; retry later with a fresh proof |
insufficient_scope (403) |
Obtain a session with registered email scope |
| Operational/delivery failure | Do not mark verified; reload and follow resend cooldown |
Operators need working existing Post/email delivery, protected encrypted transaction storage, and the existing email-confirmation slot secret (at least 32 bytes). These secrets stay server-side. A successful send request does not prove mailbox delivery; setup and live delivery acceptance are separate checks.