← back to Norma Platform
agents/instagram-agent/POSTING.md
66 lines
# Instagram posting — multi-account (35 accounts, one command)
All 35 IG-linked accounts post through **one never-expiring token**
(`META_ACCESS_TOKEN` in `~/Projects/secrets-manager/.env`) via the Facebook Graph
Content Publishing API. No per-account tokens, no refresh cron.
## CLI — `post-to.js`
```bash
cd ~/Projects/Norma/agents/instagram-agent
node post-to.js list # all 35, ranked by followers
node post-to.js verify <account> # read-only: prove the token reaches it
node post-to.js verify --verify-all # health-sweep every account
# POST (dry-run by default — add --confirm to actually publish)
node post-to.js <account> --product <handle> --confirm # real DW product (auto image+caption)
node post-to.js <account> --image <public_url> --caption "…" --confirm # single image
node post-to.js <account> --images "u1,u2,u3" --caption "…" --confirm # carousel (2–10)
node post-to.js <account> --reel <public_mp4> --caption "…" --confirm # reel
node post-to.js <account> --story <public_url> --confirm # story
node post-to.js --all --image <public_url> --caption "…" --confirm # fan out to ALL 35
```
`<account>` = handle (`velvetwallpaper` / `@velvetwallpaper`), page name
(`"Velvet Wallpaper"`), or the raw `ig_user_id`.
### Safety
- **Dry-run is the default.** Nothing publishes without `--confirm` — the
outward-facing gate is built into the tool.
- `--all` throttles 1.5s/account (each account has its own ~50-posts/24h API limit).
- Media URLs must be **public** (Meta fetches them server-side). Shopify CDN URLs work.
## HTTP — `:9810` (agent-base, Basic-Auth)
The `post`, `reel`, and `story` skills accept an `account` field, so any fleet
agent can publish to a specific handle:
```bash
curl -s -u admin:$PASS -X POST http://127.0.0.1:9810/api/skill/post \
-H 'Content-Type: application/json' \
-d '{"account":"velvetwallpaper","image_url":"https://…","caption":"…"}'
```
Account resolution is **registry-first, env-fallback**:
1. handle in `accounts.json` → shared `META_ACCESS_TOKEN`
2. `dw` → `IG_USER_ID` + `IG_ACCESS_TOKEN` (legacy)
3. `phillipe-romano` etc. → `IG_USER_ID_<SUFFIX>` + `IG_ACCESS_TOKEN_<SUFFIX>`
(the dw-marketing-reels convention — unchanged)
## Registry — `accounts.json`
Regenerate from the live token (self-healing — link a new IG in Meta Business
Suite and it appears):
```bash
node build-registry.js # refresh handles/ids
node build-registry.js --stats # also pull follower/post counts (35 extra GETs)
```
## Not yet postable
- The 45 Facebook Pages with **no linked IG account** (see
`UNLINKED-PAGES-CHECKLIST.md`) — they'd need IG accounts *created* first.
- `@hospitalityfabrics` — exists (360 followers, 177 posts) but isn't connected
to a Page, so the API can't reach it. Parked on a Page decision.