Skip to main content
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:
  1. Use your API key to request an access token
  2. Use the access token to authenticate with other Sawmills services
  3. Refresh the token as needed (tokens expire after 30 minutes by default)

Exchanging API Key for Token

API Endpoint

POST /v1/token

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

Authentication Header

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

  1. Verify API Key: Ensure your API key is correctly formatted
  2. Check Token Expiry: Verify the token hasn’t expired before using it
  3. Test with cURL: Use cURL to test token exchange independently
  4. 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

Performance

  • 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:
  1. Create API Keys if you haven’t already
  2. Integrate token-based authentication into your applications
  3. Explore the API Reference for available endpoints
  4. Set up monitoring and alerting for your API usage