Error Handling
Introduction
The Feedframer API uses standard HTTP status codes and follows the JSON:API error format for consistent, predictable error handling.
HTTP Status Codes
| Status Code | Meaning | Description |
|---|---|---|
200 |
OK | Request succeeded |
401 |
Unauthorized | Missing or invalid API key |
422 |
Unprocessable Entity | Validation error (invalid parameters) |
429 |
Too Many Requests | Rate limit exceeded |
500 |
Internal Server Error | Server-side error |
503 |
Service Unavailable | Temporary service outage |
Error Response Format
All errors follow the JSON:API specification:
{
"errors": [
{
"status": "422",
"code": "VALIDATION_ERROR",
"title": "Validation Failed",
"detail": "The page.size must be between 1 and 100.",
"source": {
"parameter": "page[size]"
}
}
]
}
Error Object Fields
| Field | Description |
|---|---|
status |
HTTP status code as a string |
code |
Machine-readable error code |
title |
Short, human-readable summary |
detail |
Detailed error message |
source |
Optional pointer to the error source (parameter, field, etc.) |
Common Errors
401 - Authentication Errors
Missing API Key
Cause: No api_key parameter provided
Response:
{
"errors": [
{
"status": "401",
"code": "MISSING_API_KEY",
"title": "Authentication Required",
"detail": "API key is required. Include it as a query parameter: ?api_key=YOUR_KEY"
}
]
}
Solution:
# ❌ Missing API key
curl 'https://feedframer.com/api/v1/me'
# ✅ Include API key
curl 'https://feedframer.com/api/v1/me?api_key=YOUR_API_KEY'
Invalid API Key
Cause: API key is incorrect or has been regenerated
Response:
{
"errors": [
{
"status": "401",
"code": "INVALID_API_KEY",
"title": "Authentication Failed",
"detail": "The provided API key is invalid."
}
]
}
Solution:
- Verify your API key in your Instagram account settings
- Check for typos or incomplete keys
- Regenerate your API key if compromised
422 - Validation Errors
Invalid Page Size
Cause: page[size] parameter out of range (must be 1-100)
Response:
{
"errors": [
{
"status": "422",
"code": "VALIDATION_ERROR",
"title": "Validation Failed",
"detail": "The page.size must be between 1 and 100.",
"source": {
"parameter": "page[size]"
}
}
]
}
Solution:
# ❌ Invalid page size
curl 'https://feedframer.com/api/v1/me?api_key=YOUR_API_KEY&page[size]=150'
# ✅ Valid page size
curl 'https://feedframer.com/api/v1/me?api_key=YOUR_API_KEY&page[size]=100'
Invalid Post Type
Cause: filter[type] value is not a valid post type
Response:
{
"errors": [
{
"status": "422",
"code": "VALIDATION_ERROR",
"title": "Validation Failed",
"detail": "The filter.type must be one of: IMAGE, VIDEO, CAROUSEL_ALBUM, REELS.",
"source": {
"parameter": "filter[type]"
}
}
]
}
Solution:
# ❌ Invalid type
curl 'https://feedframer.com/api/v1/me?api_key=YOUR_API_KEY&filter[type]=PHOTO'
# ✅ Valid type
curl 'https://feedframer.com/api/v1/me?api_key=YOUR_API_KEY&filter[type]=IMAGE'
500 - Internal Server Error
Cause: Unexpected server error
Response:
{
"errors": [
{
"status": "500",
"code": "INTERNAL_SERVER_ERROR",
"title": "Internal Server Error",
"detail": "An unexpected error occurred. Please try again later."
}
]
}
Solution:
- Retry the request after a short delay
- If the error persists, report it via GitHub Issues
- Check status page for system issues
Error Handling Examples
JavaScript (Fetch API)
async function fetchPosts(apiKey) {
try {
const response = await fetch(
`https://feedframer.com/api/v1/me?api_key=${apiKey}`
);
if (!response.ok) {
const errorData = await response.json();
const error = errorData.errors[0];
switch (error.code) {
case 'MISSING_API_KEY':
case 'INVALID_API_KEY':
throw new Error('Authentication failed. Check your API key.');
case 'VALIDATION_ERROR':
throw new Error(`Validation error: ${error.detail}`);
default:
throw new Error(`API error: ${error.detail}`);
}
}
return await response.json();
} catch (error) {
console.error('Error fetching posts:', error.message);
throw error;
}
}
PHP
<?php
function fetchPosts($apiKey) {
$url = "https://feedframer.com/api/v1/me?api_key={$apiKey}";
$response = @file_get_contents($url);
if ($response === false) {
throw new Exception('Failed to connect to Feedframer API');
}
$data = json_decode($response, true);
// Check for errors
if (isset($data['errors'])) {
$error = $data['errors'][0];
switch ($error['code']) {
case 'MISSING_API_KEY':
case 'INVALID_API_KEY':
throw new Exception('Authentication failed. Check your API key.');
case 'VALIDATION_ERROR':
throw new Exception('Validation error: ' . $error['detail']);
default:
throw new Exception('API error: ' . $error['detail']);
}
}
return $data;
}
try {
$posts = fetchPosts('YOUR_API_KEY');
print_r($posts['data']);
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
Python
import requests
def fetch_posts(api_key):
url = f'https://feedframer.com/api/v1/me?api_key={api_key}'
try:
response = requests.get(url)
response.raise_for_status() # Raises HTTPError for bad status codes
return response.json()
except requests.exceptions.HTTPError as e:
error_data = e.response.json()
error = error_data['errors'][0]
if error['code'] in ['MISSING_API_KEY', 'INVALID_API_KEY']:
raise Exception('Authentication failed. Check your API key.')
elif error['code'] == 'VALIDATION_ERROR':
raise Exception(f"Validation error: {error['detail']}")
else:
raise Exception(f"API error: {error['detail']}")
except requests.exceptions.RequestException as e:
raise Exception(f'Request failed: {str(e)}')
try:
posts = fetch_posts('YOUR_API_KEY')
print(posts['data'])
except Exception as e:
print(f'Error: {e}')
Retry Strategies
Exponential Backoff
Retry failed requests with increasing delays:
async function fetchWithRetry(url, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url);
if (response.status === 429) {
// Rate limited - wait longer each time
const delay = Math.pow(2, attempt) * 1000;
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
if (response.status >= 500) {
// Server error - retry with backoff
const delay = Math.pow(2, attempt) * 500;
console.log(`Server error. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
// Success or client error (don't retry)
return await response.json();
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
console.log(`Request failed. Retrying... (${attempt}/${maxRetries})`);
}
}
throw new Error('Max retries exceeded');
}
Graceful Degradation
Provide fallback content when API fails:
async function fetchPostsWithFallback(apiKey) {
try {
return await fetchPosts(apiKey);
} catch (error) {
console.error('API error:', error);
// Return cached data if available
const cached = localStorage.getItem('cached_posts');
if (cached) {
console.log('Using cached data');
return JSON.parse(cached);
}
// Return empty state
return {
data: [],
message: 'Unable to load posts. Please try again later.'
};
}
}
GraphQL Errors
GraphQL errors have a different structure:
{
"errors": [
{
"message": "Validation error",
"extensions": {
"category": "validation"
},
"locations": [
{
"line": 2,
"column": 3
}
]
}
]
}
Handling GraphQL Errors:
const response = await fetch('https://feedframer.com/graphql?api_key=YOUR_API_KEY', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query })
});
const result = await response.json();
if (result.errors) {
const error = result.errors[0];
console.error('GraphQL error:', error.message);
// Handle error...
}
const posts = result.data.posts;
Best Practices
1. Always Check Response Status
if (!response.ok) {
// Handle error
}
2. Parse Error Details
const errorData = await response.json();
const error = errorData.errors[0];
console.error(`Error ${error.code}: ${error.detail}`);
3. Implement Retry Logic
Retry transient errors (429, 500, 503) but not client errors (401, 422).
4. Log Errors for Debugging
console.error('API Error:', {
status: error.status,
code: error.code,
detail: error.detail,
timestamp: new Date().toISOString()
});
5. Provide User-Friendly Messages
const userMessage = error.code === 'VALIDATION_ERROR'
? `There was an issue with your request: ${error.detail}`
: 'Unable to load Instagram posts. Please try again later.';
Error Codes Reference
| Code | Status | Description |
|---|---|---|
MISSING_API_KEY |
401 | API key not provided |
INVALID_API_KEY |
401 | API key is invalid |
VALIDATION_ERROR |
422 | Request validation failed |
INTERNAL_SERVER_ERROR |
500 | Unexpected server error |
Next Steps
- Authentication - Fix auth errors
- REST API - Complete REST reference
- GraphQL API - Complete GraphQL reference