Guides/Python

Social media API from Python

Complete Python guide: install the SDK, connect social accounts via OAuth, post to 7 platforms, schedule with datetime, pull analytics, manage the inbox, and handle webhooks with Flask.

~15 minPython 3.9+Flask (optional)
Prerequisites
  • • Python 3.9+ with pip
  • • An Aether account — free, no credit card required
  • • At least one connected social profile (Business/Creator accounts for Instagram)

Step 1 — Install the SDK

pip install aether

Set your API key as an environment variable:

# Set your API key in the environment
export AETHER_API_KEY="your_api_key_here"

# Or use a .env file with python-dotenv:
# pip install python-dotenv
# AETHER_API_KEY=your_api_key_here

Step 2 — Instantiate the client

import os
from aether import Aether

client = Aether(api_key=os.environ["AETHER_API_KEY"])

# Verify the connection
profiles = client.profiles.list()
print(f"Connected profiles: {len(profiles.data)}")

Step 3 — Connect a social account

Each platform requires OAuth. Aether's Connect Links handle the entire flow — generate a URL, open it in a browser, authenticate on the platform, and the profile appears in your account immediately:

import os
import webbrowser
from aether import Aether

client = Aether(api_key=os.environ["AETHER_API_KEY"])

# Generate an OAuth Connect Link for Instagram
link = client.connect_links.create(
    platform="instagram",
    # After authentication, Instagram redirects here
    redirect_url="https://your-app.com/oauth/callback",
)

print(f"Connect URL: {link.url}")
# Open in the browser so the user can authenticate
webbrowser.open(link.url)

# After OAuth, the profile appears immediately:
profiles = client.profiles.list()
instagram = next(p for p in profiles.data if p.platform == "instagram")
print(f"Connected: {instagram.display_name} ({instagram.id})")
# ig_abc123

Step 4 — Post immediately

Pass an array of profile IDs to post to multiple platforms in one call:

import os
from aether import Aether

client = Aether(api_key=os.environ["AETHER_API_KEY"])

# Post immediately to multiple platforms
post = client.posts.create(
    text="New release is live — check the changelog 🚀",
    profile_ids=[
        "ig_abc123",   # Instagram
        "li_comp789",  # LinkedIn
        "th_user456",  # Threads
    ],
    media_urls=["https://your-cdn.com/release-screenshot.png"],
)

print(post.data.id)      # post_abc123
print(post.data.status)  # "publishing"

Step 5 — Schedule for a future time

Pass scheduled_for as an ISO 8601 string. Python's datetime module makes this straightforward:

import os
from datetime import datetime, timezone, timedelta
from aether import Aether

client = Aether(api_key=os.environ["AETHER_API_KEY"])

# Schedule for tomorrow at 9am UTC
tomorrow_9am = (
    datetime.now(timezone.utc).replace(hour=9, minute=0, second=0, microsecond=0)
    + timedelta(days=1)
).isoformat()

post = client.posts.create(
    text="Good morning — here's what we shipped this week.",
    profile_ids=["ig_abc123", "li_comp789"],
    scheduled_for=tomorrow_9am,  # "2026-07-16T09:00:00+00:00"
)

print(post.data.status)       # "scheduled"
print(post.data.scheduled_for)  # 2026-07-16T09:00:00+00:00

Per-platform content overrides

Use the overrides dict to write different copy per platform — all in one API call:

# Per-platform overrides — tailor content per profile in one call
post = client.posts.create(
    text="Default caption — shown if no override is set for a profile.",
    profile_ids=["ig_abc123", "li_comp789", "tt_xyz789"],
    overrides={
        "ig_abc123": {
            "text": "Launch day 🎉 #buildinpublic #saas #startup",
        },
        "li_comp789": {
            "text": (
                "Today we shipped a major product update. "
                "Here's what changed and what's coming next:"
            ),
        },
        "tt_xyz789": {
            "text": "we shipped something wild. let me explain 👀",
        },
    },
)

Pull analytics

Account-level and post-level metrics across all platforms:

import os
from aether import Aether

client = Aether(api_key=os.environ["AETHER_API_KEY"])

# Account-level metrics for the last 30 days
metrics = client.analytics.get_account_metrics(
    from_date="2026-06-01",
    to_date="2026-06-30",
    granularity="day",
    platform="instagram",  # optional — omit for all platforms
)

for point in metrics.data:
    print(f"{point.date}: {point.impressions} impressions, {point.engagement} engagements")

# Post-level metrics
post_metrics = client.analytics.get_post_metrics("post_abc123")
for m in post_metrics.data:
    print(f"{m.platform}: {m.metric_type} = {m.value}")

Read and reply to the inbox

DMs and comments from all platforms in one unified API:

# Read and reply to DMs across all platforms
messages = client.inbox.list(status="unread", limit=20)

for msg in messages.data:
    print(f"[{msg.platform}] {msg.sender_name}: {msg.text}")

    # Reply to the message
    if "pricing" in msg.text.lower():
        client.inbox.reply(
            message_id=msg.id,
            text="Thanks for reaching out! Here's our pricing: https://aetherhq.dev/pricing",
        )

Handle webhooks with Flask

Build a Flask endpoint to receive real-time publish confirmations and incoming messages. Always verify the HMAC-SHA256 signature:

# Flask webhook handler with HMAC verification
import os
import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route("/webhooks/aether", methods=["POST"])
def webhook():
    sig = request.headers.get("X-Aether-Signature", "")

    if not verify_signature(request.data, sig, os.environ["AETHER_WEBHOOK_SECRET"]):
        return jsonify({"error": "Invalid signature"}), 401

    payload = request.get_json(force=True)
    event   = payload.get("event")
    data    = payload.get("data", {})

    if event == "post.published":
        print(f"Published on {data['platform']}: {data.get('platformPostUrl')}")
        # Update your DB, notify users, etc.

    elif event == "post.failed":
        print(f"Failed on {data['platform']}: {data['error']['message']}")
        # Alert the user, schedule retry, etc.

    elif event == "message.created":
        print(f"New DM from {data['senderName']} on {data['platform']}")
        # Trigger auto-reply flow, alert support team, etc.

    return jsonify({"received": True}), 200

if __name__ == "__main__":
    app.run(port=5000)

Async usage

The SDK ships an AsyncAether client for use with asyncio:

# Async usage with httpx (Aether's Python SDK supports async)
import os
import asyncio
from aether import AsyncAether

async def main():
    client = AsyncAether(api_key=os.environ["AETHER_API_KEY"])

    # Post to 3 platforms concurrently
    post = await client.posts.create(
        text="Shipped something new today 🚀",
        profile_ids=["ig_abc123", "li_comp789", "th_user456"],
        scheduled_for="2026-07-20T09:00:00Z",
    )
    print(post.data.status)

    # Pull analytics while waiting on post confirmation
    metrics, profiles = await asyncio.gather(
        client.analytics.get_account_metrics(
            from_date="2026-07-01",
            to_date="2026-07-14",
        ),
        client.profiles.list(),
    )
    print(f"{len(profiles.data)} profiles, {len(metrics.data)} data points")

asyncio.run(main())
What you've covered
  • pip install aether + API key setup
  • Connecting social accounts via Connect Links
  • Immediate and scheduled posting to multiple platforms
  • Per-platform content overrides in one call
  • Account and post analytics
  • Unified inbox read and reply
  • Flask webhook receiver with HMAC-SHA256 verification
  • Async usage with AsyncAether

Start building

Free API key — 3 connected accounts, all endpoints, no credit card.