Documentation Index
Fetch the complete documentation index at: https://docs.sawmills.ai/llms.txt
Use this file to discover all available pages before exploring further.
Access tokens are short-lived credentials that provide authenticated access to Sawmills services. This guide explains how to exchange your API key for an access token and use it for authentication.
Overview
Sawmills uses a token exchange system where you can exchange a long-lived API key for a short-lived access token. This provides better security by limiting the exposure time of credentials.
Token Exchange Flow:
- Use your API key to request an access token
- Use the access token to authenticate with other Sawmills services
- Refresh the token as needed (tokens expire after 30 minutes by default)
Exchanging API Key for Token
API Endpoint
Authentication
Use your API key in the Authorization header with the ApiKey scheme:
Authorization: ApiKey sk_test.abc123def4.xyz789uvw0123456789abcdef
Request Body
The request body should be empty:
Response
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 1800
}
Response Fields:
access_token: JWT token for authenticating with other services
token_type: Always “Bearer” for Sawmills tokens
expires_in: Token expiration time in seconds (default: 1800 = 30 minutes)
Example: Exchanging API Key for Token with cURL
curl -X POST "https://api.sawmills.ai/v1/token" \
-H "Authorization: ApiKey sk_test.abc123def4.xyz789uvw0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{}'
Example: Exchanging API Key for Token with JavaScript
const response = await fetch('https://api.sawmills.ai/v1/token', {
method: 'POST',
headers: {
'Authorization': 'ApiKey sk_test.abc123def4.xyz789uvw0123456789abcdef',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
});
const data = await response.json();
console.log('Access token:', data.access_token);
console.log('Expires in:', data.expires_in, 'seconds');
Using Access Tokens
Use the access token in the Authorization header with the Bearer scheme:
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Example: Using Token with cURL
curl -X GET "https://api.sawmills.ai/v1/user-api-keys" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
Example: Using Token with JavaScript
const response = await fetch('https://api.sawmills.ai/v1/user-api-keys', {
method: 'GET',
headers: {
'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
}
});
const data = await response.json();
console.log('API Keys:', data.api_keys);
Token Management
Token Expiration
- Default TTL: 30 minutes (1800 seconds)
- Maximum TTL: 24 hours (configurable by organization)
- Refresh Required: Tokens cannot be refreshed; you must exchange a new token
Automatic Token Refresh
Implement automatic token refresh in your applications:
class SawmillsClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.accessToken = null;
this.tokenExpiry = null;
}
async getAccessToken() {
// Check if current token is still valid
if (this.accessToken && this.tokenExpiry && Date.now() < this.tokenExpiry) {
return this.accessToken;
}
// Exchange API key for new token
const response = await fetch('https://api.sawmills.ai/v1/token', {
method: 'POST',
headers: {
'Authorization': `ApiKey ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({})
});
if (!response.ok) {
throw new Error('Failed to obtain access token');
}
const data = await response.json();
this.accessToken = data.access_token;
this.tokenExpiry = Date.now() + (data.expires_in * 1000);
return this.accessToken;
}
async makeRequest(url, options = {}) {
const token = await this.getAccessToken();
return fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`
}
});
}
}
// Usage
const client = new SawmillsClient('sk_test.abc123def4.xyz789uvw0123456789abcdef');
const response = await client.makeRequest('https://api.sawmills.ai/v1/user-api-keys');
Error Handling
Common Error Responses
401 Unauthorized - Invalid API Key
{
"code": "UNAUTHENTICATED",
"message": "invalid api key credentials"
}
401 Unauthorized - Revoked API Key
{
"code": "UNAUTHENTICATED",
"message": "api key revoked"
}
401 Unauthorized - Invalid Format
{
"code": "UNAUTHENTICATED",
"message": "api key invalid"
}
401 Unauthorized - Missing Authorization
{
"code": "UNAUTHENTICATED",
"message": "authorization header required"
}
401 Unauthorized - Invalid Scheme
{
"code": "UNAUTHENTICATED",
"message": "authorization header must use ApiKey scheme"
}
500 Internal Server Error - Token Issuance Failed
{
"code": "INTERNAL",
"message": "failed to mint access token"
}
Handling Token Errors
async function handleTokenExchange(apiKey) {
try {
const response = await fetch('https://api.sawmills.ai/v1/token', {
method: 'POST',
headers: {
'Authorization': `ApiKey ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({})
});
if (!response.ok) {
const error = await response.json();
switch (error.code) {
case 'UNAUTHENTICATED':
if (error.message.includes('revoked')) {
throw new Error('API key has been revoked. Please create a new one.');
} else if (error.message.includes('invalid')) {
throw new Error('Invalid API key. Please check your credentials.');
} else {
throw new Error('Authentication failed. Please check your API key.');
}
case 'INTERNAL':
throw new Error('Server error. Please try again later.');
default:
throw new Error(`Unexpected error: ${error.message}`);
}
}
return await response.json();
} catch (error) {
console.error('Token exchange failed:', error.message);
throw error;
}
}
Security Considerations
Token Storage
- Store access tokens in memory only (not persistent storage)
- Never log or expose access tokens
- Implement secure token refresh mechanisms
API Key Security
- Keep your API key secure and never expose it in client-side code
- Use environment variables or secure key management systems
- Rotate API keys regularly
Network Security
- Always use HTTPS for token exchange and API calls
- Validate SSL certificates
- Consider using certificate pinning for additional security
Troubleshooting
Common Issues
“Authorization header required”
- Ensure you’re including the Authorization header in your request
- Check that the header is properly formatted
“Authorization header must use ApiKey scheme”
- Use
ApiKey (not Bearer) when exchanging API keys for tokens
- Format:
Authorization: ApiKey YOUR_API_KEY
“Invalid API key credentials”
- Verify your API key is correct and active
- Check that the API key hasn’t been revoked
- Ensure the API key is correctly formatted
“Failed to mint access token”
- This is a server-side error
- Check Sawmills service status
- Contact support if the issue persists
Debugging Tips
- Verify API Key: Ensure your API key is correctly formatted
- Check Token Expiry: Verify the token hasn’t expired before using it
- Test with cURL: Use cURL to test token exchange independently
- Review Logs: Check application logs for detailed error information
Best Practices
Application Design
- Implement automatic token refresh
- Handle token expiration gracefully
- Use connection pooling for better performance
- Implement retry logic with exponential backoff
Error Handling
- Always check response status codes
- Implement proper error handling for all failure cases
- Log errors for debugging (without exposing sensitive data)
- Provide meaningful error messages to users
- Cache tokens in memory to avoid unnecessary exchanges
- Use appropriate timeouts for API calls
- Implement circuit breakers for resilience
- Monitor token exchange success rates
Next Steps
Now that you understand how to obtain and use tokens, you can:
- Create API Keys if you haven’t already
- Integrate token-based authentication into your applications
- Set up monitoring and alerting for your API usage