Share:

Instagram Auto-Posting — Developer Handoff

Everything a developer needs to finish connecting Instagram to the ICONIC client platform.
Last updated: 4 April 2026

Overall Status: 95% built. Code is complete — OAuth flow, posting API, admin dashboard, client dashboard, content generation. The blocker is configuration: Meta App credentials need to be set up (requires a human with a Facebook account to create the developer app), then a scheduled posting cron needs to be added. No new code is needed for basic posting to work.

1. The Full Client Journey (End to End)

SALE Scott closes a client on a video call Scott tags contact iconic-contract-signed in GHL (GoHighLevel CRM) AUTO-SMS (5-min cron in serve_reports.js) Detects the tag → sends registration SMS with link → tags iconic-reg-link-sent REGISTER /iconic/register.html?email=X&name=X&tier=entry&icn=ICN-XXXXXX Client opens link → sets password → POST /api/iconic/register → Saves to Supabase + iconic_clients.json → Updates GHL (name, custom fields, pipeline opportunity) → Auto-login → redirect to dashboard DASHBOARD /iconic/dashboard.html Client sees: photos, stats, plan info, upload prompt, Instagram section CONNECT INSTAGRAM Client clicks "Connect Instagram Account" → Goes to /iconic/instagram_onboarding.html (setup guide) → Steps 1-3: Business account + Facebook Page + link them (client does on phone) → Steps 4-6: Meta Developer App + credentials + token (admin does once) → Step 7: Click "Connect" → auto-setup exchanges token → saves config AUTO-POSTING (after connected) System posts AI photos to client's Instagram automatically Admin monitors via /iconic/instagram_admin.html

2. What's Built vs What's Missing

ComponentFileStatusNotes
Graph API wrapperIconic/instagram_post.jsDONESingle + carousel posting, container polling, caption gen. 455 lines.
OAuth + client managementIconic/instagram_manager.jsDONEToken exchange, per-client tokens, queue, health checks. 597 lines.
14 API endpointsserve_reports.jsDONEOAuth flow, posting, admin CRUD, config, health. See Section 4.
Onboarding guideIconic/instagram_onboarding.htmlDONE7-step click-by-click setup with auto-connect button.
Client dashboard IG sectionIconic/dashboard.htmlDONEConnected/not-connected states, disconnect button.
Admin dashboardIconic/instagram_admin.htmlPARTIALUI built. JS needs wiring to admin endpoints.
Content generationIconic/generate_social.jsDONE60+ styles (feed/stories/reels), male + female.
Client setup guideIconic/instagram_client_setup.htmlDONE"I have IG" vs "I need IG" paths.
Meta App credentialsig_app_config.jsonEMPTYBLOCKER. Needs human to create Meta Developer App.
Scheduled posting cronserve_reports.jsTODOprocessScheduledPosts() exists but nothing calls it.
Admin endpoint authserve_reports.jsTODOAll /api/instagram/admin/* endpoints are unprotected.

3. Key Files

FilePurposeLines
Iconic/instagram_post.jsLow-level Graph API v22.0 wrapper. Single image + carousel posting. Container creation → polling → publishing. Exported: graphRequest, createMediaContainer, publishMedia, createCarousel, postWithToken, postCarouselWithToken, verifyAccount, makeConfig, generateCaption455
Iconic/instagram_manager.jsPer-client OAuth, token storage, posting queue, health checks. Exported: getOAuthUrl, handleCallback, saveClientInstagram, disconnectClient, postToClient, postCarouselToClient, queuePost, processScheduledPosts, checkTokenHealth, checkAllTokenHealth, getAllClientsInstagramStatus, updateClientSettings, getPostingHistory, loadAppConfig, saveAppConfig597
serve_reports.jsMain server. All 14 Instagram API endpoints live here. Also has the auto-setup endpoint and checkInstagramStatus function.7374
ig_app_config.jsonMeta App ID + Secret storage. Currently EMPTY. Auto-setup endpoint also saves access token and IG account ID here.4
iconic_clients.jsonClient database. Each client gets an .instagram object added after OAuth with: connected, username, igAccountId, pageId, accessToken, status, postCount, autoPost, postsPerWeek~53
Iconic/instagram_onboarding.html7-step setup guide. Steps 1-3 (phone), Steps 4-6 (Meta developer portal), Step 7 (auto-connect button calls /api/instagram/auto-setup).~500
Iconic/instagram_admin.htmlAdmin dashboard: client list, config form, posting history, token health check. UI built, JS partially wired.~150
Iconic/generate_social.js60+ Instagram content styles (feed 1:1, stories 9:16, reels 9:16). Male + female variants. Uses OHWX LoRA trigger word.~150

4. All API Endpoints

MethodPathAuthWhat It Does
GET/api/instagram/statusNoneCheck if central @iconicbyai account is configured. Checks process.env → ig_app_config.json → Windows env vars.
GET/api/instagram/connectSession cookieRedirects client to Meta OAuth. Encodes email in state param. Requires Meta App ID to be saved.
GET/api/instagram/callbackPublic (Meta redirect)Handles OAuth callback. Exchanges code → short-lived → long-lived token. Finds IG account. Saves to iconic_clients.json. Redirects to dashboard.
GET/api/instagram/client-statusSession cookieReturns logged-in client's IG status: connected, username, postCount, autoPost, followers.
POST/api/instagram/disconnectSession cookieClears client's IG tokens and sets status to disconnected.
POST/api/instagram/post-nowNoneImmediately posts a photo to a client's IG. Body: {email, photoFile, caption}.
POST/api/instagram/auto-setupNoneOne-click setup: takes shortLivedToken, exchanges for long-lived, finds IG account, saves everything to ig_app_config.json + process.env.
GET/api/instagram/admin/clientsNoneList all clients with their IG connection status.
POST/api/instagram/admin/settingsNoneUpdate client's autoPost and postsPerWeek. Body: {email, autoPost, postsPerWeek}.
GET/api/instagram/admin/historyNoneGet last 50 posts across all clients.
GET/api/instagram/admin/configNoneGet Meta App ID (no secret exposed).
POST/api/instagram/admin/configNoneSave Meta App ID + Secret. Body: {appId, appSecret}.
POST/api/instagram/admin/queueNoneQueue a photo for scheduled posting. Body: {email, photoFile, caption, scheduledFor}.
POST/api/instagram/admin/check-healthNoneCheck token health for all connected clients.

5. What Needs to Be Done (In Order)

Phase 1: Unblock the Configuration (Human Required)

A human with a Facebook account needs to do these steps. The onboarding guide at /iconic/instagram_onboarding.html walks through this click-by-click:

  1. Switch the @iconicbyai Instagram account to a Business account (Instagram app → Settings → Account type → Business)
  2. Create a Facebook Page (facebook.com → Pages → Create, or Facebook app → Menu → Pages → Create)
  3. Link the Instagram account to that Facebook Page (Instagram → Edit Profile → Page → select the page)
  4. Create a Meta Developer App at developers.facebook.com (type: Business, add Instagram product)
  5. Copy the App ID and App Secret from the app's Settings → Basic page
  6. Generate an access token via the Graph API Explorer with 4 permissions: instagram_basic, instagram_content_publish, pages_show_list, pages_read_engagement
  7. Paste the App ID, App Secret, and token into the onboarding page → click "Connect" → auto-setup does the rest
After Step 7, ig_app_config.json will be populated and all OAuth flows will work. No code changes needed.

Phase 2: Add Scheduled Posting Cron (Developer — 5 min)

The function processScheduledPosts() in instagram_manager.js already processes queued posts. It just needs to be called on a schedule.

Add this to serve_reports.js near the existing cron jobs (search for cron.schedule):

// Instagram scheduled posting — every 30 minutes
cron.schedule('*/30 * * * *', async () => {
  try {
    const igm = getIgManager();
    const count = await igm.processScheduledPosts();
    if (count > 0) console.log(`[IG Scheduler] Posted ${count} scheduled items`);
  } catch (e) {
    console.error('[IG Scheduler] Error:', e.message);
  }
}, { timezone: 'America/Chicago' });

Phase 3: Secure Admin Endpoints (Developer — 30 min)

All /api/instagram/admin/* endpoints currently have no auth. Add a check for an admin session or API key before each one. Pattern:

// Add at the top of each admin endpoint:
const adminEmails = ['[email protected]']; // or check a role
const sessionToken = parseCookies(req).iconic_session;
const email = getEmailFromSession(sessionToken);
if (!email || !adminEmails.includes(email)) {
  res.writeHead(401, { 'Content-Type': 'application/json' });
  return res.end(JSON.stringify({ ok: false, error: 'Admin access required' }));
}

Phase 4: Wire Up Admin Dashboard (Developer — 1-2 hours)

Iconic/instagram_admin.html has the UI built but needs its JavaScript completed to call the admin API endpoints (fetch clients, save config, check health, view history, queue posts).

Phase 5: Token Refresh Notification (Developer — 30 min)

Long-lived page tokens don't expire, but user tokens last 60 days. If a client's token dies:

6. Per-Client Data Structure

After a client connects Instagram, their record in iconic_clients.json gets an .instagram field:

{
  "[email protected]": {
    "name": "Neil Spence",
    "tier": "entry",
    "plan": "entry",
    "password": "...",
    "instagram": {
      "connected": true,
      "username": "iconicbyai",
      "igAccountId": "17841400000000",
      "pageId": "123456789",
      "accessToken": "EAA...long_page_token...",
      "connectedAt": "2026-04-04T12:00:00.000Z",
      "lastPostAt": null,
      "postCount": 0,
      "autoPost": false,
      "postsPerWeek": 3,
      "status": "active",
      "followers": 150,
      "profilePic": "https://..."
    }
  }
}

7. Posting Flow (How a Photo Gets to Instagram)

1. TRIGGER Admin calls POST /api/instagram/post-now Body: { email: "[email protected]", photoFile: "1_Profile.jpg", caption: "Your new look" } 2. LOOKUP Server finds client in iconic_clients.json Gets: accessToken, igAccountId from client.instagram Gets: sessionId from client record → builds image URL Image URL: https://reports.iconicbyai.com/api/uploads/{sessionId}/generated/{photoFile} 3. CREATE CONTAINER POST to Graph API: /{igAccountId}/media Body: { image_url, caption, access_token } Returns: containerId 4. WAIT FOR PROCESSING Poll GET /{containerId}?fields=status_code every 2 seconds Wait until status_code = "FINISHED" (max 60 seconds) 5. PUBLISH POST to Graph API: /{igAccountId}/media_publish Body: { creation_id: containerId, access_token } Returns: mediaId (the live Instagram post ID) 6. UPDATE RECORDS client.instagram.postCount++ client.instagram.lastPostAt = now Save to iconic_clients.json

8. Live URLs

PageURLWho Sees It
Setup Guidereports.iconicbyai.com/iconic/instagram_onboarding.htmlAdmin (one-time setup)
Client Dashboardreports.iconicbyai.com/iconic/dashboard.htmlClients (has IG section)
Client Setupreports.iconicbyai.com/iconic/instagram_client_setup.htmlClients (OAuth guide)
Admin Dashboardreports.iconicbyai.com/iconic/instagram_admin.htmlAdmin only
Admin Hubreports.iconicbyai.com/iconic/hubAdmin only
Instagram Previewreports.iconicbyai.com/iconic/instagram_preview.htmlClients

9. Environment & Tech Stack

10. Testing Checklist

OAuth Flow

Single Image Posting

Scheduled Posting (after cron is added)

Token Health