Skip to main content

Connecting Accounts from the API

Everything else in this API assumes a connected social account. This page is how you get one without touching the dashboard — from a script, a CLI, or an AI agent (the MCP tools create_connect_link, create_reconnect_link, and connect_credential_account wrap these endpoints).

There are two connection styles, decided by the platform:

StylePlatformsBrowser needed?
OAuth connect linkx, instagram, facebook, youtube, pinterest, threads, linkedin, tiktokOne click by the account owner (the platform's own consent screen; that hop is imposed by the platforms, not us)
Direct credentialstelegram, discord, blueskyNone. Fully in-API

OAuth platforms: POST /v1/accounts/connect-link

curl -X POST https://app.posteverywhere.ai/api/v1/accounts/connect-link \
-H "Authorization: Bearer pe_live_..." \
-H "Content-Type: application/json" \
-d '{"platform": "instagram"}'
{
"data": {
"platform": "instagram",
"url": "https://www.instagram.com/oauth/authorize?...",
"expires_in_seconds": 600,
"instructions": "Have the instagram account owner open this URL in any browser within 10 minutes..."
},
"error": null
}

The flow, gh auth login style:

  1. Mint the link (requires the write scope; expires in 10 minutes).
  2. Hand it to the account owner. They can open it in any browser — they do not need to be logged in to PostEverywhere there; the link carries a signed, single-org grant of who initiated it.
  3. They approve on the platform's consent screen.
  4. The account lands in your organization. Poll GET /v1/accounts until the new account appears (typically seconds after approval), then post to it.

Security properties: the link is HMAC-signed and bound to your organization and workspace, expires after 10 minutes, and can only ever ADD an account to the organization that minted it. It grants the clicker nothing. Treat it like any invite link: send it to the account owner directly, not somewhere public.

Credential platforms: POST /v1/accounts/connect-credential

No browser, validated live against the platform before saving:

# Telegram: bot from @BotFather, bot must be an ADMIN of the channel
curl -X POST .../v1/accounts/connect-credential \
-H "Authorization: Bearer pe_live_..." -H "Content-Type: application/json" \
-d '{"platform": "telegram", "bot_token": "123456:ABC...", "channel": "@mychannel"}'

# Discord: Server Settings > Integrations > Webhooks
-d '{"platform": "discord", "webhook_url": "https://discord.com/api/webhooks/..."}'

# Bluesky: Settings > App Passwords (never the main account password)
-d '{"platform": "bluesky", "handle": "me.bsky.social", "app_password": "xxxx-xxxx-xxxx-xxxx"}'

Bad credentials return a 400 with the platform's reason, so agents can self-correct. Re-submitting credentials for an already-connected account updates it in place — that is also how these platforms reconnect.

Fixing a dead token: POST /v1/accounts/{id}/reconnect

When GET /v1/accounts/{id}/health reports needs_reconnection or token_expired, mint a repair link:

curl -X POST https://app.posteverywhere.ai/api/v1/accounts/1234/reconnect \
-H "Authorization: Bearer pe_live_..."

Same mechanics as connect-link, with one rule: the owner must approve while logged in to the platform as that same profile. Matching is by the platform's account id — authorizing as a different profile connects a new account instead of repairing this one. Verify with the health endpoint afterwards.

Notes for agents

  • list_accounts before and after is the confirmation loop: mint link, wait for the human, poll until the platform appears, then proceed to posting.
  • A connect link that expires unclicked costs nothing; mint a fresh one.
  • Connecting an account someone ELSE's PostEverywhere workspace already holds is blocked by an anti-hijack guard; the human will see an explanatory error and should contact support if they believe they own the account.