Skip to main content

Python Integration

Integrate Tokencraft design tokens into your Python applications.

Quick Start

Install Dependencies

pip install requests python-dotenv

Basic Usage

import requests
import os
from dotenv import load_dotenv

load_dotenv()

TOKENCRAFT_TOKEN = os.getenv('TOKENCRAFT_TOKEN')
API_BASE = 'https://app.tokencraft.dev/api/v1'

def fetch_tokens(tokenset_id, mode_id, format='json'):
    """Fetch tokens from Tokencraft API"""
    url = f'{API_BASE}/tokensets/{tokenset_id}/modes/{mode_id}/export'
    
    response = requests.get(
        url,
        params={'format': format},
        headers={'Authorization': f'Bearer {TOKENCRAFT_TOKEN}'}
    )
    
    response.raise_for_status()
    
    return response.json() if format == 'json' else response.text

# Usage
tokens = fetch_tokens('tokenset-123', 'mode-light', 'json')
print(tokens)

API Client Class

# tokencraft_client.py
import requests
from typing import Dict, List, Optional

class TokencraftClient:
    """Client for Tokencraft API"""
    
    def __init__(self, token: str, base_url: str = 'https://app.tokencraft.dev/api/v1'):
        self.token = token
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {token}'
        })
    
    def _request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
        """Make API request"""
        url = f'{self.base_url}{endpoint}'
        response = self.session.request(method, url, **kwargs)
        response.raise_for_status()
        return response
    
    def get_workspaces(self) -> Dict:
        """Get all workspaces"""
        response = self._request('GET', '/workspaces')
        return response.json()
    
    def get_workspace(self, workspace_id: str) -> Dict:
        """Get specific workspace"""
        response = self._request('GET', f'/workspaces/{workspace_id}')
        return response.json()
    
    def get_tokensets(self, workspace_id: str) -> Dict:
        """Get tokensets in a workspace"""
        response = self._request('GET', f'/workspaces/{workspace_id}/tokensets')
        return response.json()
    
    def get_tokenset(self, tokenset_id: str) -> Dict:
        """Get specific tokenset"""
        response = self._request('GET', f'/tokensets/{tokenset_id}')
        return response.json()
    
    def get_modes(self, tokenset_id: str) -> Dict:
        """Get modes for a tokenset"""
        response = self._request('GET', f'/tokensets/{tokenset_id}/modes')
        return response.json()
    
    def get_tokens(self, tokenset_id: str, mode_id: str) -> Dict:
        """Get tokens for a specific mode"""
        response = self._request(
            'GET',
            f'/tokensets/{tokenset_id}/modes/{mode_id}/tokens'
        )
        return response.json()
    
    def export_tokens(
        self,
        tokenset_id: str,
        mode_id: str,
        format: str = 'json'
    ) -> str | Dict:
        """Export tokens in specified format"""
        response = self._request(
            'GET',
            f'/tokensets/{tokenset_id}/modes/{mode_id}/export',
            params={'format': format}
        )
        
        return response.json() if format == 'json' else response.text

# Usage
client = TokencraftClient(os.getenv('TOKENCRAFT_TOKEN'))
workspaces = client.get_workspaces()

Django Integration

Settings

# settings.py
TOKENCRAFT_TOKEN = os.getenv('TOKENCRAFT_TOKEN')
TOKENCRAFT_API_BASE = 'https://app.tokencraft.dev/api/v1'
TOKENCRAFT_TOKENSET_ID = os.getenv('TOKENCRAFT_TOKENSET_ID')
TOKENCRAFT_MODE_ID = os.getenv('TOKENCRAFT_MODE_ID')

Management Command

# management/commands/sync_tokens.py
from django.core.management.base import BaseCommand
from django.conf import settings
import requests
import json

class Command(BaseCommand):
    help = 'Sync design tokens from Tokencraft'
    
    def handle(self, *args, **options):
        url = (
            f'{settings.TOKENCRAFT_API_BASE}/tokensets/'
            f'{settings.TOKENCRAFT_TOKENSET_ID}/modes/'
            f'{settings.TOKENCRAFT_MODE_ID}/export'
        )
        
        response = requests.get(
            url,
            params={'format': 'json'},
            headers={'Authorization': f'Bearer {settings.TOKENCRAFT_TOKEN}'}
        )
        
        response.raise_for_status()
        tokens = response.json()
        
        # Save to file
        with open('static/tokens.json', 'w') as f:
            json.dump(tokens, f, indent=2)
        
        self.stdout.write(
            self.style.SUCCESS('Successfully synced design tokens')
        )
Run with:
python manage.py sync_tokens

Template Context Processor

# context_processors.py
import json
from django.conf import settings

def design_tokens(request):
    """Add design tokens to template context"""
    try:
        with open('static/tokens.json', 'r') as f:
            tokens = json.load(f)
        return {'design_tokens': tokens}
    except FileNotFoundError:
        return {'design_tokens': {}}
<!-- template.html -->
<style>
  :root {
    --primary-color: {{ design_tokens.colors.primary.500.value }};
  }
</style>

Flask Integration

# app.py
from flask import Flask, jsonify
import requests
import os

app = Flask(__name__)

# Load tokens on startup
def load_tokens():
    url = (
        f"{os.getenv('TOKENCRAFT_API_BASE')}/tokensets/"
        f"{os.getenv('TOKENCRAFT_TOKENSET_ID')}/modes/"
        f"{os.getenv('TOKENCRAFT_MODE_ID')}/export"
    )
    
    response = requests.get(
        url,
        params={'format': 'json'},
        headers={'Authorization': f"Bearer {os.getenv('TOKENCRAFT_TOKEN')}"}
    )
    
    return response.json()

tokens = load_tokens()

@app.route('/api/tokens')
def get_tokens():
    return jsonify(tokens)

@app.route('/api/tokens/<path:token_path>')
def get_token(token_path):
    keys = token_path.split('.')
    value = tokens
    
    for key in keys:
        value = value.get(key)
        if not value:
            return jsonify({'error': 'Token not found'}), 404
    
    return jsonify(value)

Build Script

# scripts/build_tokens.py
import requests
import json
import os
from pathlib import Path

def fetch_and_save_tokens():
    """Fetch tokens and save to multiple formats"""
    
    tokenset_id = os.getenv('TOKENCRAFT_TOKENSET_ID')
    mode_id = os.getenv('TOKENCRAFT_MODE_ID')
    token = os.getenv('TOKENCRAFT_TOKEN')
    base_url = os.getenv('TOKENCRAFT_API_BASE')
    
    # Fetch JSON
    url = f'{base_url}/tokensets/{tokenset_id}/modes/{mode_id}/export'
    
    # JSON format
    response = requests.get(
        url,
        params={'format': 'json'},
        headers={'Authorization': f'Bearer {token}'}
    )
    response.raise_for_status()
    
    tokens = response.json()
    Path('dist').mkdir(exist_ok=True)
    
    with open('dist/tokens.json', 'w') as f:
        json.dump(tokens, f, indent=2)
    
    # CSS format
    response = requests.get(
        url,
        params={'format': 'css'},
        headers={'Authorization': f'Bearer {token}'}
    )
    response.raise_for_status()
    
    with open('dist/tokens.css', 'w') as f:
        f.write(response.text)
    
    print('✓ Tokens built successfully')
    print(f'  - dist/tokens.json')
    print(f'  - dist/tokens.css')

if __name__ == '__main__':
    fetch_and_save_tokens()

Data Processing

Convert to Python Dict

def tokens_to_flat_dict(tokens, prefix=''):
    """Convert nested tokens to flat dictionary"""
    result = {}
    
    for key, value in tokens.items():
        new_key = f'{prefix}.{key}' if prefix else key
        
        if isinstance(value, dict) and 'value' in value:
            result[new_key] = value['value']
        elif isinstance(value, dict):
            result.update(tokens_to_flat_dict(value, new_key))
    
    return result

# Usage
flat_tokens = tokens_to_flat_dict(tokens)
# {
#   'colors.primary.500': '#3b82f6',
#   'spacing.base': '16px',
#   ...
# }

Generate Python Constants

def generate_python_constants(tokens, output_file='tokens.py'):
    """Generate Python constants file"""
    
    with open(output_file, 'w') as f:
        f.write('# Generated design tokens\n\n')
        
        flat = tokens_to_flat_dict(tokens)
        
        for key, value in flat.items():
            const_name = key.upper().replace('.', '_')
            f.write(f"{const_name} = '{value}'\n")
    
    print(f'✓ Generated {output_file}')

# Generate
generate_python_constants(tokens)

# Use
from tokens import COLORS_PRIMARY_500

Caching

import time
from functools import wraps

class TokenCache:
    """Simple in-memory cache for tokens"""
    
    def __init__(self, ttl=300):  # 5 minutes
        self.cache = {}
        self.ttl = ttl
    
    def get(self, key):
        if key in self.cache:
            data, timestamp = self.cache[key]
            if time.time() - timestamp < self.ttl:
                return data
            del self.cache[key]
        return None
    
    def set(self, key, value):
        self.cache[key] = (value, time.time())

cache = TokenCache()

def cached_fetch_tokens(tokenset_id, mode_id, format='json'):
    """Fetch tokens with caching"""
    cache_key = f'{tokenset_id}-{mode_id}-{format}'
    
    # Check cache
    cached = cache.get(cache_key)
    if cached:
        return cached
    
    # Fetch from API
    tokens = fetch_tokens(tokenset_id, mode_id, format)
    
    # Store in cache
    cache.set(cache_key, tokens)
    
    return tokens

Error Handling

from requests.exceptions import HTTPError, RequestException

def safe_fetch_tokens(tokenset_id, mode_id, format='json'):
    """Fetch tokens with error handling"""
    try:
        response = requests.get(
            f'{API_BASE}/tokensets/{tokenset_id}/modes/{mode_id}/export',
            params={'format': format},
            headers={'Authorization': f'Bearer {TOKENCRAFT_TOKEN}'},
            timeout=10
        )
        
        response.raise_for_status()
        
        return response.json() if format == 'json' else response.text
        
    except HTTPError as e:
        if e.response.status_code == 401:
            raise Exception('Invalid API token')
        elif e.response.status_code == 404:
            raise Exception('Tokenset or mode not found')
        elif e.response.status_code == 429:
            raise Exception('Rate limit exceeded')
        else:
            raise Exception(f'API error: {e}')
    
    except RequestException as e:
        raise Exception(f'Network error: {e}')

Next Steps