Back to Blog
Developer Tutorial

Schedule Instagram + Facebook Posts from Node.js in 5 Minutes

A practical step-by-step guide to scheduling social media posts to Instagram and Facebook from a Node.js script using the ViralGhost Agent API. Full code included.

February 26, 20268 min read

Schedule Instagram + Facebook Posts from Node.js in 5 Minutes

If you're building a Node.js app that needs to post to social media — whether it's a marketing tool, a content pipeline, or just your personal automation — you've probably discovered the hard way that Instagram and Facebook's native APIs are painful.

Between Facebook's Graph API permissions, Instagram's content publishing API requirements, and the constant OAuth token management, what should be a simple "post this text and image" turns into days of integration work.

The ViralGhost Agent API reduces this to a single API call. In this tutorial, you'll go from zero to scheduled posts in about 5 minutes.

What We're Building

A Node.js script that:

1. Reads a content plan from a JSON file
2. Schedules posts to both Instagram and Facebook
3. Supports images, scheduling, and AI-generated captions

By the end, you'll have a reusable script that schedules a full week of social content in one run.

Prerequisites

  • Node.js 18+ (we'll use native fetch)

  • A ViralGhost account — [sign up free at viralghost.xyz](https://viralghost.xyz) (no credit card)

  • Instagram and/or Facebook linked in your ViralGhost dashboard

  • Your API key from Settings → API
  • Step 1: Set Up the Project

    bash
    mkdir social-scheduler && cd social-scheduler
    npm init -y

    No dependencies needed — we'll use Node.js built-in fetch and fs.

    Step 2: Get Your API Key and Account IDs

    After signing up at [viralghost.xyz](https://viralghost.xyz):

    1. Link your accounts — Connect Instagram and Facebook from the dashboard
    2. Create an API key — Go to Settings → API → Create Key
    3. Note your account IDs — Each linked account has an ID like acc_instagram_123

    Your API key will look like vg_live_your_api_key. Keep it secret — treat it like a password.

    Step 3: Create Your Content Plan

    Create a content.json file with your posts for the week:

    json
    {
    "posts": [
    {
    "text": "Monday motivation: ship something small today 🚀",
    "image_url": "https://yoursite.com/images/monday.png",
    "day_offset": 0,
    "time": "09:00"
    },
    {
    "text": "New blog post: How we reduced our build time by 60% — link in bio",
    "image_url": "https://yoursite.com/images/blog-preview.png",
    "day_offset": 2,
    "time": "12:00"
    },
    {
    "text": "Friday wins thread 🧵 What did you ship this week?",
    "day_offset": 4,
    "time": "15:00"
    },
    {
    "text": "Weekend project ideas for developers 👇",
    "image_url": "https://yoursite.com/images/weekend.png",
    "day_offset": 5,
    "time": "10:00"
    }
    ]
    }

    Each post has the caption text, an optional image URL, and when to publish relative to next Monday.

    Step 4: Build the Scheduler Script

    Create schedule.mjs:

    javascript
    import fs from "fs";

    const API_KEY = process.env.VIRALGHOST_API_KEY || "vg_live_your_api_key";
    const BASE_URL = "https://api.viralghost.xyz/v1";

    // Replace with your actual account IDs from the dashboard
    const ACCOUNTS = {
    instagram: "acc_instagram_123",
    facebook: "acc_facebook_456"
    };

    async function apiCall(endpoint, body) {
    const resp await fetch(${BASE_URL}${endpoint}, {
    method: "POST",
    headers: {
    "Authorization": Bearer ${API_KEY},
    "Content-Type": "application/json"
    },
    body: JSON.stringify(body)
    });

    const data = await response.json();

    if (!response.ok) {
    throw new Error(API error: ${data.message} (${data.error}));
    }

    return data;
    }

    function getNextMonday() {
    const now = new Date();
    const m new Date(now);
    monday.setDate(now.getDate() + ((1 + 7 - now.getDay()) % 7 || 7));
    monday.setHours(0, 0, 0, 0);
    return monday;
    }

    async function scheduleWeek() {
    const { posts } = JSON.parse(fs.readFileSync("content.json", "utf-8"));
    const m getNextMonday();

    console.log(Scheduling ${posts.length} posts starting ${monday.toLocaleDateString()}\n);

    for (const post of posts) {
    const scheduleDate = new Date(monday);
    scheduleDate.setDate(monday.getDate() + post.day_offset);
    const [hours, minutes] = post.time.split(":");
    scheduleDate.setHours(parseInt(hours), parseInt(minutes), 0, 0);

    const payload = {
    accounts: [ACCOUNTS.instagram, ACCOUNTS.facebook],
    content: { text: post.text },
    schedule_at: scheduleDate.toISOString()
    };

    if (post.image_url) {
    payload.content.image_url = post.image_url;
    }

    try {
    const result = await apiCall("/posts", payload);
    console.log(✅ Scheduled for ${scheduleDate.toLocaleString()}: "${post.text.substring(0, 50)}...");
    console.log( Post ID: ${result.post_id});
    console.log( Platforms: Instagram, Facebook\n);
    } catch (err) {
    console.error(❌ Failed to schedule: ${err.message}\n);
    }
    }
    }

    scheduleWeek();

    Step 5: Run It

    bash
    VIRALGHOST_API_KEY=vg_live_your_api_key node schedule.mjs

    You'll see output like this:


    Scheduling 4 posts starting 3/3/2026

    ✅ Scheduled for 3/3/2026, 9:00:00 AM: "Monday motivation: ship something small today 🚀..."
    Post ID: pst_abc123
    Platforms: Instagram, Facebook

    ✅ Scheduled for 3/5/2026, 12:00:00 PM: "New blog post: How we reduced our build time by 60%..."
    Post ID: pst_def456
    Platforms: Instagram, Facebook

    ✅ Scheduled for 3/7/2026, 3:00:00 PM: "Friday wins thread 🧵 What did you ship this week?..."
    Post ID: pst_ghi789
    Platforms: Instagram, Facebook

    ✅ Scheduled for 3/8/2026, 10:00:00 AM: "Weekend project ideas for developers 👇..."
    Post ID: pst_jkl012
    Platforms: Instagram, Facebook

    That's it. Four posts scheduled to two platforms in one command.

    Step 6: Add AI-Generated Captions

    Don't want to write every caption by hand? Use the AI generation endpoint:

    javascript
    async function generateAndSchedule(topic, dayOffset, time) {
    // Step 1: Generate a caption
    const generated = await apiCall("/ai/generate", {
    type: "caption",
    prompt: topic,
    tone: "casual",
    platform: "instagram"
    });

    console.log(📝 Generated: "${generated.content.substring(0, 60)}...");

    // Step 2: Schedule it
    const m getNextMonday();
    const scheduleDate = new Date(monday);
    scheduleDate.setDate(monday.getDate() + dayOffset);
    const [hours, minutes] = time.split(":");
    scheduleDate.setHours(parseInt(hours), parseInt(minutes), 0, 0);

    const result = await apiCall("/posts", {
    accounts: [ACCOUNTS.instagram, ACCOUNTS.facebook],
    content: { text: generated.content },
    schedule_at: scheduleDate.toISOString()
    });

    console.log(✅ Scheduled for ${scheduleDate.toLocaleString()});
    console.log( Post ID: ${result.post_id}\n);

    return result;
    }

    // Schedule a full week with AI-generated content
    await generateAndSchedule("Monday motivation for developers", 0, "09:00");
    await generateAndSchedule("Promote our latest blog post about build optimization", 2, "12:00");
    await generateAndSchedule("Friday wins - ask what people shipped this week", 4, "15:00");
    await generateAndSchedule("Weekend side project ideas", 5, "10:00");

    Now you're generating AND scheduling content with zero manual copywriting.

    Example API Response

    Here's what the API returns when you schedule a post:

    json
    {
    "post_id": "pst_abc123",
    "status": "scheduled",
    "accounts": ["acc_instagram_123", "acc_facebook_456"],
    "content": {
    "text": "Monday motivation: ship something small today 🚀",
    "image_url": "https://yoursite.com/images/monday.png"
    },
    "scheduled_at": "2026-03-03T09:00:00.000Z",
    "created_at": "2026-02-26T17:00:00.000Z"
    }

    And here's an error response (e.g., invalid account ID):

    json
    {
    "error": "invalid_account",
    "message": "Account acc_invalid_123 not found or not linked to your workspace.",
    "status": 400
    }

    Adding to Your Existing App

    If you're integrating into an existing Node.js app (Express, Next.js, etc.), wrap the API call in a utility:

    javascript
    // lib/viralghost.mjs
    const API_KEY = process.env.VIRALGHOST_API_KEY;
    const BASE_URL = "https://api.viralghost.xyz/v1";

    export async function schedulePost({ accounts, text, imageUrl, scheduleAt }) {
    const payload = {
    accounts,
    content: { text }
    };
    if (imageUrl) payload.content.image_url = imageUrl;
    if (scheduleAt) payload.schedule_at = scheduleAt;

    const res = await fetch(${BASE_URL}/posts, {
    method: "POST",
    headers: {
    "Authorization": Bearer ${API_KEY},
    "Content-Type": "application/json"
    },
    body: JSON.stringify(payload)
    });

    if (!res.ok) {
    const err = await res.json();
    throw new Error(err.message);
    }

    return res.json();
    }

    // Usage in your Express route:
    // import { schedulePost } from "./lib/viralghost.mjs";
    // app.post("/api/schedule", async (req, res) => {
    // const result = await schedulePost(req.body);
    // res.json(result);
    // });

    Free Tier: What You Get

    The [ViralGhost free tier](/docs/agent-api) includes:

  • 2 social accounts (perfect for Instagram + Facebook)

  • 30 posts/month (about 1/day)

  • 15 AI generations/month

  • Full API access — same endpoints as paid plans
  • No credit card required. If you need more volume, Pro ($49/mo) bumps you to 10 accounts and 500 posts/month.

    Next Steps

  • [Read the full API docs](/docs/agent-api) for all available endpoints

  • Add X (Twitter) and LinkedIn by linking more accounts and adding their IDs

  • Set up a cron job to run your scheduler weekly

  • Build an admin dashboard that uses the API to manage content

  • [Get your free API key at viralghost.xyz](https://viralghost.xyz) and start scheduling posts from Node.js in minutes.

    Topics covered:

    Instagram API postingFacebook Pages APIschedule social media posts Node.jsViralGhost Agent APINode.js social media automationInstagram scheduling API

    Share this article:

    Deploy Your AI Social Agent

    Stop spending hours on social media. Train your AI agent on your voice and maintain consistent presence in just 30 minutes daily.

    Start Free Trial