Best Practices

Best Practices

This guide outlines best practices for integrating with the Spreetail Channel Integration API to ensure reliable, efficient, and secure operations.

Authentication

Token Management

DO:

  • Cache tokens and reuse them for their full validity period (24 hours)
  • Implement automatic token refresh before expiration
  • Store tokens securely in memory, not in logs or files

DON'T:

  • Request a new token for every API call
  • Store tokens in client-side code or public repositories
  • Log tokens or include them in error messages
# Good: Cache and reuse tokens
class APIClient:
    def __init__(self):
        self.token = None
        self.token_expires_at = 0
    
    def get_token(self):
        if self.token and time.time() < self.token_expires_at - 300:
            return self.token
        # Refresh token
        ...

Credential Security

DO:

  • Use environment variables for credentials
  • Rotate secrets regularly
  • Use different credentials for development and production

DON'T:

  • Hardcode credentials in source code
  • Commit credentials to version control
  • Share credentials between team members

Request Handling

Idempotency

DO:

  • Use unique reference numbers for orders
  • Implement idempotency checks for critical operations
  • Handle duplicate request errors gracefully
# Good: Check for duplicates before creating
def create_order_safely(order_data):
    try:
        return create_order(order_data)
    except APIError as e:
        if e.status_code == 409:  # Conflict
            # Order already exists, fetch it instead
            return get_order_by_reference(order_data['ReferenceNumber'])
        raise

Validation

DO:

  • Validate all data before sending API requests
  • Check required fields and formats
  • Verify business rules (e.g., stock availability)
# Good: Validate before API call
def validate_and_create_order(order_data):
    # Validate structure
    errors = validate_order_structure(order_data)
    if errors:
        return {"success": False, "errors": errors}
    
    # Check inventory
    for item in order_data['OrderItems']:
        inventory = get_inventory(sku=item['SKU'])
        if inventory['quantity'] < item['Qty']:
            return {
                "success": False,
                "error": f"Insufficient stock for {item['SKU']}"
            }
    
    # All validations passed
    return create_order(order_data)

Error Handling

DO:

  • Implement comprehensive error handling
  • Use retry logic for transient errors (5xx, 429)
  • Log errors with sufficient context
  • Handle specific error codes appropriately

DON'T:

  • Ignore errors or use generic error handlers
  • Retry on client errors (4xx) without fixing the issue
  • Retry indefinitely without backoff

Performance

Rate Limiting

DO:

  • Respect rate limits (100 requests/minute by default)
  • Implement exponential backoff for rate limit errors
  • Batch operations when possible
  • Cache responses when appropriate
# Good: Rate limit aware client
import time
from collections import deque

class RateLimitedClient:
    def __init__(self, max_requests=100, window=60):
        self.max_requests = max_requests
        self.window = window
        self.requests = deque()
    
    def wait_if_needed(self):
        now = time.time()
        # Remove old requests outside window
        while self.requests and self.requests[0] < now - self.window:
            self.requests.popleft()
        
        # Wait if at limit
        if len(self.requests) >= self.max_requests:
            sleep_time = self.window - (now - self.requests[0])
            if sleep_time > 0:
                time.sleep(sleep_time)
        
        self.requests.append(time.time())

Caching

DO:

  • Cache inventory data (5-10 minutes)
  • Cache authentication tokens
  • Cache static reference data

DON'T:

  • Cache order creation responses
  • Cache data that changes frequently
  • Cache without considering TTL
# Good: Cache with TTL
from functools import lru_cache
import time

class CachedInventory:
    def __init__(self, ttl=300):  # 5 minutes
        self.cache = {}
        self.ttl = ttl
    
    def get(self, sku):
        if sku in self.cache:
            data, timestamp = self.cache[sku]
            if time.time() - timestamp < self.ttl:
                return data
        
        # Fetch fresh data
        data = fetch_inventory(sku)
        self.cache[sku] = (data, time.time())
        return data

Data Management

Reference Numbers

DO:

  • Use consistent, unique reference number formats
  • Include timestamps or sequence numbers
  • Prefix with client identifier
# Good: Generate unique reference numbers
import uuid
from datetime import datetime

def generate_reference_number(client_id):
    timestamp = datetime.utcnow().strftime('%Y%m%d-%H%M%S')
    unique_id = str(uuid.uuid4())[:8]
    return f"{client_id}-{timestamp}-{unique_id}"

Date Handling

DO:

  • Use UTC for all timestamps
  • Format dates as ISO 8601 with timezone
  • Validate date formats before sending
# Good: Consistent date handling
from datetime import datetime, timezone

def format_date(dt):
    """Format datetime as ISO 8601 UTC string"""
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    return dt.isoformat().replace('+00:00', 'Z')

Monitoring and Logging

Logging

DO:

  • Log all API requests and responses (without sensitive data)
  • Include request IDs and timestamps
  • Log errors with full context
  • Use structured logging
# Good: Structured logging
import logging
import json

logger = logging.getLogger(__name__)

def log_api_request(method, endpoint, status_code, duration):
    logger.info(json.dumps({
        "event": "api_request",
        "method": method,
        "endpoint": endpoint,
        "status_code": status_code,
        "duration_ms": duration * 1000,
        "timestamp": datetime.utcnow().isoformat()
    }))

Monitoring

DO:

  • Monitor API response times
  • Track error rates by type
  • Alert on authentication failures
  • Monitor rate limit usage

Security

Data Protection

DO:

  • Use HTTPS for all API calls
  • Never log sensitive data (tokens, secrets, customer data)
  • Encrypt sensitive data at rest
  • Follow GDPR/data protection regulations

Access Control

DO:

  • Use least privilege principle
  • Rotate credentials regularly
  • Monitor for unauthorized access
  • Use separate credentials for different environments

Testing

Test Environment

DO:

  • Use test credentials for development
  • Test error scenarios
  • Test rate limiting behavior
  • Validate all error codes
# Good: Comprehensive testing
def test_order_creation():
    # Test successful creation
    order = create_test_order()
    result = create_order(order)
    assert result['success'] == True
    
    # Test duplicate detection
    result2 = create_order(order)
    assert result2['success'] == False
    assert 'already exists' in result2['error']
    
    # Test validation errors
    invalid_order = {'ReferenceNumber': 'TEST'}
    result3 = create_order(invalid_order)
    assert result3['success'] == False

Code Organization

Structure

DO:

  • Create reusable API client classes
  • Separate authentication logic
  • Implement proper error handling
  • Use configuration files for settings
# Good: Well-organized client
class SpreetailAPIClient:
    def __init__(self, client_id, client_secret, base_url=None):
        self.client_id = client_id
        self.client_secret = client_secret
        self.base_url = base_url or "https://api.spreetaileu.com/api/api/v1"
        self.session = requests.Session()
        self._token = None
        self._token_expires_at = 0
    
    def authenticate(self):
        # Authentication logic
        ...
    
    def create_order(self, order_data):
        # Order creation logic
        ...
    
    def get_inventory(self, sku=None):
        # Inventory retrieval logic
        ...

Summary

Following these best practices will help you:

  • Improve Reliability: Proper error handling and retry logic
  • Enhance Security: Secure credential management
  • Optimize Performance: Caching and rate limit awareness
  • Maintain Code Quality: Well-structured, testable code
  • Ensure Compliance: Data protection and monitoring

For specific questions or advanced use cases, contact [email protected].