Getting Started with the Sollama.net API
This guide will help you start converting webpages into LLM-optimized markdown. We'll cover authentication, your first conversion, and practical examples for common LLM use cases.
Prerequisites
Before you begin, make sure you have:
- A Sollama.net account
- Your API key (available in your dashboard settings)
- Basic knowledge of HTTP requests and JSON
- A clear understanding of your LLM optimization needs
Authentication
All API requests require authentication using a Bearer token. Include the token in your requests using the Authorization header:
Authorization: Bearer YOUR_API_KEY
Your First Conversion
Let's convert a webpage to LLM-ready markdown using cURL:
# Convert a blog post to markdown
curl -X GET \
"https://sollama.net/api/md?url=https://blog.example.com/ai-guide&format=json" \
-H 'Authorization: Bearer YOUR_API_KEY'
Response:
{
"success": true,
"data": {
"markdown": "# Complete Guide to AI Implementation\n\nArtificial Intelligence is transforming...",
"title": "Complete Guide to AI Implementation",
"url": "https://blog.example.com/ai-guide",
"statusCode": 200
}
}
Or using JavaScript with fetch:
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://blog.example.com/ai-guide',
format: 'json',
onlyMainContent: true
})
});
const data = await response.json();
console.log('LLM-ready content:', data.data.markdown);
LLM-Focused Use Cases
1. Converting Documentation for AI Training
Perfect for creating training datasets from technical documentation:
const convertDocs = async (docUrls) => {
const conversions = await Promise.all(
docUrls.map(async (url) => {
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url,
format: 'json',
onlyMainContent: true,
enhancedCodeBlocks: true,
excludeTags: ['nav', '.sidebar', '.footer']
})
});
return response.json();
})
);
return conversions.filter(c => c.success).map(c => c.data.markdown);
};
// Convert multiple documentation pages
const docs = await convertDocs([
'https://docs.example.com/getting-started',
'https://docs.example.com/api-reference',
'https://docs.example.com/tutorials'
]);
2. Processing Blog Content for AI Analysis
Extract clean content from blog posts and articles:
const processBlogPost = async (url) => {
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url,
format: 'json',
onlyMainContent: true,
excludeTags: [
'.social-share',
'.comments',
'.related-posts',
'aside'
],
enhancedImages: true, // Extract image alt text
enhancedLinks: true // Better link formatting
})
});
const result = await response.json();
if (result.success) {
return {
title: result.data.title,
content: result.data.markdown,
url: result.data.url
};
}
throw new Error(result.error.message);
};
3. Chart and Data Visualization Processing
Convert dashboards and reports with chart detection:
const processDashboard = async (dashboardUrl) => {
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: dashboardUrl,
format: 'json',
// Specifically include chart containers
includeTags: [
'.chart-container',
'#revenue-chart',
'.data-visualization',
'[data-chart]'
],
enhancedTables: true, // Better table processing
enhancedImages: true, // OCR for chart images
waitFor: 3000 // Wait for charts to load
})
});
const result = await response.json();
return result.success ? result.data : null;
};
// Process a financial dashboard
const chartData = await processDashboard('https://company.com/dashboard/financials');
4. Batch Processing for Content Analysis
Process multiple URLs for large-scale content analysis:
const batchProcess = async (urls, options = {}) => {
const defaultOptions = {
format: 'json',
onlyMainContent: true,
enhancedTables: true,
enhancedCodeBlocks: true,
timeout: 30000,
...options
};
const results = [];
// Process in batches to respect rate limits
for (let i = 0; i < urls.length; i += 5) {
const batch = urls.slice(i, i + 5);
const batchResults = await Promise.allSettled(
batch.map(async (url) => {
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url,
...defaultOptions
})
});
return { url, result: await response.json() };
})
);
results.push(...batchResults);
// Brief pause between batches
await new Promise(resolve => setTimeout(resolve, 1000));
}
return results;
};
// Process research papers
const papers = await batchProcess([
'https://arxiv.org/abs/2301.00001',
'https://arxiv.org/abs/2301.00002',
'https://arxiv.org/abs/2301.00003'
]);
5. Real-time Content Processing for LLM Applications
Integrate with LLM applications for real-time content processing:
class LLMContentProcessor {
constructor(apiKey) {
this.apiKey = apiKey;
this.cache = new Map();
}
async processUrl(url, options = {}) {
// Check cache first
const cacheKey = `${url}:${JSON.stringify(options)}`;
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url,
format: 'json',
onlyMainContent: true,
enhancedImages: true,
...options
})
});
const result = await response.json();
if (result.success) {
// Cache successful conversions
this.cache.set(cacheKey, result.data.markdown);
return result.data.markdown;
}
throw new Error(result.error.message);
}
// Process content for LLM consumption
async prepareForLLM(url, context = '') {
const content = await this.processUrl(url, {
excludeTags: ['nav', 'footer', '.ads', '.social'],
enhancedTables: true,
enhancedCodeBlocks: true
});
return `Context: ${context}\n\nContent from ${url}:\n\n${content}`;
}
}
// Usage in your LLM application
const processor = new LLMContentProcessor('your-api-key');
const llmInput = await processor.prepareForLLM(
'https://docs.example.com/advanced-guide',
'User is asking about advanced implementation patterns'
);
Framework Integration Examples
NextJS API Route
// pages/api/convert.js or app/api/convert/route.js
export async function POST(request) {
const { url, options } = await request.json();
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SOLLAMA_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ url, ...options })
});
return response;
}
Remix Loader
// app/routes/convert.tsx
export async function loader({ request }) {
const url = new URL(request.url);
const targetUrl = url.searchParams.get('url');
if (!targetUrl) {
throw new Response('URL parameter required', { status: 400 });
}
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SOLLAMA_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: targetUrl,
format: 'json',
onlyMainContent: true
})
});
return response.json();
}
Error Handling Best Practices
Always implement proper error handling for production applications:
const robustConversion = async (url, options = {}) => {
try {
const response = await fetch('https://sollama.net/api/md', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ url, ...options })
});
const result = await response.json();
if (!result.success) {
console.error('Conversion failed:', result.error);
// Handle specific error types
switch (result.error.statusCode) {
case 400:
throw new Error(`Invalid request: ${result.error.message}`);
case 401:
throw new Error('Authentication failed. Check your API key.');
case 429:
throw new Error('Rate limit exceeded. Please retry after a delay.');
case 503:
throw new Error('Service temporarily unavailable. Please retry.');
default:
throw new Error(`Conversion error: ${result.error.message}`);
}
}
return result.data;
} catch (error) {
console.error('Network or parsing error:', error);
throw error;
}
};
Performance Tips
- Use caching: Identical URLs return cached results for faster responses
- Batch requests: Process multiple URLs with delays between batches
- Optimize selectors: Use specific CSS selectors to reduce processing time
- Set appropriate timeouts: Balance between reliability and speed
- Handle errors gracefully: Implement retry logic for transient failures
Next Steps
- Explore the API Reference for detailed endpoint documentation
- Check out Integration Examples for framework-specific implementations
- Learn about Chart Detection for advanced data processing
- See Image Processing for OCR and visual content extraction
Ready to give your LLMs vision superpowers? Start converting and avoid the guesswork!