Instagram channels

The gateway is omnichannel. Alongside WhatsApp you can connect Instagram
accounts and drive their Direct Messages through the same API, webhooks, and
AI smart-reply engine you already use for WhatsApp.

> ⚠️ Unofficial API notice. Instagram has no official DM API for personal/creator
> accounts, so this uses the private API (via the instagrapi engine). Instagram
> may rate-limit, throw a security checkpoint, or ban accounts that automate
> aggressively. Keep volumes low, use a residential connection where possible, and
> treat logins gently. Use at your own risk.

---

1. Create an Instagram channel

Instagram channels are created exactly like WhatsApp ones, with platform: "instagram".

curl -X POST "/api/v1/accounts" \
  -H "Authorization: Bearer ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{"name":"My brand IG","platform":"instagram"}'

The response includes the channel id and a per-channel API token (used for the
message API below).

2. Connect (log in)

Instagram uses credential login instead of a QR. From the dashboard:
Channels → open the channel → Connect, then enter the username and password.
Two-factor and security checkpoints are handled inline.

Programmatically:

# Step 1 — username + password
curl -X POST "/api/v1/accounts/{id}/connect" \
  -H "Authorization: Bearer ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{"username":"yourbrand","password":"••••"}'

The response status is one of:

| status | meaning |
|-----------------------|---------------------------------------------------------------|
| connected | logged in — DMs will start syncing |
| two_factor_required | re-POST /connect adding "verification_code":"123456" |
| challenge_required | a code was sent to email/SMS — submit it to the challenge route |

# Step 2a — 2FA
curl -X POST "/api/v1/accounts/{id}/connect" \
  -H "Authorization: Bearer ADMIN_JWT" -H "Content-Type: application/json" \
  -d '{"username":"yourbrand","password":"••••","verification_code":"123456"}'

Step 2b — security checkpoint

curl -X POST "/api/v1/accounts/{id}/ig/challenge" \ -H "Authorization: Bearer ADMIN_JWT" -H "Content-Type: application/json" \ -d '{"username":"yourbrand","password":"••••","code":"123456"}'

The Instagram session is stored AES-GCM encrypted at rest and never returned to
the dashboard.

3. Receive DMs

There is no push channel for Instagram, so the worker polls for new DMs every
IG_POLL_SECONDS (default 20s). New incoming messages:

4. Send a DM

Use the channel's API token. to is the chat id (ig:) for an existing
thread, or iguser: to start a new one.

curl -X POST "/api/v1/messages/text" \
  -H "Authorization: Bearer CHANNEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"to":"ig:340282366841710300949128","body":"Hi! Thanks for the message 🙌"}'

5. AI smart-reply

Per-channel AI behaviour (auto-reply on/off, system prompt, business knowledge,
manager alerts) is configured under the channel's AI agent tab — identical to
WhatsApp. When enabled, incoming DMs are answered automatically by the AI and the
reply is sent back to the same thread.

6. Webhooks

Instagram emits the platform-neutral events:

The payload chat_id is ig:; from is the sender's username.

---

Roadmap

Phase 1 (this release) covers DMs. Planned next: comment auto-reply, post/reel
publishing + scheduling, stories, media in DMs, and a ManyChat-style visual flow
builder — all engine-neutral so they extend to future Twitter/LinkedIn channels.