SDKs

Python SDK

Sync and async clients for the Outfame API. Uses pydantic models for response validation, httpx under the hood for async. Works with Python 3.9+.

FeatureDetails
Packageoutfame
Version1.8.0
Python≥ 3.9
Async supportYes (asyncio / httpx)
LicenseMIT
Sourcegithub.com/outfame/outfame-python

Installation

pip install outfame
# or
poetry add outfame
# or
pipenv install outfame

Quick start

Synchronous client

import outfame

client = outfame.Client(api_key="sk_live_your_api_key")

# List accounts
accounts = client.accounts.list(platform="instagram")
for account in accounts.data:
    print(f"{account.id}: {account.instagram_username} ({account.status})")

# Get analytics
overview = client.analytics.overview("acc_7Gx2kLm9Qr", period="30d")
print(f"Net growth: +{overview.net_growth}")
print(f"Engagement rate: {overview.engagement_rate}%")

Async client

import outfame
import asyncio

async def main():
    client = outfame.AsyncClient(api_key="sk_live_your_api_key")

    # All methods are async
    accounts = await client.accounts.list(platform="instagram")

    # Parallel requests
    tasks = [
        client.analytics.overview(acc.id, period="7d")
        for acc in accounts.data
    ]
    results = await asyncio.gather(*tasks)

    for acc, analytics in zip(accounts.data, results):
        print(f"{acc.instagram_username}: +{analytics.net_growth} followers")

    await client.close()

asyncio.run(main())

Tip — The async client pairs well with FastAPI, Django ASGI, and Sanic.


Accounts

# Create an account
account = client.accounts.create(
    instagram_username="new_handle",
    platform="instagram",
    targeting_config={
        "competitor_accounts": ["competitor1", "competitor2"],
        "hashtags": ["fitness", "wellness"],
        "filters": {
            "age_range": {"min": 18, "max": 44},
            "language": "en",
            "activity_level": "high",
        },
    },
)
print(f"Created: {account.id} (status: {account.status})")

# Update
updated = client.accounts.update(
    "acc_7Gx2kLm9Qr",
    targeting_config={
        "hashtags": ["fitness", "wellness", "nutrition"],
    },
)

# Delete
client.accounts.delete("acc_7Gx2kLm9Qr")

# Pagination
accounts = client.accounts.list(limit=10)
while accounts.has_more:
    accounts = client.accounts.list(limit=10, cursor=accounts.next_cursor)
    for acc in accounts.data:
        print(acc.instagram_username)

# Auto-pagination iterator
for account in client.accounts.list_auto_paging(platform="instagram"):
    print(account.instagram_username)

Analytics

# Overview
overview = client.analytics.overview("acc_7Gx2kLm9Qr", period="30d")
print(f"Followers gained: {overview.followers_gained}")
print(f"Followers lost: {overview.followers_lost}")
print(f"Net growth: {overview.net_growth}")

# Growth time series
growth = client.analytics.growth("acc_7Gx2kLm9Qr", period="7d", granularity="daily")
for point in growth.data_points:
    print(f"{point.date}: {point.followers} (+{point.net})")

# Engagement
engagement = client.analytics.engagement("acc_7Gx2kLm9Qr", period="30d")
for content_type, metrics in engagement.by_content_type.items():
    print(f"{content_type}: {metrics.engagement_rate}%")

# Audience
audience = client.analytics.audience("acc_7Gx2kLm9Qr")
print(f"Quality score: {audience.quality_score}")
print(f"Bot percentage: {audience.bot_percentage}%")

# Custom date range
custom = client.analytics.overview(
    "acc_7Gx2kLm9Qr",
    period="custom",
    start_date="2026-01-01",
    end_date="2026-01-31",
)

Targeting

# Get current config
config = client.targeting.config("acc_7Gx2kLm9Qr")
print(f"Competitors: {config.competitor_accounts}")

# Update targeting
client.targeting.update("acc_7Gx2kLm9Qr", {
    "competitor_accounts": ["new_rival_1", "new_rival_2"],
    "hashtags": ["travel", "digitalnomad"],
    "ai_optimization": {
        "enabled": True,
        "mode": "aggressive",
        "quality_threshold": 0.8,
    },
})

# AI suggestions
suggestions = client.targeting.suggestions(
    "acc_7Gx2kLm9Qr",
    goal="balanced",
    include_reasoning=True,
)
print(f"Confidence: {suggestions.confidence}")
for s in suggestions.suggestions.add_competitors:
    print(f"  Add: @{s.username} (relevance: {s.relevance_score})")
    print(f"  Reason: {s.reasoning}")

Engagement

# Activity log
activities = client.engagement.activity("acc_7Gx2kLm9Qr", type="follow", limit=20)
for act in activities.data:
    print(f"{act.type} -> @{act.target_username} ({act.quality_score})")

# Stats
stats = client.engagement.stats("acc_7Gx2kLm9Qr")
print(f"Likes: {stats.actions.likes.performed}/{stats.actions.likes.limit}")
print(f"Follow-back rate: {stats.conversion_rates.follow_to_follow_back:.1%}")

# Pause / Resume
client.engagement.pause("acc_7Gx2kLm9Qr", reason="Vacation")
client.engagement.resume("acc_7Gx2kLm9Qr")

Webhooks

# Create
webhook = client.webhooks.create(
    url="https://yourapp.com/webhooks/outfame",
    events=["account.growth_milestone", "engagement.daily_summary"],
)
signing_secret = webhook.signing_secret  # Store securely

# Verify signature (helper)
from outfame.webhooks import verify_signature

is_valid = verify_signature(
    payload=request.body,
    signature=request.headers["X-Outfame-Signature"],
    timestamp=request.headers["X-Outfame-Timestamp"],
    secret=signing_secret,
)

# Django example
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def webhook_handler(request):
    if not verify_signature(
        payload=request.body.decode(),
        signature=request.headers.get("X-Outfame-Signature", ""),
        timestamp=request.headers.get("X-Outfame-Timestamp", ""),
        secret=settings.OUTFAME_WEBHOOK_SECRET,
    ):
        return JsonResponse({"error": "Invalid signature"}, status=401)

    event = json.loads(request.body)
    # Process event...
    return JsonResponse({"received": True})

# FastAPI example
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/webhooks/outfame")
async def handle_webhook(request: Request):
    body = await request.body()
    if not verify_signature(
        payload=body.decode(),
        signature=request.headers.get("x-outfame-signature", ""),
        timestamp=request.headers.get("x-outfame-timestamp", ""),
        secret=os.environ["OUTFAME_WEBHOOK_SECRET"],
    ):
        raise HTTPException(status_code=401)

    event = await request.json()
    print(f"Received: {event['type']}")
    return {"received": True}

Error handling

from outfame.exceptions import (
    OutfameError,
    AuthenticationError,
    RateLimitError,
    NotFoundError,
    ValidationError,
)

try:
    account = client.accounts.retrieve("acc_invalid")
except NotFoundError:
    print("Account not found")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except AuthenticationError:
    print("Invalid API key")
except ValidationError as e:
    print(f"Validation errors: {e.errors}")
except OutfameError as e:
    print(f"API error: {e.code} - {e.message}")

Configuration

ParameterTypeDefaultDescription
api_keystrAPI key. Required unless access_token is set.
access_tokenstrNoneOAuth access token.
base_urlstrhttps://api.outfame.com/v1API base URL.
timeoutfloat30.0Request timeout in seconds.
max_retriesint3Automatic retries for transient errors.

Environment variable

# The SDK automatically reads from OUTFAME_API_KEY
export OUTFAME_API_KEY=sk_live_your_api_key

# Then in Python:
client = outfame.Client()  # No api_key argument needed