Step-by-step guide to obtaining, using, and refreshing tokens with Maximizer OAuth.
This guide walks through the OAuth 2.0 Authorization Code Grant with Maximizer Cloud, from the first redirect to refreshing tokens. If you don't have a client_id yet, see the prerequisites first.
Try it without writing any codeThe Test Console runs this entire flow in your browser: sign in, exchange the code, and inspect the tokens you get back.
Note: This guide uses the Maximizer Cloud endpoints. For on-premise installations the flow is the same, but the endpoint URLs differ. See OAuth for Maximizer On-Premise.
Step 1: Request an Authorization Code
Redirect the user's browser to the Authorize endpoint:
https://auth.maximizer.com/v1/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&state={csrf_token}
Required Parameters
| Parameter | Description |
|---|---|
response_type | Must always be "code". |
client_id | The 20-character client ID issued for your application by Maximizer. |
redirect_uri | The registered Redirect URI for your application in Maximizer, starting with "https". Must match exactly and cannot include additional URL parameters. Use the state parameter for extra data. |
Optional Parameters
| Parameter | Description |
|---|---|
scope | A space-delimited list of access scopes requested. Defaults to "data" if not provided. Available scopes: data grants read and write access to Maximizer data via the Octopus API, Ferret API, or Webhooks API; data.readonly grants read-only access; webaccess grants access to Maximizer UI APIs. |
state | An alphanumeric value to maintain state between the request and callback. Recommended to prevent CSRF attacks by verifying this value upon return. |
code_challenge | The PKCE code challenge: the Base64URL-encoded SHA-256 hash of a random code_verifier generated by your application. Required for public clients that do not use a client_secret; recommended for all clients. |
code_challenge_method | Must be the literal value "SHA256" when code_challenge is supplied. Note: Maximizer OAuth uses "SHA256", not the "S256" value used by some other providers. |
Note: All parameter values must be URL-encoded.
Example
https://auth.maximizer.com/v1/authorize?response_type=code&client_id=a82cz44dydhu00k2wpfb&redirect_uri=https%3A%2F%2Fwww.example.com%2Fmyapp%2Foauth&state=xyzABC123
For a public client using PKCE, include the code challenge parameters:
https://auth.maximizer.com/v1/authorize?response_type=code&client_id=a82cz44dydhu00k2wpfb&redirect_uri=https%3A%2F%2Fwww.example.com%2Fmyapp%2Foauth&state=xyzABC123&code_challenge=E9Mel3rzKG3wUyDbTC7LXbAHJi7cf1EY3lFDPqtCCXY&code_challenge_method=SHA256
Step 2: User Sign-In and Approval
The user signs in and grants your application access to their Maximizer resources:
%%{init: {"themeVariables": {"fontSize": "18px"}}}%%
flowchart LR
A["Confirm email"] --> B["Select account"]
B --> C{"Sign-in method"}
C -- "Password" --> D["Enter password"]
C -- "SSO" --> E["Sign in with identity provider"]
D --> F["Redirect back with code"]
E --> F
- E-mail confirmation. The user enters their e-mail address and receives a 6-digit confirmation code (and a magic link) by e-mail. Entering the code, or opening the link, confirms ownership of the address. Returning users on the same browser skip this step for up to 90 days.
- Account selection. If several Maximizer accounts are associated with the e-mail address, the user picks one; a single account is selected automatically.
- Credentials or SSO. The user signs in with their Maximizer password. If their account is configured for single sign-on, they are handed off to their identity provider instead. Accounts that only allow SSO skip the password form automatically.
Your application does not need to know the user's region, account, or sign-in method; all of it is resolved from the user's e-mail address.
Step 3: Receive the Authorization Code
After the user grants permission, the browser is redirected back to your application's redirect_uri.
Success Redirect
{redirect_uri}?code={authorization_code}&state={state_parameter}&login_hint=d%20{database_name}%20u%20USER_ID
{authorization_code}: Authorization code for requesting an access token. It is single-use and expires after 2 minutes, so your application should exchange it immediately.{state_parameter}: Value supplied in the original request for CSRF protection.{database_name}: Identifier of the database that was authorized.USER_ID: ID of the user who granted access.
Error Redirect
{redirect_uri}?error={error}&error_description={description}&state={state_parameter}
{error}: Error code.{description}: Detailed error description.{state_parameter}: Value supplied in the original request for CSRF protection.
Note: If the user cancels the sign-in, the error redirect includes error_code=14.
Step 4: Exchange the Code for Tokens
Make an HTTP POST request to the Token endpoint with the following parameters:
| Parameter | Description |
|---|---|
grant_type | Must be "authorization_code". |
client_id | Your application's 20-character client ID. Must match the client_id used in the authorization request. |
client_secret | Your application's 64-character client secret. Required for confidential clients; public clients using PKCE send code_verifier instead. |
code_verifier | The PKCE code verifier whose SHA-256 hash was sent as code_challenge in Step 1. Required when the authorization request included a code_challenge. |
redirect_uri | The same Redirect URI used in the authorization request. |
code | The authorization code received in Step 3. This value can vary in length. |
Note: Parameters must be sent in the request body as application/x-www-form-urlencoded. Parameters passed in the URL query string are ignored, and the request will fail with HTTP 400.
Example Request
POST /v1/token HTTP/1.1
Host: auth.maximizer.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&client_id=a82cz44dydhu00k2wpfb&client_secret=pv28mq41bj1qvwouti64o9ourmlju42iq7n94hjonmf7ylge89k1znm7u16s6yx7&redirect_uri=https%3A%2F%2Fwww.example.com%2Fmyapp%2Foauth&code=n6cnsjcjzoo96e9y2e8sResponse
A successful token request returns a JSON object:
| Parameter | Description |
|---|---|
access_token | Token for accessing Maximizer APIs. |
token_type | Type of token; always "Bearer". |
expires_in | Time in seconds before the access token expires (e.g., 600). |
refresh_token | Token used to obtain a new access token. |
Note: Both tokens vary in length and can be long. Treat them as opaque strings, and do not store them in persistent storage that assumes a fixed length.
Example Response
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJteC1jaWQiOi...",
"token_type": "Bearer",
"expires_in": 600,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6InJlZnJlc2gifQ.eyJpc3MiOi..."
}If an error occurs, the response is returned with HTTP status 400. See Error Handling below.
Step 5: Call Maximizer APIs
With the access_token, your application can make authorized requests to Maximizer APIs such as the Octopus API, Ferret API, or Webhooks API. Refer to the relevant API documentation for usage details.
Send the token in the Authorization header with the Bearer prefix:
Authorization: Bearer <access_token>
Step 6: Refresh the Tokens
Access tokens are short-lived. Use the refresh_token to obtain a new pair of tokens without requiring the user to sign in again. Make an HTTP POST request to the Token endpoint with the following parameters:
| Parameter | Description |
|---|---|
grant_type | Must be "refresh_token". |
client_id | Your application's 20-character client ID. |
client_secret | Your application's 64-character client secret. Not required for public clients using PKCE. |
redirect_uri | The same Redirect URI registered in Maximizer. |
refresh_token | The refresh token received from the previous token request. |
Note: Parameters must be sent in the request body as application/x-www-form-urlencoded. Parameters passed in the URL query string are ignored, and the request will fail with HTTP 400.
Example Request
POST /v1/token HTTP/1.1
Host: auth.maximizer.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&client_id=a82cz44dydhu00k2wpfb&client_secret=pv28mq41bj1qvwouti64o9ourmlju42iq7n94hjonmf7ylge89k1znm7u16s6yx7&redirect_uri=https%3A%2F%2Fwww.example.com%2Fmyapp%2Foauth&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6InJlZnJlc2gifQ.eyJpc3MiOi...The response has the same format as in Step 4 and contains a new access token and a new refresh token. Store the new refresh token, because the previous one is no longer valid.
Token Lifetimes
| Token | Lifetime | Notes |
|---|---|---|
| Authorization code | 2 minutes | Single-use. Exchange it immediately. |
| Access token | 10 minutes (600 s) | Each use extends its validity by another 10 minutes, up to a maximum lifespan of 24 hours. After that, refresh or re-authorize. |
| Refresh token | Up to 180 days (6 months) | Single-use. Each refresh issues a new access + refresh token pair and invalidates the previous refresh token. |
If a refresh request times out before your application receives the response, you may safely retry the same refresh token within approximately 60 seconds. Instead of a reuse error, the same new token pair will be returned. Past that window, the old refresh token is permanently invalid.
Error Handling
Every failed token request returns HTTP status 400 with a JSON body:
| Property | Description |
|---|---|
error | OAuth2 error code. |
error_code | Numeric error code. Codes 3000 and above originate from Maximizer OAuth itself. |
error_description | Detailed error description. |
Your application must branch on the error and error_code fields of the response body, not on the HTTP status code, to decide whether to retry or re-authenticate:
error | error_code | Meaning | Recommended action |
|---|---|---|---|
invalid_grant | 3001 | The refresh token is invalid or expired. | Re-authenticate the user (Step 1). |
invalid_grant | other (e.g. 4) | The refresh token was expired, revoked, or already used. | Re-authenticate the user (Step 1). |
temporarily_unavailable | 3005 | A transient error occurred while processing the request. | Retry with backoff. |
Important: Do not treat every 400 response as a revoked session. An application that logs the user out on every error will drop still-valid sessions on a transient failure. Retry on temporarily_unavailable; re-authenticate only on invalid_grant.
Using an OAuth2 Library
To ensure security and reliability, it's strongly recommended to use an established open-source OAuth2 library for your platform and language. For a list of available libraries, visit the OAuth2 homepage.
