Skip to main content

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.

Security Note

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

ParameterTypeRequiredDescription
grant_typestringYesMust be client_credentials
client_idstringYesYour client identifier
client_secretstringYesYour client secret
scopestringYesYour 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"
}
FieldDescription
access_tokenThe JWT access token to use for API requests
expires_inToken expiration time in seconds (typically 3600 = 1 hour)
token_typeAlways 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

  1. Cache the Token: Store the access token and reuse it until it expires
  2. Monitor Expiration: Track the expires_in value to know when to refresh
  3. Refresh Proactively: Request a new token shortly before expiration (e.g., 5 minutes before)
  4. 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