Exchange a Mailhub API key for a short-lived access token and a longer-lived refresh token, then use the access token as a Bearer credential on every other request. Refreshing is a true rotation (the spent refresh token is invalidated); revoking is idempotent. The optional `X-SubAccount-Id` header is validated at token exchange but is not persisted in either token, so it changes nothing about the session — see each operation's own header description for that operation's exact effect. Never log an access token, refresh token, or API key in application logs, error trackers, or support tickets.
Operations
POST /api/v1/auth/token
Create access token
Authenticates the client with an API key
Authentication: none — this operation does not require a bearer credential.
Parameters
| Name | In | Type | Required | Description |
|---|
X-SubAccount-Id | header | string (uuid) | optional | Optional. Validates that the given sub-account exists and is active for your account (404/409 if not), but the result is not persisted — it is never embedded in the returned access token, the refresh token, or the response, and has no effect on any later request. Example: 3a7d9e21-6b48-4c15-9f2e-7d0c5b83a614 |
|---|
Request body (required)
Responses
| Status | Description | Body |
|---|
200 | Authenticated successfully | application/json — CreateAccessTokenResponseEnvelope
|
|---|
400 | Invalid request data | application/json — ErrorEnvelope
|
|---|
401 | Invalid API key or token | application/json — ErrorEnvelope
|
|---|
404 | Sub-account not found | application/json — ErrorEnvelope
|
|---|
409 | Sub-account inactive | application/json — ErrorEnvelope
|
|---|
415 | The request was sent with a `Content-Type` other than `application/json`. Answered by middleware ahead of authentication, so it is reachable on every write operation. | application/json — ErrorEnvelope
|
|---|
422 | Validation errors | application/json — ErrorEnvelope
|
|---|
500 | The request could not be completed because of an unexpected server-side failure. | application/json — ErrorEnvelope
|
|---|
POST /api/v1/auth/token/refresh
Refresh access token
Refreshes the access token using a refresh token
Authentication: none — this operation does not require a bearer credential.
Parameters
| Name | In | Type | Required | Description |
|---|
X-SubAccount-Id | header | string (uuid) | optional | Not read by this operation. A malformed value still fails with 400 (checked globally, ahead of routing); a well-formed value has no effect — refresh never reads or persists a sub-account scope. Example: 3a7d9e21-6b48-4c15-9f2e-7d0c5b83a614 |
|---|
Request body (required)
Responses
| Status | Description | Body |
|---|
200 | Token refreshed successfully | application/json — RefreshAccessTokenResponseEnvelope
|
|---|
400 | Invalid request data | application/json — ErrorEnvelope
|
|---|
401 | Invalid or expired refresh token | application/json — ErrorEnvelope
|
|---|
415 | The request was sent with a `Content-Type` other than `application/json`. Answered by middleware ahead of authentication, so it is reachable on every write operation. | application/json — ErrorEnvelope
|
|---|
422 | Validation errors | application/json — ErrorEnvelope
|
|---|
500 | The request could not be completed because of an unexpected server-side failure. | application/json — ErrorEnvelope
|
|---|
POST /api/v1/auth/token/revoke
Revoke refresh token
Revokes the refresh token
Authentication: none — this operation does not require a bearer credential.
Parameters
| Name | In | Type | Required | Description |
|---|
X-SubAccount-Id | header | string (uuid) | optional | Not read by this operation. A malformed value still fails with 400 (checked globally, ahead of routing); a well-formed value has no effect — revoke never reads or persists a sub-account scope. Example: 3a7d9e21-6b48-4c15-9f2e-7d0c5b83a614 |
|---|
Request body (required)
Responses
| Status | Description | Body |
|---|
200 | Logout completed successfully | application/json — RevokeRefreshTokenResponseEnvelope
|
|---|
400 | Invalid request data | application/json — ErrorEnvelope
|
|---|
401 | Invalid refresh token | application/json — ErrorEnvelope
|
|---|
415 | The request was sent with a `Content-Type` other than `application/json`. Answered by middleware ahead of authentication, so it is reachable on every write operation. | application/json — ErrorEnvelope
|
|---|
422 | Validation errors | application/json — ErrorEnvelope
|
|---|
500 | The request could not be completed because of an unexpected server-side failure. | application/json — ErrorEnvelope
|
|---|
Schemas
The public schemas the operations above reference. Each is listed once; a type name in the tables above links to its fields here.ApiError
One thing that went wrong.
| Field | Type | Required | Description |
|---|
code | string | required | Machine-readable error identifier, dotted and stable — for example Order.NotFound. Branch
on this rather than on message. |
|---|
message | string | required | Readable explanation of the failure. Wording may change; do not parse it. |
|---|
metaData | object nullable | optional | Extra detail about this particular failure. Its shape depends on code. |
|---|
CreateAccessTokenRequest
Exchanges an API key for an access token.
| Field | Type | Required | Description |
|---|
apiKey | string | required | The API key issued to your Mailhub account. It is exchanged here for a short-lived access
token and is not accepted as credentials on any other operation. |
|---|
CreateAccessTokenResponse
A freshly issued token pair and the account and key it belongs to.
| Field | Type | Required | Description |
|---|
accessToken | string | required | Bearer token to send as the Authorization: Bearer <token> header on subsequent
calls. |
|---|
accessTokenExpiresAtUtc | string (date-time) | required | UTC instant after which the access token is no longer accepted. Format: date-time |
|---|
accountId | string (guid) | required | Identifier of the Mailhub account the API key belongs to. Orders, shipments and labels
created with the issued token are scoped to this account. Format: guid |
|---|
apiKeyId | string (guid) | required | Identifier of the API key the token was issued from. Distinguishes which of an account's
keys produced this token when several are in use. Format: guid |
|---|
refreshToken | string | required | Token that buys a new access token without re-sending the API key. Send it to the token
refresh operation. |
|---|
refreshTokenExpiresAtUtc | string (date-time) | required | UTC instant after which the refresh token can no longer be exchanged and a new API-key
exchange is needed. Format: date-time |
|---|
CreateAccessTokenResponseEnvelope
The envelope every JSON operation answers with: a success flag and either a result or errors.
| Field | Type | Required | Description |
|---|
data | CreateAccessTokenResponse nullable | required | The operation's result. Absent when the call failed. |
|---|
errors | ApiError[] nullable | required | What went wrong. Absent when the call succeeded. |
|---|
success | boolean | required | Whether the operation succeeded. When false, read errors. |
|---|
ErrorEnvelope
The envelope every JSON operation answers with: a success flag and either a result or errors.
| Field | Type | Required | Description |
|---|
data | object nullable | required | The operation's result. Absent when the call failed. |
|---|
errors | ApiError[] | required | What went wrong. Absent when the call succeeded. |
|---|
success | boolean | required | Whether the operation succeeded. When false, read errors. |
|---|
RefreshAccessTokenRequest
Exchanges a refresh token for a new token pair.
| Field | Type | Required | Description |
|---|
refreshToken | string | required | The refresh token returned by a previous token or refresh call. |
|---|
RefreshAccessTokenResponse
A replacement token pair. The refresh token sent in the request is consumed.
| Field | Type | Required | Description |
|---|
accessToken | string | required | Replacement bearer token to send as the Authorization: Bearer <token> header. |
|---|
accessTokenExpiresAtUtc | string (date-time) | required | UTC instant after which the access token is no longer accepted. Format: date-time |
|---|
accountId | string (guid) | required | Identifier of the Mailhub account the API key belongs to. Orders, shipments and labels
created with the issued token are scoped to this account. Format: guid |
|---|
apiKeyId | string (guid) | required | Identifier of the API key the token was issued from. Distinguishes which of an account's
keys produced this token when several are in use. Format: guid |
|---|
refreshToken | string | required | Replacement refresh token. Use this one for the next refresh — the token sent in the
request is consumed. |
|---|
refreshTokenExpiresAtUtc | string (date-time) | required | UTC instant after which the refresh token can no longer be exchanged and a new API-key
exchange is needed. Format: date-time |
|---|
RefreshAccessTokenResponseEnvelope
The envelope every JSON operation answers with: a success flag and either a result or errors.
| Field | Type | Required | Description |
|---|
data | RefreshAccessTokenResponse nullable | required | The operation's result. Absent when the call failed. |
|---|
errors | ApiError[] nullable | required | What went wrong. Absent when the call succeeded. |
|---|
success | boolean | required | Whether the operation succeeded. When false, read errors. |
|---|
RevokeRefreshTokenRequest
Revokes a refresh token.
| Field | Type | Required | Description |
|---|
refreshToken | string | required | The refresh token to revoke. Revoking stops any further refresh; an access token already
issued from it stays usable until its own expiry. |
|---|
RevokeRefreshTokenResponse
The outcome of revoking a refresh token.
| Field | Type | Required | Description |
|---|
isSuccess | boolean | required | Whether the refresh token was revoked. |
|---|
RevokeRefreshTokenResponseEnvelope
The envelope every JSON operation answers with: a success flag and either a result or errors.
| Field | Type | Required | Description |
|---|
data | RevokeRefreshTokenResponse nullable | required | The operation's result. Absent when the call failed. |
|---|
errors | ApiError[] nullable | required | What went wrong. Absent when the call succeeded. |
|---|
success | boolean | required | Whether the operation succeeded. When false, read errors. |
|---|