Python Examples

Introduction

This guide provides Python examples for integrating Feedframer into your Python applications using the requests library.

Installation

Install the requests library:

pip install requests

Basic Usage

Simple GET Request

import requests

api_key = 'YOUR_API_KEY'
url = f'https://feedframer.com/api/v1/me?api_key={api_key}&page[size]=12'

response = requests.get(url)
data = response.json()

# Display account info
print(f"Account: {data['username']}")
print(f"Followers: {data['followersCount']}")

# Display posts
for post in data['posts']:
    print(post['caption'])
    print(post['mediaUrl'])

With Parameters

import requests

api_key = 'YOUR_API_KEY'

params = {
    'api_key': api_key,
    'filter[type]': 'IMAGE',
    'page[size]': 12,
    'sort': '-published_at'
}

response = requests.get('https://feedframer.com/api/v1/me', params=params)
data = response.json()

for post in data['posts']:
    print(f"Caption: {post['caption']}")
    print(f"Media URL: {post['mediaUrl']}")

Complete Client Class

import requests
import time
from typing import Optional, Dict, List

class FeedframerClient:
    def __init__(self, api_key: str, base_url: str = 'https://feedframer.com'):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()

    def get_posts(self, params: Optional[Dict] = None) -> Optional[Dict]:
        """Fetch posts from Feedframer API"""
        default_params = {
            'api_key': self.api_key,
            'page[size]': 12
        }

        if params:
            default_params.update(params)

        try:
            response = self.session.get(
                f'{self.base_url}/api/v1/me',
                params=default_params,
                timeout=10
            )

            response.raise_for_status()
            return response.json()

        except requests.exceptions.RequestException as e:
            print(f"Error fetching posts: {e}")
            return None

    def get_image_posts(self, limit: int = 12) -> Optional[List[Dict]]:
        """Get only image posts"""
        data = self.get_posts({
            'filter[type]': 'IMAGE',
            'page[size]': limit
        })

        return data['posts'] if data else None

    def get_video_posts(self, limit: int = 12) -> Optional[List[Dict]]:
        """Get only video posts"""
        data = self.get_posts({
            'filter[type]': 'VIDEO',
            'page[size]': limit
        })

        return data['posts'] if data else None

    def get_reels(self, limit: int = 12) -> Optional[List[Dict]]:
        """Get only reels"""
        data = self.get_posts({
            'filter[type]': 'REELS',
            'page[size]': limit
        })

        return data['posts'] if data else None

# Usage
client = FeedframerClient('YOUR_API_KEY')
posts = client.get_image_posts(12)

if posts:
    for post in posts:
        print(post['caption'])

Error Handling

import requests
from typing import Optional, Dict

class FeedframerClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = 'https://feedframer.com'

    def get_posts(self, params: Optional[Dict] = None) -> Optional[Dict]:
        default_params = {
            'api_key': self.api_key,
            'page[size]': 12
        }

        if params:
            default_params.update(params)

        try:
            response = requests.get(
                f'{self.base_url}/api/v1/me',
                params=default_params,
                timeout=10
            )

            # Check for HTTP errors
            if response.status_code == 401:
                print("Authentication failed. Check your API key.")
                return None

            if response.status_code == 429:
                print("Rate limit exceeded. Please wait.")
                return None

            if response.status_code == 422:
                error_data = response.json()
                print(f"Validation error: {error_data.get('message', 'Unknown error')}")
                return None

            response.raise_for_status()

            data = response.json()

            # Check for API errors
            if 'error' in data:
                print(f"API Error: {data.get('message', data['error'])}")
                return None

            return data

        except requests.exceptions.Timeout:
            print("Request timed out")
            return None

        except requests.exceptions.ConnectionError:
            print("Connection error")
            return None

        except requests.exceptions.RequestException as e:
            print(f"Request failed: {e}")
            return None

Caching

File-Based Caching

import requests
import json
import os
import time
from pathlib import Path

class CachedFeedframerClient:
    def __init__(self, api_key: str, cache_dir: str = '/tmp/feedframer-cache'):
        self.api_key = api_key
        self.base_url = 'https://feedframer.com'
        self.cache_dir = Path(cache_dir)
        self.cache_duration = 3600  # 1 hour

        # Create cache directory
        self.cache_dir.mkdir(parents=True, exist_ok=True)

    def get_posts(self, params: Optional[Dict] = None) -> Optional[Dict]:
        # Generate cache key
        cache_key = self._get_cache_key(params)
        cache_file = self.cache_dir / f'{cache_key}.json'

        # Check cache
        if cache_file.exists():
            cache_age = time.time() - cache_file.stat().st_mtime

            if cache_age < self.cache_duration:
                with open(cache_file, 'r') as f:
                    return json.load(f)

        # Fetch fresh data
        default_params = {
            'api_key': self.api_key,
            'page[size]': 12
        }

        if params:
            default_params.update(params)

        try:
            response = requests.get(
                f'{self.base_url}/api/v1/me',
                params=default_params,
                timeout=10
            )

            response.raise_for_status()
            data = response.json()

            # Cache the response
            with open(cache_file, 'w') as f:
                json.dump(data, f)

            return data

        except requests.exceptions.RequestException as e:
            print(f"Error: {e}")
            return None

    def _get_cache_key(self, params: Optional[Dict]) -> str:
        import hashlib
        key_str = json.dumps(params or {}, sort_keys=True)
        return hashlib.md5(key_str.encode()).hexdigest()

    def clear_cache(self):
        """Clear all cached files"""
        for cache_file in self.cache_dir.glob('*.json'):
            cache_file.unlink()

Redis Caching

import requests
import json
import redis
from typing import Optional, Dict

class RedisCachedFeedframerClient:
    def __init__(self, api_key: str, redis_url: str = 'redis://localhost:6379'):
        self.api_key = api_key
        self.base_url = 'https://feedframer.com'
        self.redis = redis.from_url(redis_url)
        self.cache_duration = 3600  # 1 hour

    def get_posts(self, params: Optional[Dict] = None) -> Optional[Dict]:
        # Generate cache key
        cache_key = f'feedframer:{self._get_cache_key(params)}'

        # Check cache
        cached = self.redis.get(cache_key)
        if cached:
            return json.loads(cached)

        # Fetch fresh data
        default_params = {
            'api_key': self.api_key,
            'page[size]': 12
        }

        if params:
            default_params.update(params)

        try:
            response = requests.get(
                f'{self.base_url}/api/v1/me',
                params=default_params,
                timeout=10
            )

            response.raise_for_status()
            data = response.json()

            # Cache the response
            self.redis.setex(
                cache_key,
                self.cache_duration,
                json.dumps(data)
            )

            return data

        except requests.exceptions.RequestException as e:
            print(f"Error: {e}")
            return None

    def _get_cache_key(self, params: Optional[Dict]) -> str:
        import hashlib
        key_str = json.dumps(params or {}, sort_keys=True)
        return hashlib.md5(key_str.encode()).hexdigest()

Pagination

Fetch All Pages

def get_all_posts(api_key: str) -> List[Dict]:
    """Fetch all posts using cursor pagination"""
    all_posts = []
    cursor = None

    while True:
        params = {
            'api_key': api_key,
            'page[size]': 50
        }

        if cursor:
            params['page[cursor]'] = cursor

        response = requests.get('https://feedframer.com/api/v1/me', params=params)
        data = response.json()

        all_posts.extend(data['posts'])

        cursor = data['pagination'].get('nextCursor')
        if not cursor:
            break

    return all_posts

# Usage
posts = get_all_posts('YOUR_API_KEY')
print(f'Fetched {len(posts)} total posts')

GraphQL

import requests

def fetch_posts_graphql(api_key: str, limit: int = 12) -> Optional[List[Dict]]:
    query = """
    query GetPosts($first: Int!) {
      posts(first: $first) {
        data {
          id
          caption
          mediaUrl
          timestamp
        }
      }
    }
    """

    variables = {
        'first': limit
    }

    response = requests.post(
        f'https://feedframer.com/graphql?api_key={api_key}',
        json={
            'query': query,
            'variables': variables
        },
        headers={'Content-Type': 'application/json'}
    )

    if response.ok:
        data = response.json()
        if 'errors' in data:
            print(f"GraphQL errors: {data['errors']}")
            return None

        return data['data']['posts']['data']

    return None

Flask Integration

from flask import Flask, render_template, jsonify
import requests

app = Flask(__name__)
API_KEY = 'YOUR_API_KEY'

def get_instagram_posts(limit=12):
    response = requests.get(
        'https://feedframer.com/api/v1/me',
        params={
            'api_key': API_KEY,
            'page[size]': limit
        }
    )

    if response.ok:
        return response.json()['posts']

    return []

@app.route('/')
def index():
    posts = get_instagram_posts(12)
    return render_template('instagram.html', posts=posts)

@app.route('/api/posts')
def api_posts():
    posts = get_instagram_posts(12)
    return jsonify({'posts': posts})

if __name__ == '__main__':
    app.run(debug=True)

Django Integration

# views.py

from django.shortcuts import render
from django.http import JsonResponse
from django.conf import settings
import requests

def instagram_feed(request):
    response = requests.get(
        'https://feedframer.com/api/v1/me',
        params={
            'api_key': settings.FEEDFRAMER_API_KEY,
            'page[size]': 12
        }
    )

    posts = response.json()['posts'] if response.ok else []

    return render(request, 'instagram/feed.html', {
        'posts': posts
    })

def api_posts(request):
    response = requests.get(
        'https://feedframer.com/api/v1/me',
        params={
            'api_key': settings.FEEDFRAMER_API_KEY,
            'page[size]': 12,
            'filter[type]': request.GET.get('type', '')
        }
    )

    if response.ok:
        return JsonResponse(response.json())

    return JsonResponse({'error': 'Failed to fetch posts'}, status=500)

Async with aiohttp

import aiohttp
import asyncio

async def fetch_posts_async(api_key: str) -> Optional[Dict]:
    params = {
        'api_key': api_key,
        'page[size]': 12
    }

    async with aiohttp.ClientSession() as session:
        async with session.get(
            'https://feedframer.com/api/v1/me',
            params=params
        ) as response:
            if response.status == 200:
                return await response.json()

            return None

# Usage
async def main():
    posts = await fetch_posts_async('YOUR_API_KEY')
    print(posts)

asyncio.run(main())

Next Steps