Integration Guide

Step-by-step guides to help you integrate our API into your applications quickly and efficiently.

Web Application Integration

Integrating our API into a web application is straightforward. Here's a complete example using JavaScript and modern web technologies.

Setting Up Authentication

First, create a secure environment for your API key. Never expose API keys in client-side code.

// config.js - Store this securely on your server
const API_CONFIG = {
  baseURL: 'https://api.oscarrondon.com/v1',
  apiKey: process.env.API_KEY, // Use environment variables
  timeout: 10000
};

// api-client.js - Create a reusable API client
class ApiClient {
  constructor(config) {
    this.baseURL = config.baseURL;
    this.apiKey = config.apiKey;
    this.timeout = config.timeout;
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseURL}${endpoint}`;
    const config = {
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
        ...options.headers
      },
      timeout: this.timeout,
      ...options
    };

    try {
      const response = await fetch(url, config);
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      return await response.json();
    } catch (error) {
      console.error('API request failed:', error);
      throw error;
    }
  }
}

Mobile Application Integration

Our API is designed to work seamlessly with mobile applications. Here are best practices for iOS and Android integration.

Error Handling Strategy

Implement robust error handling to provide a smooth user experience even when network conditions are poor.

// iOS Swift Example
import Foundation

class APIService {
    private let baseURL = "https://api.oscarrondon.com/v1"
    private let apiKey: String
    
    init(apiKey: String) {
        self.apiKey = apiKey
    }
    
    func fetchContent(completion: @escaping (Result<[Content], APIError>) -> Void) {
        guard let url = URL(string: "\(baseURL)/content") else {
            completion(.failure(.invalidURL))
            return
        }
        
        var request = URLRequest(url: url)
        request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                completion(.failure(.networkError(error)))
                return
            }
            
            guard let data = data else {
                completion(.failure(.noData))
                return
            }
            
            do {
                let contentResponse = try JSONDecoder().decode(ContentResponse.self, from: data)
                completion(.success(contentResponse.data))
            } catch {
                completion(.failure(.decodingError(error)))
            }
        }.resume()
    }
}

Server-to-Server Integration

For backend services, implement caching and rate limiting to optimize performance and stay within API limits.

# Python Example with caching
import requests
import time
from functools import lru_cache
from typing import Dict, List, Optional

class APIClient:
    def __init__(self, api_key: str, base_url: str = "https://api.oscarrondon.com/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        })
        self.last_request_time = 0
        self.rate_limit_delay = 0.1  # 100ms between requests
    
    def _rate_limit(self):
        """Implement simple rate limiting"""
        elapsed = time.time() - self.last_request_time
        if elapsed < self.rate_limit_delay:
            time.sleep(self.rate_limit_delay - elapsed)
        self.last_request_time = time.time()
    
    @lru_cache(maxsize=100)
    def get_content(self, content_type: Optional[str] = None) -> List[Dict]:
        """Cached content retrieval"""
        self._rate_limit()
        
        params = {}
        if content_type:
            params['type'] = content_type
            
        response = self.session.get(f"{self.base_url}/content", params=params)
        response.raise_for_status()
        return response.json()['data']

Best Practices

Follow these recommendations to build robust, scalable applications with our API.

Authentication & Security

Protect your API keys and implement proper security measures in your applications.

API Key Security

  • Never expose API keys in client-side code
  • Use environment variables for server applications
  • Rotate API keys regularly
  • Implement IP whitelisting when possible

Request Security

  • Always use HTTPS for API requests
  • Validate and sanitize user inputs
  • Implement proper error handling
  • Log security events for monitoring

Performance Optimization

Optimize your API usage for better performance and cost efficiency.

Caching Strategies

  • Client-side caching: Cache responses in memory or local storage
  • HTTP caching: Respect cache headers (ETag, Cache-Control)
  • Application caching: Use Redis or Memcached for frequently accessed data

Request Optimization

// Good: Batch multiple requests when possible
const fetchMultipleContent = async (contentIds) => {
  // Use bulk endpoint if available
  return await apiClient.request('/content/bulk', {
    method: 'POST',
    body: JSON.stringify({ ids: contentIds })
  });
};

// Good: Use pagination for large datasets
const fetchAllContent = async () => {
  let allContent = [];
  let offset = 0;
  const limit = 50;
  
  while (true) {
    const response = await apiClient.request(`/content?limit=${limit}&offset=${offset}`);
    allContent.push(...response.data);
    
    if (!response.pagination.has_more) break;
    offset += limit;
  }
  
  return allContent;
};

Error Handling Patterns

Implement comprehensive error handling to create resilient applications.

// Comprehensive error handling example
class APIError extends Error {
  constructor(message, status, code) {
    super(message);
    this.name = 'APIError';
    this.status = status;
    this.code = code;
  }
}

class APIClient {
  async request(endpoint, options = {}) {
    const maxRetries = 3;
    let attempt = 0;
    
    while (attempt < maxRetries) {
      try {
        const response = await fetch(`${this.baseURL}${endpoint}`, {
          headers: this.getHeaders(),
          ...options
        });
        
        if (!response.ok) {
          const errorData = await response.json().catch(() => ({}));
          
          switch (response.status) {
            case 401:
              throw new APIError('Authentication failed', 401, 'AUTH_FAILED');
            case 429:
              // Rate limited - implement exponential backoff
              const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
              await this.sleep(retryAfter * 1000);
              attempt++;
              continue;
            case 500:
            case 502:
            case 503:
              // Server errors - retry with backoff
              if (attempt < maxRetries - 1) {
                await this.sleep(Math.pow(2, attempt) * 1000);
                attempt++;
                continue;
              }
              throw new APIError('Server error', response.status, 'SERVER_ERROR');
            default:
              throw new APIError(
                errorData.message || 'Unknown error',
                response.status,
                errorData.code || 'UNKNOWN_ERROR'
              );
          }
        }
        
        return await response.json();
      } catch (error) {
        if (error instanceof APIError) {
          throw error;
        }
        
        // Network or other errors
        if (attempt < maxRetries - 1) {
          await this.sleep(Math.pow(2, attempt) * 1000);
          attempt++;
          continue;
        }
        
        throw new APIError('Network error', 0, 'NETWORK_ERROR');
      }
    }
  }
  
  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Troubleshooting

Common issues and their solutions to help you resolve problems quickly.

Common Errors

Here are the most frequently encountered errors and how to resolve them.

401 Unauthorized Authentication Failed

Cause: Invalid or missing API key

Solution:

  • Verify your API key is correct and active
  • Check that the Authorization header is properly formatted
  • Ensure your API key has the necessary permissions
# Correct format
curl -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \
     https://api.oscarrondon.com/v1/content
429 Rate Limited Too Many Requests

Cause: Exceeded rate limits

Solution:

  • Implement exponential backoff retry logic
  • Respect the Retry-After header
  • Consider upgrading your plan for higher limits
  • Implement request queuing and batching
422 Validation Error Invalid Request Data

Cause: Request data doesn't meet validation requirements

Solution:

  • Check the error response for specific field validation messages
  • Ensure required fields are present
  • Validate data types and formats
  • Check field length limits

Debugging Tips

Use these techniques to diagnose and resolve API integration issues.

Enable Debug Logging

// Enable detailed logging for debugging
const debug = process.env.NODE_ENV === 'development';

class APIClient {
  async request(endpoint, options = {}) {
    if (debug) {
      console.log('API Request:', {
        url: `${this.baseURL}${endpoint}`,
        method: options.method || 'GET',
        headers: { ...this.getHeaders(), ...options.headers },
        body: options.body
      });
    }
    
    const response = await fetch(`${this.baseURL}${endpoint}`, {
      headers: this.getHeaders(),
      ...options
    });
    
    if (debug) {
      console.log('API Response:', {
        status: response.status,
        headers: Object.fromEntries(response.headers),
        url: response.url
      });
    }
    
    return response;
  }
}

Test API Connectivity

Use these commands to test basic connectivity and authentication:

# Test basic connectivity
curl -I https://api.oscarrondon.com/v1/

# Test authentication
curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://api.oscarrondon.com/v1/content?limit=1

# Test with verbose output for debugging
curl -v -H "Authorization: Bearer YOUR_API_KEY" \
     https://api.oscarrondon.com/v1/content

Support Resources

If you're still experiencing issues, here are additional resources to help you:

Email Support

Send detailed error logs and reproduction steps to:

osaron@ucdavis.edu

GitHub Issues

Report bugs or request features:

GitHub Repository

FAQ

Check our frequently asked questions:

View FAQ