Authentication
All API access begins with authentication. You exchange your credentials for a time-limited access token, which is then used for every subsequent request.
Prerequisites
- Only requests from pre-approved IP addresses are allowed to access the API
- Send
Authorization: Bearer <access_token>header in all API calls - Request ID must be passed under the header
X-REQUEST-IDin all requests for cross-system request tracking
Base URLs
| Environment | Base URL |
|---|---|
| Staging | https://api.dev.myhubble.money |
| Production | https://api.myhubble.money |
Login API
/v1/partners/auth/loginExchange your credentials for an access token. This endpoint does not require authentication — this is how you get the token.
Request Body
{
"clientId": "string",
"clientSecret": "string"
}
Response
Status 200: Login successful
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresInSecs": 3600
}
Error Responses
| Status | Meaning | Common Cause |
|---|---|---|
401 | Unauthorized | Wrong clientId/clientSecret, or staging keys on production |
400 | Bad Request | Missing fields in request body |
403 | Forbidden | Request from a non-whitelisted IP |
Typically means: (1) the clientId has a typo or is incorrect, or (2) you are hitting the wrong environment. Contact Hubble support with your clientId and environment details.
The Login endpoint requires POST. Don't hit /v1/partner/… instead of /v1/partners/… (note the plural).
Example Request
curl -X POST "https://api.dev.myhubble.money/v1/partners/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "YOUR_STAGING_CLIENT_ID",
"clientSecret": "YOUR_STAGING_CLIENT_SECRET"
}'
Token Management
The access token expires after expiresInSecs (typically 3600s / 1 hour). You must:
Cache the Token
Do not call Login before every request. Store the token and reuse it for all requests within the validity window.
// Example: Token caching
let cachedToken = null;
let tokenExpiry = null;
async function getToken() {
const now = Date.now();
// Return cached token if still valid (with 5-min buffer)
if (cachedToken && tokenExpiry && now < tokenExpiry - 300000) {
return cachedToken;
}
// Fetch new token
const response = await fetch('/v1/partners/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET
})
});
const data = await response.json();
cachedToken = data.token;
tokenExpiry = now + (data.expiresInSecs * 1000);
return cachedToken;
}
Implement Automatic Token Refresh
Recommended: refresh at 80% of expiry time (e.g., after 48 minutes for a 60-minute token).
Handle 401 Responses Mid-Session
If you receive a 401 during a request, re-authenticate and retry the failed request automatically.
Request Headers
Every API call after authentication must include these headers:
| Header | Value | Description |
|---|---|---|
Authorization | Bearer <access_token> | JWT token from the Login API |
X-REQUEST-ID | A unique UUID per request | Critical for troubleshooting with Hubble support |
Content-Type | application/json | Required for all POST requests |
Always generate a UUID for each request and log it on your side. When contacting Hubble support, providing the X-REQUEST-ID dramatically speeds up resolution.
Example Headers
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
X-REQUEST-ID: 239774a8-f59c-496c-bb52-ceb683d60af3
Content-Type: application/json
Example: Authenticated Request
curl -X GET \
https://api.dev.myhubble.money/v1/partners/products \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'X-REQUEST-ID: a-unique-uuid-here'
Setup Checklist
- Store clientId and clientSecret securely (environment variables, secrets manager)
- Implement the token acquisition flow using
/v1/partners/auth/login - Implement token refresh logic based on
expiresInSecs - Include
Authorization: Bearer {access_token}header in all API calls - Generate and log unique
X-REQUEST-IDfor every API request - Configure base URLs separately so switching environments is a config change
- Handle 401 responses by re-authenticating automatically
Next Steps
Once authentication is set up: