Authentication
Authentication Flow
All protected endpoints require a Bearer access token. The flow is:
- Exchange your
api_key+api_secretfor a short-lived access token - Attach the token to subsequent requests via the
Authorizationheader
Authorization: Bearer <access_token>
Tokens are valid for 4 hours. Re-issue a new token before expiry.
Authentication — POST /v1/auth/token
Exchange your API key and secret for a short-lived Bearer access token. All protected API endpoints require this token.
Request
POST /v1/auth/token
Content-Type: application/json
Body Parameters
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
api_key |
string | Yes | max 64 chars | Your API key identifier |
api_secret |
string | Yes | max 128 chars | Your API secret |
Example
curl -X POST api.heldsway.com/api//v1/auth/token \
-H "Content-Type: application/json" \
-d '{
"api_key": "hs_key_xxxxxxxxxxxxxxxx",
"api_secret": "hs_secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}'
Success Response
HTTP 200 OK
{
"success": true,
"message": "Token issued successfully.",
"data": {
"access_token": "AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj",
"token_type": "Bearer",
"expires_in": 14400,
"scopes": ["reports:read"]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
access_token |
string | Opaque token string. Use in Authorization header. |
token_type |
string | Always "Bearer" |
expires_in |
integer | Token lifetime in seconds (currently 14400 = 4 hours) |
scopes |
string[] | Scopes this token grants access to |
Using the Token
Attach the token to all subsequent API requests via the Authorization header:
Authorization: Bearer <access_token>
Example
curl api.heldsway.com/api//v1/affiliate/analytics?section=stats \
-H "Authorization: Bearer AbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIjKlMnOpQrStUvWxYzAbCdEfGhIj"
Token Expiry & Re-issuance
- Tokens expire after 4 hours (
expires_in: 14400seconds). - There is no refresh mechanism — simply call
POST /v1/auth/tokenagain to get a new token. - Re-issue the token before it expires to avoid interruption. A safe strategy is to re-issue when less than 10 minutes remain.
Error Reference
| HTTP Status | Error Code | Cause |
|---|---|---|
401 |
UNAUTHORIZED |
api_key not found, or api_secret does not match |
401 |
UNAUTHORIZED |
API key is inactive or has expired |
403 |
FORBIDDEN |
The business associated with the API key is inactive |
422 |
VALIDATION_ERROR |
Missing or invalid request body fields |
503 |
SERVICE_UNAVAILABLE |
Temporary authentication service failure |
Error Response Examples
Invalid credentials (401)
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API credentials."
}
}
Inactive API key (401)
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "API key is inactive or expired."
}
}
Inactive business (403)
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "The business associated with this API key is inactive."
}
}
Validation error (422)
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"api_key": ["The api key field is required."]
}
}
}
Rate Limiting
This endpoint is throttled at 120 requests per minute per IP address. Exceeding the limit returns HTTP 429 Too Many Requests.