Authentication Guide
Overview
The Events Content Calendar API uses OAuth 2.0 Client Credentials flow for authentication. All API requests require a valid JWT (JSON Web Token) access token included in the Authorization header.
Authentication Flow
Step 1: Obtain Client Credentials
Before you can authenticate, you need:
- Client ID: Your unique client identifier
- Client Secret: Your confidential secret key
- API Scope: The scope of access granted to your application
These credentials will be provided to you during the onboarding process or you can request them from your account manager.
Keep your client secret confidential. Never expose it in client-side code or public repositories.
Step 2: Request an Access Token
Send a POST request to the token endpoint to obtain a JWT access token.
Token Endpoint
https://wsg-auth.auth.us-east-1.amazoncognito.com/oauth2/token
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
grant_type | string | Yes | Must be client_credentials |
client_id | string | Yes | Your client identifier |
client_secret | string | Yes | Your client secret |
scope | string | Yes | Your API scope |
Example Request (cURL)
curl -X POST \
https://wsg-auth.auth.us-east-1.amazoncognito.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<your-client-id>" \
-d "client_secret=<your-client-secret>" \
-d "scope=<your-api-scope>"
Success Response
{
"access_token": "eyJraWQiOiJ...",
"expires_in": 3600,
"token_type": "Bearer"
}
| Field | Description |
|---|---|
access_token | The JWT access token to use for API requests |
expires_in | Token expiration time in seconds (typically 3600 = 1 hour) |
token_type | Always Bearer |
Step 3: Use the Access Token
Include the access token in the Authorization header of all API requests.
Header Format
Authorization: Bearer <your-access-token>
Making Authenticated Requests
Using cURL
curl -X POST \
https://alt-api.prod.ahotu.com/graphql \
-H "Authorization: Bearer eyJraWQiOiJ..." \
-H "Content-Type: application/json" \
-d '{
"query": "query { events(page: 0, size: 10) { totalCount } }"
}'
Using JavaScript/TypeScript
const token = "eyJraWQiOiJ...";
const response = await fetch('https://alt-api.prod.ahotu.com/graphql', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
query {
events(page: 0, size: 10) {
totalCount
data {
id
name { en }
}
}
}
`
})
});
const data = await response.json();
console.log(data);
Using Python
import requests
token = "eyJraWQiOiJ..."
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
query = """
query {
events(page: 0, size: 10) {
totalCount
data {
id
name { en }
}
}
}
"""
response = requests.post(
'https://alt-api.prod.ahotu.com/graphql',
headers=headers,
json={'query': query}
)
data = response.json()
print(data)
Token Management
Token Expiration
Access tokens typically expire after 1 hour (3600 seconds). You must request a new token when the current one expires.
Best Practices
- Cache the Token: Store the access token and reuse it until it expires
- Monitor Expiration: Track the
expires_invalue to know when to refresh - Refresh Proactively: Request a new token shortly before expiration (e.g., 5 minutes before)
- Handle 401 Errors: If you receive a 401 Unauthorized error, request a new token
Token Caching Example (JavaScript)
class TokenManager {
constructor(clientId, clientSecret, scope) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.scope = scope;
this.token = null;
this.expiresAt = null;
}
async getToken() {
// Return cached token if still valid
if (this.token && this.expiresAt > Date.now()) {
return this.token;
}
// Request new token
const response = await fetch(
'https://wsg-auth.auth.us-east-1.amazoncognito.com/oauth2/token',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret,
scope: this.scope,
}),
}
);
const data = await response.json();
this.token = data.access_token;
// Set expiration 5 minutes before actual expiration
this.expiresAt = Date.now() + (data.expires_in - 300) * 1000;
return this.token;
}
}
// Usage
const tokenManager = new TokenManager(
'your-client-id',
'your-client-secret',
'your-scope'
);
const token = await tokenManager.getToken();
Error Handling
Common Authentication Errors
401 Unauthorized
Cause: Token is missing, invalid, or expired
Solution: Request a new access token
{
"errors": [
{
"message": "Unauthorized",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
]
}
400 Bad Request (Token Endpoint)
Cause: Invalid client credentials or malformed request
Solution: Verify your client ID, secret, and request parameters
{
"error": "invalid_client"
}
403 Forbidden
Cause: Token is valid but lacks required permissions
Solution: Contact your account manager to verify your API scope
{
"errors": [
{
"message": "Forbidden",
"extensions": {
"code": "FORBIDDEN"
}
}
]
}
Security Best Practices
1. Protect Your Credentials
- Never commit credentials to version control
- Use environment variables or secure credential stores
- Rotate credentials regularly
- Restrict access to credentials within your organization
2. Use HTTPS Only
All API requests must use HTTPS. HTTP requests will be rejected.
3. Implement Token Refresh Logic
Don't wait for requests to fail. Implement proactive token refresh before expiration.
4. Monitor for Unusual Activity
Track API usage and set up alerts for:
- Unusual request volumes
- Failed authentication attempts
- Requests from unexpected IP addresses
5. Principle of Least Privilege
Request only the API scope you need for your application.
Environment Variables
Store your credentials securely using environment variables:
# .env file (never commit this file)
API_CLIENT_ID=your-client-id
API_CLIENT_SECRET=your-client-secret
API_SCOPE=your-scope
API_BASE_URL=https://alt-api.prod.ahotu.com/graphql
AUTH_URL=https://wsg-auth.auth.us-east-1.amazoncognito.com/oauth2/token
Access in your application:
const clientId = process.env.API_CLIENT_ID;
const clientSecret = process.env.API_CLIENT_SECRET;
const scope = process.env.API_SCOPE;
Testing Authentication
Quick Test with cURL
# 1. Get token
TOKEN=$(curl -s -X POST \
https://wsg-auth.auth.us-east-1.amazoncognito.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=<your-client-id>" \
-d "client_secret=<your-client-secret>" \
-d "scope=<your-scope>" \
| jq -r '.access_token')
# 2. Test API request
curl -X POST \
https://alt-api.prod.ahotu.com/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"query { events(page: 0, size: 1) { totalCount } }"}'
Next Steps
- 📘 Review Query Examples to start making API requests
- 🚀 Explore the Data Model to understand the API structure
- 📊 Check Best Practices for optimal API usage