Authorize
GET /oauth/authorize — start the authorization-code + PKCE flow and obtain the user's consent.
GET /oauth/authorizeThe authorization endpoint. Redirect the user's browser here to begin the flow.
Supermail authenticates the user, shows a consent screen where they pick which
mailbox(es) your app may reach and which capabilities to grant, then redirects
back to your redirect_uri with an authorization code.
Query parameters
| Parameter | Required | Description |
|---|---|---|
response_type | yes | Must be code. |
client_id | yes | Your application's id. |
redirect_uri | yes | Must exactly match one of the app's registered redirect URIs. |
scope | yes | Space-separated scopes, e.g. openid mail.read. Must stay inside the app's registered ceiling and include every required scope. |
state | recommended | Opaque value echoed back on the redirect — use it for CSRF protection and to carry per-request context. |
code_challenge | yes | The 43-character PKCE challenge — base64url(SHA-256(verifier)), without padding. |
code_challenge_method | yes | Must be S256; plain is not accepted. |
prompt | no | select_account shows Traummail's account chooser first, so the user can pick, add, or create the account to sign in with instead of silently continuing as the browser's active account. Any other value is refused with invalid_request. |
login_hint | no | The Traummail username of the account the user already chose in your app. If that account is signed in on this browser, the request continues as it (it becomes the browser's active account) without the chooser; otherwise the account chooser is shown. Ignored together with prompt=select_account. |
PKCE is mandatory for every client, including confidential clients.
Generate a 43–128 character high-entropy code_verifier from the ASCII
unreserved set, derive code_challenge = base64url(sha256(verifier)), and
keep the verifier for the token exchange.
Example
GET /oauth/authorize?response_type=code
&client_id=app_01H...
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20mail.read%20accounts.read
&state=xyz123
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256Choosing an account
A browser can be signed in to several Traummail accounts at once. Without
prompt, the authorize request continues as the browser's active account. With
prompt=select_account, the user first sees the accounts signed in on that
browser (and ones that were signed out), plus Use another account and
Create an account; the request then resumes for the account they chose.
Send prompt=select_account whenever a person explicitly starts a sign-in, and
always after your app signed them out.
When the person picked one of their accounts in your own app (for example to
sign in again after your session expired), send its username as login_hint
instead, so they are not asked to choose the same account twice.
Consent
On the consent screen the user chooses the account selector — one specific mailbox or all of their mailboxes (now and in the future). Every requested scope starts selected. Scopes the app registered as required are locked; the remaining recommended scopes are shown as optional and may be unchecked. The resulting grant records that decision. Approving transfers controllership of the granted data to your app.
Supermail enforces the required subset on the server during authorize, consent, and token issuance. A client cannot bypass it by editing the consent request. See Required and recommended scopes.
Redirects back to your app
On approval, the user is sent to your redirect_uri with a one-time code:
https://app.example.com/callback?code=ac_9f3a...&state=xyz123The code is single-use, expires in ~60 seconds, and is bound to your client, the PKCE challenge, and the grant. Exchange it at the token endpoint.
On denial, the user is sent back with an error instead:
https://app.example.com/callback?error=access_denied&state=xyz123Always verify the returned state matches the one you sent before acting on the
response.