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.0Full-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.2Pythonic 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")
Community Libraries
Third-party libraries maintained by the community. These may not be as up-to-date as official SDKs.
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.
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/jsoncontent type - Return
application/jsonresponses - 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-Afterheader 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.