Instagram Graph API
Meta's Graph API requires weeks of app review, 60-day token rotation, and 3-step carousel container calls. Aether wraps all of that into one endpoint — so you skip the bureaucracy and ship in a day.
One API call. No carousel containers, no token-refresh cron jobs, no app review.
import Aether from "aether";
const aether = new Aether({ apiKey: process.env.AETHER_API_KEY });
// Post a photo to Instagram
const post = await aether.posts.create({
text: "Shipping something new today 🚀 #buildinpublic",
profileIds: ["ig_abc123"],
mediaUrls: ["https://your-cdn.com/launch-photo.jpg"],
scheduledFor: "2026-06-15T09:00:00Z",
});
console.log(post.status); // "scheduled"
console.log(post.id); // "post_2k4mn8x"Free tier · 3 accounts · no credit card
Get your free API keyimport os
import aether
client = aether.Aether(api_key=os.environ["AETHER_API_KEY"])
post = client.posts.create(
text="Shipping something new today 🚀 #buildinpublic",
profile_ids=["ig_abc123"],
media_urls=["https://your-cdn.com/launch-photo.jpg"],
scheduled_for="2026-06-15T09:00:00Z",
)
print(post.status) # "scheduled"curl -X POST https://api.aetherhq.dev/v1/posts \
-H "Authorization: Bearer $AETHER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Shipping something new today 🚀 #buildinpublic",
"profileIds": ["ig_abc123"],
"mediaUrls": ["https://your-cdn.com/launch-photo.jpg"],
"scheduledFor": "2026-06-15T09:00:00Z"
}'Aether returns a normalized post object. The publishResults array populates after publishing with per-platform status and the platform-native post ID.
{
"success": true,
"data": {
"id": "post_2k4mn8x",
"status": "scheduled",
"text": "Shipping something new today 🚀 #buildinpublic",
"profileIds": ["ig_abc123"],
"mediaUrls": ["https://cdn.aetherhq.dev/org_9p2qrs/launch-photo.jpg"],
"mediaKeys": ["org_9p2qrs/launch-photo.jpg"],
"scheduledFor": "2026-06-15T09:00:00.000Z",
"timezone": null,
"publishResults": [],
"publishedAt": null,
"failedAt": null,
"createdAt": "2026-06-08T14:23:11.000Z"
}
}Getting instagram_content_publish directly takes weeks: build a Meta app, record a screen-share demo, submit for review, wait for approval, then build a 60-day token refresh cron job.
Aether's Connect Link removes all of that. Call one endpoint to generate a branded OAuth URL, send it to your user, and their Instagram account appears in your dashboard — no Meta portal work on your side.
// Generate an Instagram Connect Link for your user
const link = await aether.connectLinks.create({
platform: "instagram",
redirectUrl: "https://yourapp.com/settings/social",
});
// Send link.url to your user.
// They click, authenticate on Instagram, and their account
// appears in your Aether dashboard automatically.
console.log(link.url);
// "https://connect.aetherhq.dev/link/cl_xk9p2m..."
console.log(link.expiresAt);
// "2026-06-15T14:23:11.000Z"Aether's Connect Link handles Instagram OAuth for your users — no Meta app review on your side. One Connect Link URL, one click, account connected.
Single posts, carousels, Reels, and Stories in one API call. Timezone-aware scheduling, immediate publishing, or bulk CSV upload.
Read and reply to Instagram comments and DMs programmatically. Unified inbox API surface across all platforms.
Impressions, reach, engagement, saves, and follower delta — per post and per account. Normalized schema, sub-second Tinybird queries.
Historical engagement analysis returns the optimal hours and days to publish for each connected account — per platform.
Every endpoint is simultaneously an MCP tool. Claude Desktop, Cursor, or any MCP-compatible agent can post to Instagram without extra integration code.
These are Instagram's platform-level limits. Aether automatically queues and retries requests that hit them — your code does not need to handle backoff logic.
| Operation | Limit | Error code | Note |
|---|---|---|---|
| Content publish | 50 posts / 24 h | 341 | Per Instagram account |
| API calls | 200 calls / hr / token | 17 | Per access token |
| Media upload | 100 MB per file | 352 | Images + videos |
| Video (Feed) | 60 seconds max | — | MP4 / MOV |
| Reels | 90 min max · 50 / day | — | Per account |
| Carousel | 10 items max | 100 | Images or videos |
| Code | Meaning | How Aether handles it |
|---|---|---|
| 190 | Invalid / expired OAuth token | Aether auto-refreshes tokens — reconnect the account if this persists |
| 200 | Permission error — missing scope | Re-connect via Connect Link; Aether requests all required scopes upfront |
| 341 | Daily publish limit reached (50/day) | Aether queues and retries after the window resets |
| 368 | Account temporarily blocked by Instagram | Content policy violation — review post and resubmit |
| 10 | App permission denied (app review gate) | Use Aether — Meta app review is Aether's responsibility, not yours |
| 100 | Invalid request parameter | Aether validates the request before forwarding; check your input |
AI-Native
Aether ships an MCP server that exposes every REST endpoint — including Instagram publishing — as a callable tool. Claude Desktop, Cursor, Windsurf, and any MCP-compatible agent can post to Instagram with no extra integration code.
# Add to ~/.claude/claude_desktop_config.json (or Cursor settings)
{
"mcpServers": {
"aether": {
"command": "npx",
"args": ["-y", "aether-mcp"],
"env": { "AETHER_API_KEY": "sk_live_..." }
}
}
}
# Claude can now post to Instagram directly:
# "Post this image to Instagram scheduled for 9am tomorrow"With Aether you call POST /v1/posts with your Instagram profile ID and content. Aether handles all underlying Graph API calls — media containers, carousel assembly, and scheduling — so you send one request and get back one normalized post object.
No. Aether's platform app has already completed Meta's app review and holds the instagram_content_publish permission. Your integration only needs an Aether API key — no Meta developer portal work required on your side.
Instagram allows 50 published posts per 24 hours per account and 200 API calls per hour per access token. Aether automatically queues and retries requests that hit platform rate limits, and surfaces the status in the post's publishResults field.
Yes. Pass scheduledFor as an ISO 8601 datetime string (e.g. '2026-06-15T09:00:00Z'). Aether stores the post as 'scheduled' and publishes it at the right time. Pass a timezone string to schedule relative to the account's local time zone.
Yes. The free tier includes 3 connected social accounts, full API access, the MCP server, and all features. No credit card required. Upgrade when you need more accounts.
Free tier · 3 accounts · full API access · MCP server · no credit card.
Get your free API key →