Token Refresh

Session JWTs expire after 15 days. Use the refresh token to obtain a new session JWT without requiring the user to log in again.

Refresh Flow


Automatic Refresh Strategy

Refresh the token before it expires to prevent authentication failures:

import requests
from datetime import datetime, timedelta
import jwt
 
class ChordianClient:
    def __init__(self):
        self.token = None
        self.token_expires_at = None
        self.base_url = "https://chordian-core.chordian.ai"
    
    def should_refresh_token(self):
        """Check if token expires in next hour"""
        if not self.token_expires_at:
            return True
        
        expires_soon = datetime.now() + timedelta(hours=1)
        return datetime.now() >= expires_soon
    
    def refresh_token(self):
        """Refresh the session JWT"""
        response = requests.post(
            f"{self.base_url}/api/auth/refresh",
            # Cookies are automatically sent
        )
        
        if response.status_code == 200:
            data = response.json()
            self.token = data['token']
            
            # Decode to get expiration
            decoded = jwt.decode(
                self.token, 
                options={"verify_signature": False}
            )
            self.token_expires_at = datetime.fromtimestamp(decoded['exp'])
            
            return True
        elif response.status_code == 401:
            # Refresh token expired, need to re-login
            raise Exception("Refresh token expired, please login again")
        else:
            raise Exception(f"Refresh failed: {response.status_code}")
    
    def make_request(self, method, endpoint, **kwargs):
        """Make authenticated request with auto-refresh"""
        if self.should_refresh_token():
            self.refresh_token()
        
        headers = kwargs.get('headers', {})
        headers['Authorization'] = f'Bearer {self.token}'
        kwargs['headers'] = headers
        
        return requests.request(method, f"{self.base_url}{endpoint}", **kwargs)
 
# Usage
client = ChordianClient()
response = client.make_request('POST', '/api/workflow/start', json={
    'prompt': 'Find SaaS companies',
    'serviceId': 'srv_123'
})

Manual Refresh

For simple use cases, manually refresh when needed:

curl -X POST https://chordian-core.chordian.ai/api/auth/refresh \
  -H "Cookie: refresh_token=your-refresh-token" \
  -H "Content-Type: application/json"

Response

200 OK:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expiresIn": 1296000
}

401 Unauthorized:

{
  "error": {
    "code": "INVALID_REFRESH_TOKEN",
    "message": "Refresh token expired or invalid",
    "status": 401
  }
}

Best Practices

💡 Tip: Refresh proactively - Don’t wait for the token to expire. Refresh 1 hour before expiration.

  1. Store expiration time - Decode JWT and track exp claim
  2. Implement retry logic - If refresh fails with 401, redirect to login
  3. Handle concurrent requests - Queue requests during refresh to avoid race conditions
  4. Secure refresh tokens - Always use httpOnly cookies

Troubleshooting

ErrorCauseSolution
400 Bad RequestNo refresh token in cookieRe-login to get new refresh token
401 UnauthorizedRefresh token expired (>30 days)User must log in again
500 Internal ErrorServer issueRetry with exponential backoff

Next Steps