SDKs & Libraries

Official and community-maintained libraries to accelerate your development process.

Official SDKs

We maintain official SDKs for the most popular programming languages. These libraries provide type safety, error handling, and convenience methods.

JavaScript/TypeScript

v2.1.0

Full-featured SDK with TypeScript support, automatic retries, and built-in caching.

npm install @oscarrondon/api-client
import { ApiClient } from '@oscarrondon/api-client';

const client = new ApiClient({
  apiKey: 'your-api-key',
  environment: 'production'
});

const content = await client.content.list({
  type: 'blog',
  limit: 10
});

Python

v1.8.2

Pythonic SDK with async support, automatic pagination, and comprehensive error handling.

pip install oscarrondon-api
from oscarrondon_api import ApiClient

client = ApiClient(api_key="your-api-key")

# Synchronous usage
content = client.content.list(type="blog", limit=10)

# Async usage
async with ApiClient(api_key="your-api-key") as client:
    content = await client.content.list_async(type="blog")

Java

v1.5.0

Enterprise-ready Java SDK with Spring Boot integration and reactive streams support.

<dependency>
  <groupId>com.oscarrondon</groupId>
  <artifactId>api-client</artifactId>
  <version>1.5.0</version>
</dependency>

Community Libraries

Third-party libraries maintained by the community. These may not be as up-to-date as official SDKs.

PHP SDK Community

Composer package for PHP applications with PSR-7 support.

View on Packagist
Rust Crate Community

Async Rust client with serde serialization support.

View on crates.io
Swift Package Community

Swift Package Manager compatible library for iOS/macOS.

View on GitHub

Code Examples

Real-world examples and use cases to help you implement common scenarios.

Basic Examples

Get started with these fundamental examples that demonstrate core API functionality.

Fetching and Displaying Content

This example shows how to retrieve content and display it in a web application.

import React, { useState, useEffect } from 'react';
import { ApiClient } from '@oscarrondon/api-client';

const client = new ApiClient({ 
  apiKey: process.env.REACT_APP_API_KEY 
});

function ContentList() {
  const [content, setContent] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchContent() {
      try {
        const response = await client.content.list({
          type: 'blog',
          status: 'published',
          limit: 10
        });
        setContent(response.data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchContent();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div className="content-list">
      {content.map(item => (
        <article key={item.id} className="content-item">
          <h2>{item.title}</h2>
          <p>By {item.author} • {new Date(item.created_at).toLocaleDateString()}</p>
          <div className="content-preview">
            {item.excerpt}
          </div>
        </article>
      ))}
    </div>
  );
}

export default ContentList;
<template>
  <div class="content-list">
    <div v-if="loading">Loading...</div>
    <div v-else-if="error" class="error">Error: {{ error }}</div>
    <article 
      v-else 
      v-for="item in content" 
      :key="item.id" 
      class="content-item"
    >
      <h2>{{ item.title }}</h2>
      <p>By {{ item.author }} • {{ formatDate(item.created_at) }}</p>
      <div class="content-preview">
        {{ item.excerpt }}
      </div>
    </article>
  </div>
</template>

<script>
import { ApiClient } from '@oscarrondon/api-client';

const client = new ApiClient({ 
  apiKey: process.env.VUE_APP_API_KEY 
});

export default {
  name: 'ContentList',
  data() {
    return {
      content: [],
      loading: true,
      error: null
    };
  },
  async mounted() {
    try {
      const response = await client.content.list({
        type: 'blog',
        status: 'published',
        limit: 10
      });
      this.content = response.data;
    } catch (err) {
      this.error = err.message;
    } finally {
      this.loading = false;
    }
  },
  methods: {
    formatDate(dateString) {
      return new Date(dateString).toLocaleDateString();
    }
  }
};
</script>
class ContentManager {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseURL = 'https://api.oscarrondon.com/v1';
  }

  async fetchContent() {
    const container = document.getElementById('content-container');
    
    try {
      container.innerHTML = '<div class="loading">Loading...</div>';
      
      const response = await fetch(`${this.baseURL}/content?type=blog&status=published&limit=10`, {
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json'
        }
      });

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      const data = await response.json();
      this.renderContent(data.data);
    } catch (error) {
      container.innerHTML = `<div class="error">Error: ${error.message}</div>`;
    }
  }

  renderContent(content) {
    const container = document.getElementById('content-container');
    
    const html = content.map(item => `
      <article class="content-item">
        <h2>${this.escapeHtml(item.title)}</h2>
        <p>By ${this.escapeHtml(item.author)} • ${new Date(item.created_at).toLocaleDateString()}</p>
        <div class="content-preview">
          ${this.escapeHtml(item.excerpt)}
        </div>
      </article>
    `).join('');
    
    container.innerHTML = html;
  }

  escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }
}

// Usage
const contentManager = new ContentManager('your-api-key');
contentManager.fetchContent();

Advanced Examples

More sophisticated examples demonstrating advanced features and patterns.

Real-time Content Updates with WebSockets

This example shows how to implement real-time content updates using WebSockets.

class RealTimeContentManager {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.wsUrl = 'wss://api.oscarrondon.com/v1/ws';
    this.content = new Map();
    this.subscribers = new Set();
  }

  async connect() {
    this.ws = new WebSocket(`${this.wsUrl}?token=${this.apiKey}`);
    
    this.ws.onopen = () => {
      console.log('Connected to real-time updates');
      this.subscribe('content.updated');
      this.subscribe('content.created');
      this.subscribe('content.deleted');
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.handleMessage(message);
    };

    this.ws.onclose = () => {
      console.log('Disconnected from real-time updates');
      // Implement reconnection logic
      setTimeout(() => this.connect(), 5000);
    };
  }

  subscribe(eventType) {
    this.ws.send(JSON.stringify({
      type: 'subscribe',
      event: eventType
    }));
  }

  handleMessage(message) {
    switch (message.type) {
      case 'content.updated':
        this.updateContent(message.data);
        break;
      case 'content.created':
        this.addContent(message.data);
        break;
      case 'content.deleted':
        this.removeContent(message.data.id);
        break;
    }
    
    // Notify all subscribers
    this.subscribers.forEach(callback => callback(message));
  }

  updateContent(contentItem) {
    this.content.set(contentItem.id, contentItem);
  }

  addContent(contentItem) {
    this.content.set(contentItem.id, contentItem);
  }

  removeContent(contentId) {
    this.content.delete(contentId);
  }

  onUpdate(callback) {
    this.subscribers.add(callback);
    return () => this.subscribers.delete(callback);
  }
}

// Usage
const rtManager = new RealTimeContentManager('your-api-key');
rtManager.connect();

const unsubscribe = rtManager.onUpdate((message) => {
  console.log('Content update:', message);
  // Update your UI here
});

Integration Patterns

Common patterns for integrating the API into different application architectures.

Repository Pattern (Backend)

Clean architecture approach for backend services.

View Example

Redux Integration (Frontend)

Managing API state with Redux and RTK Query.

View Example

GraphQL Wrapper

Exposing REST API through GraphQL layer.

View Example

Frequently Asked Questions

Common questions and answers about using our API.

General Questions

What are the rate limits for the API?

Rate limits depend on your subscription plan:

  • Free: 100 requests/hour
  • Basic: 1,000 requests/hour
  • Pro: 10,000 requests/hour
  • Enterprise: Custom limits

Rate limit headers are included in every response to help you track usage.

How do I handle authentication securely?

Follow these security best practices:

  • Never expose API keys in client-side code
  • Use environment variables for storing keys
  • Rotate keys regularly (we recommend every 90 days)
  • Implement IP whitelisting when possible
  • Use HTTPS for all API requests

For frontend applications, create a backend proxy that handles API authentication.

What data formats are supported?

Our API exclusively uses JSON for both requests and responses. All endpoints:

  • Accept application/json content type
  • Return application/json responses
  • Use UTF-8 encoding
  • Follow RFC 7159 JSON specification

How do I paginate through large result sets?

Use the limit and offset parameters:

# First page (10 items)
curl "https://api.oscarrondon.com/v1/content?limit=10&offset=0"

# Second page
curl "https://api.oscarrondon.com/v1/content?limit=10&offset=10"

The response includes pagination metadata to help with navigation.

Technical Questions

Can I use webhooks for real-time notifications?

Yes! Webhooks are available for Pro and Enterprise plans. You can configure webhooks to receive notifications for:

  • Content creation, updates, and deletion
  • User account changes
  • API key usage alerts

Configure webhooks in your dashboard under "API Settings".

What happens if I exceed my rate limit?

When you exceed your rate limit, you'll receive:

  • HTTP 429 status code
  • Retry-After header with wait time
  • Error response with details

Implement exponential backoff in your client to handle rate limiting gracefully.

Is there API versioning?

Yes, we use URL-based versioning. The current version is v1:

  • Current: https://api.oscarrondon.com/v1/
  • We maintain backwards compatibility for at least 12 months
  • Breaking changes are introduced in new versions
  • Deprecation notices are sent via email and API headers

Billing & Plans

How is API usage calculated?

Usage is calculated based on successful API requests:

  • Each successful request (2xx status) counts toward your quota
  • Failed requests (4xx, 5xx) don't count against your limit
  • Usage resets monthly on your billing cycle date
  • Real-time usage tracking available in your dashboard

Can I upgrade or downgrade my plan?

Yes, you can change your plan at any time:

  • Upgrades take effect immediately
  • Downgrades take effect at the next billing cycle
  • Pro-rated billing for mid-cycle upgrades
  • No penalties for plan changes

Manage your plan from the billing section of your dashboard.