Get a bearer token
Exchanges a customer’s email address and password for a short-lived bearer token and a refresh token. Every authenticated API call in the Members Portal uses the access_token returned here as a Bearer credential. Pass totp when the customer has two-factor authentication enabled — omitting it when 2FA is active will return a two_factor_auth_check error.
Unlike most Nexudus API endpoints, this request must be encoded as application/x-www-form-urlencoded, not application/json. Sending a JSON
body will result in an unsupported_grant_type error.
Authentication
No authentication required. This is the endpoint that issues credentials.
Request Body
Grant flow to use. Must be password for email/password authentication.
The customer’s email address.
Time-based One-Time Password for two-factor authentication. Required when the customer has 2FA enabled; omit otherwise.
Response
Bearer token to include in the Authorization header of all subsequent authenticated requests.
Token scheme. Always bearer.
Lifetime of the access token in seconds.
Token used to obtain a new access_token after it expires, without requiring the customer to re-enter their password.
Examples
Successful sign-in
POST /api/token
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=jane.doe%40example.com&password=S3cur3P%40ss
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 86400,
"refresh_token": "8xLOxBtZp8"
}
Sign-in with two-factor authentication
POST /api/token
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=jane.doe%40example.com&password=S3cur3P%40ss&totp=482910
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"expires_in": 86400,
"refresh_token": "8xLOxBtZp8"
}
TypeScript Integration
import { type AxiosResponse } from 'axios'
import qs from 'qs'
import { AuthToken } from '@/states/useAuthContext'
const data = {
grant_type: 'password',
username: values.email,
password: values.password,
totp: values.totp,
}
const res: AxiosResponse<AuthToken> = await httpClient.post('/api/token', qs.stringify(data), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
})
if (res.data.access_token) {
saveSession({ tokenResponse: res.data, remember: values.rememberMe })
}
Usage in Portal
| Context | Source file |
|---|
Sign-in page (/signin) | src/views/auth/SignIn/useSignIn.ts |
Error Responses
400 Bad Request — unsupported_grant_type
The grant_type field is missing or the body was not encoded as application/x-www-form-urlencoded.
400 Bad Request — invalid_grant
Credentials are incorrect, the customer is not registered with this location, or the account has been suspended. The error_description field
contains a human-readable reason.
400 Bad Request — two_factor_auth_check
The customer has 2FA enabled but totp was not supplied or the supplied code is invalid. Prompt the customer for their one-time code and retry.
400 Bad Request — must_reset_password
The customer is required to reset their password before signing in. The error_description field contains a password-reset token to pass to the
reset-password flow.
| Method | Endpoint | Description |
|---|
POST | /api/token | (this endpoint) Exchange credentials for a bearer token |
GET | /api/public/billing/customer | Retrieve the authenticated customer’s profile |
GET | /api/public/teams/my | List teams the authenticated customer belongs to |