Instagram's API is notoriously complex — app review, business account requirements, rate limit tiers, and media format restrictions that vary by content type. Aether wraps all of that into three API calls. Here's how to go from zero to your first published post.
Prerequisites
- An Aether account — free tier is enough
- An Aether API key from the dashboard
- Node.js 18+ in your project
1. Install the SDK
npm install aether2. Connect an Instagram account
Aether uses Connect Links to handle Instagram OAuth on your behalf. You generate a one-time URL and redirect your user to it — Aether handles the Instagram app review, permissions, and token storage.
import Aether from "aether";
const aether = new Aether({ apiKey: process.env.AETHER_API_KEY });
// 1. Generate an OAuth link for your user
const link = await aether.connectLinks.create({
platform: "instagram",
redirectUrl: "https://yourapp.com/oauth/instagram/callback",
});
console.log(link.url);
// → https://connect.aetherhq.dev/oauth/ig_...
// Redirect the user to this URLWhile your Aether app is in development, only Instagram accounts you've added as testers in the Meta Developer Portal can complete this flow. Instagram requires app review for production access.
3. Publish and schedule posts
Once an Instagram profile is connected, publishing is a single API call. Use overrides.instagram to attach hashtags, media, or alt text specific to Instagram without affecting other platforms.
// 2. Once connected, list their profiles
const profiles = await aether.profiles.list({ platform: "instagram" });
const profileId = profiles.data[0]?.id;
// 3. Publish a post immediately
const post = await aether.posts.create({
profileIds: [profileId],
text: "Shipping something new today 🚀 #buildinpublic",
overrides: {
instagram: {
hashtags: ["#launch", "#api", "#indiehacker"],
},
},
});
console.log(post.status); // "published"
console.log(post.platformResults?.instagram?.url); // post URLScheduling with timezone support
Pass any ISO 8601 timestamp with a UTC offset to scheduledFor. Aether stores the absolute UTC time and re-derives the local time at publish — so daylight saving transitions don't corrupt your schedule.
// Schedule for 9am EST tomorrow
const scheduled = await aether.posts.create({
profileIds: [profileId],
text: "Good morning from the Aether team ☀️",
scheduledFor: "2026-06-01T09:00:00-05:00",
overrides: {
instagram: {
mediaUrls: ["https://yourcdn.com/image.jpg"],
altText: "Product screenshot showing the new dashboard",
},
},
});
console.log(scheduled.status); // "scheduled"
console.log(scheduled.scheduledFor); // "2026-06-01T14:00:00.000Z"Next steps
- Subscribe to
post.publishedandpost.failedwebhooks to track publish status in your system - Use
GET /v1/analytics/posts/:postIdto pull impressions, likes, and reach after publishing - Check the scheduling guide for rate limits and bulk CSV upload