- Mailbox API – Authentication and Authorization
- Mailbox API – Schemas
- Mailbox API – Versioning
- Mailbox API – Service
- Mailbox API – Account
- Mailbox API – Account Settings
- Mailbox API – Account Security
- Mailbox API – Account Filters
- Mailbox API – Folders
- Mailbox API – Mails
- Mailbox API – Mails Create and Send
- Mailbox API – Mails Search
- Mailbox API – Mails Counters
- Mailbox API – BIMI
- Mailbox API – Conversations
- Mailbox API – Labels
- Mailbox API – Contacts
- Mailbox API – Batch Operations
- Mailbox API – Undo
- Mailbox API – Error Handling
Updated: Jul 31, 2026
The Axigen Mailbox API requires every request to be made in the context of an authenticated session. This page describes the ways a client can obtain a session, how to carry it on subsequent requests, and the additional steps that may be required before a session becomes usable.
Auth Methods
The Axigen Mailbox API supports the following authentication and authorization methods:
|
Method |
Axigen's role |
Best for |
Availability |
|---|---|---|---|
|
Axigen OAuth 2.0 |
Authorization server – Axigen issues the tokens |
First party mobile and native apps that must stay signed in across restarts |
10.7+ |
|
External OAuth 2.0 with OpenID Connect |
Resource server – Axigen validates tokens issued by your identity provider |
Deployments with a central identity provider; browser based applications and mobile / native apps |
All versions |
|
Cookie Authentication |
Authenticates the user directly |
Browser based clients |
All versions |
|
Basic Authentication |
Authenticates the user directly |
Scripts and server to server integrations, and any case where no OAuth 2.0 provider is available |
All versions |
Note that using an OAuth 2.0 flow is strongly recommended as it is the most secure option. It avoids handling user passwords in your application and gives you revocable, short lived credentials.
Choosing a Method
-
If your deployment already has an external identity provider, use External OAuth 2.0 with OpenID Connect. Your application obtains a token from the provider and Axigen validates it.
-
If there is no external provider and you are building a mobile or native app that should keep the user signed in, use Axigen OAuth 2.0. Axigen itself issues an access and refresh token pair.
-
Use Cookie Authentication for browser based clients, and Basic Authentication only when neither OAuth option is available.
Sessions
Every method ends with a session identifier (sessid). Each subsequent request must carry two things: the session identifier, and the credential the session was created with.
The session identifier travels in the X-Axigen-Session header, whichever login endpoint produced it:
The credential depends on how the session was created, and is not interchangeable:
|
Session obtained via |
Repeat on every request |
|---|---|
|
|
The same |
|
|
The |
|
|
The |
A request that presents the session identifier but omits the credential is rejected as an expired session. A cookie backed session used from a client that does not store cookies will therefore appear to expire on the first call after login.
Behind the webmail proxy, the session identifier is returned with a 32 character backend routing suffix appended. Send the value exactly as received – only the leading 32 characters are used.
2-Step Verification and Captcha
2-Step Verification and Captcha are supported in the following scenarios:
|
Method |
2-Step Verification |
Captcha |
|---|---|---|
|
Axigen OAuth 2.0 |
Handled during the session login that precedes the authorization code request |
Handled during the session login that precedes the authorization code request |
|
External OAuth 2.0 with OpenID Connect |
If enabled by the Authorization Server |
If enabled by the Authorization Server |
|
Cookie Authentication |
Supported |
Supported |
|
Basic Authentication |
Not supported |
Not supported |
Login
Request Headers
|
Name |
Required |
Values |
Description |
|---|---|---|---|
|
|
* |
|
“Basic” – used to authenticate against internal user authentication mechanism when OAuth 2.0 and OpenID Connect are not available “Bearer” – used to authenticate against an external authentication provider (such as OAuth 2.0 and OpenID Connect) |
Response
When successful, the endpoint returns the following JSON structure:
All subsequent API calls must use the same authentication method and include the session ID in the X-Axigen-Session header.
Important: If you start with Basic Auth, all subsequent API calls must also include the same Basic Auth header.
Note that when using bearer token authorization, the username is unknown to Axigen until the token is validated against the external authentication provider.
In case the user can't be authenticated (i.e. wrong authentication credentials, invalid token, expired token, unknown user), the endpoint will respond with 401 Unauthorized.
Cookie Login
Request body (JSON)
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
The username including the domain name when the user does not belong to the primary domain or no primary domain is set |
|
|
|
|
* |
The account password |
|
|
|
|
The value of the captcha text |
||
|
|
|
The captcha id |
||
|
|
|
The value set based on user choice |
Response
When successful, the endpoint returns the following JSON structure:
Additionally, the response will also include the following headers when applicable:
|
Name |
Type |
Present |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
The |
|
|
|
|
|
The value is set to The value is set to |
All subsequent API calls must send the _hmail cookie and include the session ID in the X-Axigen-Session header.
In case the user can not be authenticated (i.e. wrong authentication credentials, invalid captcha, unknown user), the endpoint will reply back with 401 Unauthorized.
Cookie Login with 2-Step Verification
When 2-Step Verification is administratively enabled and active (i.e. the Cookie Login endpoint includes a X-Axigen-2FA header set to required), the API client must use this endpoint to complete the 2-Step Verification.
The API client should call the List Account Security Methods endpoint with scope=2fa to obtain the list of available methods. When using either an email or sms method, a totpToken must be obtained by calling Send Token.
Alternatively, a recoveryCode can be used to complete the 2-Step Verification. Recovery codes are generated automatically when activating the 2-Step Verification. They can also be regenerated by calling Regenerate Recovery Codes.
Request body (JSON)
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
The id of the 2-Step Verification method being used |
|
|
|
|
* |
The TOTP code |
|
|
|
|
* |
One of the recovery codes received when activating 2-Step Verification or after manually regenerating the recovery codes. |
Either of methodId and totpToken or recoveryCode is required.
Response
If successful, the response will be empty.
Password Expiration 10.7+
Applies starting with Axigen X7 (10.7)
When logging in with a password that has expired (i.e. the login endpoint includes a X-Axigen-Expired-Password header set to true), the API client must use the password reset endpoint in order to change the password before doing anything else. They can check the password policy details using the account info endpoint. This happens after the 2-Step Verification, if it is configured.
Captcha
This API is only available when using cookie login.
Get Status
Query parameters
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
The username (including the domain name) for which the captcha requirement should be checked. |
Response
When successful, the endpoint returns the following JSON structure:
Get Captcha
Query parameters
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
The username (including the domain name) for which the captcha requirement should be checked. |
|
|
|
|
Typically set to the current timestamp. This is used to work around browser level caching of the captcha image. |
Response
When successful, the endpoint returns the captcha image as PNG in case captcha is required.
Additionally, the response will also include the following headers when applicable:
|
Name |
Type |
Present |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
The captcha id to be sent when calling cookie login. |
Axigen OAuth 2.0 10.7+
Applies starting with Axigen X7 (10.7)
Axigen can act as its own OAuth 2.0 authorization server, issuing access and refresh tokens for registered first party clients. This lets an application keep a user signed in without storing their password and without an external identity provider.
The flow differs from a classic third party OAuth 2.0 authorization: rather than redirecting the user to a consent screen, the client starts from an already authenticated session and exchanges it for a durable token pair. Use one of the session login methods described above to obtain that initial session.
The exchange is one way. POST /api/v1/login/code consumes the session it is called from – the session is discarded and its cookie expired as the authorization code is issued. Plan for the client to hold tokens from that point on, and to obtain any further session from POST /api/v1/session.
Flow Overview
-
Sign the user in with a session login method to obtain a session.
-
Call
POST /api/v1/login/codefrom that session to obtain a short lived authorization code. This ends the session. -
Exchange the code for an access and refresh token pair at
POST /api/v1/auth/token. No session is required for this call. -
Call
POST /api/v1/sessionwith the access token to obtain a session. -
When the access token expires, obtain a fresh pair at
POST /api/v1/auth/tokenusing the refresh token, then repeat step 4. -
On logout, revoke the refresh token with
POST /api/v1/auth/revoke.
A 401 on an ordinary API call means the session expired, not that the user must sign in again – obtain a new session at step 4. Only refresh token expiry or revocation requires a full sign in.
PKCE
Every authorization code is bound to a PKCE verifier (RFC 7636). Before requesting a code, generate a random code_verifier of 43 to 128 characters from [A-Za-z0-9-._~] and derive the challenge as BASE64URL(SHA256(code_verifier)). Send the challenge to /api/v1/login/code and the original verifier to /api/v1/auth/token.
Only the S256 method is supported. plain is rejected.
Token Lifetimes
|
Item |
Lifetime |
Notes |
|---|---|---|
|
Authorization code |
10 minutes |
Single use. Only one code may be pending per account – issuing a new one invalidates the previous. |
|
Access token |
15 minutes |
Stateless and multi use. Verified by signature alone. |
|
Refresh token |
30 days |
Single use; rotated on every refresh. |
|
Signing keys |
60 days |
The three most recent periods (previous, current and next) are accepted at any time. |
Access and refresh tokens are also rejected if they were issued at or before the account's last password change or last session invalidation, regardless of their remaining lifetime.
Registered Clients
|
clientId |
redirectUri |
|---|---|
|
|
|
Client registration is static. The redirectUri presented on a request must match the registered value for that clientId exactly.
Request an Authorization Code
Requires an authenticated session. Consumes it.
Request body (JSON)
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
Currently only |
The OAuth 2.0 client id |
|
|
|
* |
Currently only |
The OAuth 2.0 redirect uri. Must exactly match the registered URI for the given |
|
|
|
* |
The PKCE code challenge, |
|
|
|
|
* |
Must be |
The PKCE code challenge method. Only |
|
|
|
* |
An opaque value used to correlate the request with the redirect. Verify it on return |
Response
When successful, the endpoint returns the following JSON structure:
The redirect URL is the registered redirectUri with the authorization code and your state appended as percent encoded query parameters, for example axigen://auth?code=<code>&state=<state>. Confirm the returned state matches the one you sent before using the code.
The response also expires the _hmail session cookie.
Errors
|
Status |
Condition |
|---|---|
|
|
No valid session |
|
|
Unknown |
|
|
|
This endpoint returns the standard Mailbox API error envelope, not the OAuth 2.0 error format used by the endpoints below.
Exchange the Code for Tokens
Public endpoint – no session or prior authentication required. The request body must be application/x-www-form-urlencoded; any other content type is rejected.
Request body (application/x-www-form-urlencoded)
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
Must be |
The OAuth 2.0 grant type |
|
|
|
* |
The authorization code from the |
|
|
|
|
* |
43–128 characters from |
The original PKCE verifier whose SHA-256 hash was sent as |
|
|
|
If present, must match the value stored at |
Optional. When present it is validated; a mismatch is an error |
|
|
|
|
If present, must match the value stored at |
Optional. When present it is validated; a mismatch is an error |
Response
When successful, the endpoint returns the following JSON structure:
Responses carry Cache-Control: no-store.
Refresh the Token Pair
Public endpoint. Same endpoint as the code exchange, distinguished by grant_type.
Request body (application/x-www-form-urlencoded)
|
Name |
Type |
Required |
Values |
Description |
|---|---|---|---|---|
|
|
|
* |
Must be |
The OAuth 2.0 grant type |
|
|
|
* |
A valid refresh JWT |
Response
Identical in shape to the code exchange response.
Refresh tokens are rotated: each refresh returns a new pair and invalidates the token presented. Persist the new refresh token before using it, and discard the old one.
Presenting a refresh token that has already been rotated is treated as a compromise: the entire rotation family is revoked, and every token descended from that original sign in stops working. The user must sign in again. Clients should therefore serialise refresh calls and never retry a refresh with a token whose replacement has already been stored.
Open a Session
Exchanges a valid access token for a Mailbox API session. No request body.
Request Headers
|
Name |
Required |
Values |
Description |
|---|---|---|---|
|
|
* |
|
An access token previously issued by |
This endpoint is Bearer only. A request that also carries an _hmail session cookie is rejected rather than resolved in favour of one credential.
Response
When successful, the endpoint returns the following JSON structure:
Additionally, the response will also include the following header
|
Name |
Type |
Present |
Description |
|---|---|---|---|
|
|
|
* |
The |
All subsequent API calls must send the _hmail cookie and include the session ID in the X-Axigen-Session header.
Sessions created this way are treated as having completed 2-Step Verification – it was completed during the sign in that produced the authorization code.
Errors
401 Unauthorized with a WWW-Authenticate: Bearer header and an OAuth 2.0 error body. error is invalid_token when the token is missing, malformed, unverifiable, refers to an unknown user, or predates a password change or session invalidation; invalid_request when a session cookie is present; server_error when session creation fails.
Revoke a Refresh Token
Public endpoint, per RFC 7009. Call this on logout. The request body must be application/x-www-form-urlencoded.
Request body (application/x-www-form-urlencoded)
|
Name |
Type |
Required |
Description |
|---|---|---|---|
|
|
|
* |
The refresh token to revoke. Revokes the entire rotation family |
Response
If successful, the response will be empty, with 200 OK.
Per RFC 7009 the endpoint also returns 200 for tokens that are invalid, expired, or unknown, so a success response is not confirmation that a token existed. Only a missing token parameter (400) or a storage failure (500) return a non-200 status.
Verify Token Signatures
Public endpoint. Returns the public keys used to verify Axigen issued tokens, allowing a client or resource server to check them offline.
Response
When successful, the endpoint returns the following JSON structure:
Keys are derived per 60 day period, and the set covers the previous, current and next period. Cache the key set and refetch it when a token presents an unknown kid. Tokens without a kid, or with a kid outside the accepted set, are rejected.
Error Responses
/api/v1/auth/token and /api/v1/auth/revoke return RFC 6749 error bodies rather than the standard Mailbox API error envelope:
|
error |
Meaning |
|---|---|
|
|
Wrong content type, or a required parameter is missing |
|
|
The code, verifier, or refresh token was rejected – invalid, expired, replayed, revoked, or mismatched against the values recorded at authorization time |
|
|
|
|
|
Internal failure |
invalid_grant is deliberately undifferentiated: the specific reason is logged server side but not returned, to avoid aiding enumeration.