POST /api/v1/connect/{platform}
OAuth authorization URL for the account owner (valid 10 minutes, single use). Facebook: the owner picks Pages; the result may be a pending connection. WhatsApp: a Postgale page that runs Meta's Embedded Signup (several numbers → pending connection). Telegram has no OAuth: the answer is a one-time code (15 minutes) and instructions: a chat admin adds Postgale's bot as an admin with the right to post and sends /connect <code> in the channel or group (or forwards that channel post to the bot); the chat then appears in GET /api/v1/accounts and account.connected is emitted. Discord: a server admin installs Postgale's bot (scope bot) and picks channels, one account per channel (platformAccountId = channel id); POST /api/v1/connect/discord binds more channels of that server (without DISCORD_BOT_TOKEN the link creates a channel webhook instead, platformAccountId = webhook id). Mastodon needs instance (the server's domain; public DNS names only): Postgale registers itself on that server if needed and the link opens its authorization page (platformAccountId = <id>@<server>). Bluesky has no OAuth: POST {handle, appPassword} (a Bluesky app password, never the account password) connects the account right away and answers {platform, account}; a refused handle or password is a 400. Platforms that are not live on this instance answer 400. Same as GET with externalId (and instance) in the JSON body; Bluesky needs POST with handle and appPassword
BearerAuthAuthorizationBearer <token>API key sk_...
platform*string"instagram""tiktok""x""linkedin""facebook""threads""whatsapp""telegram""discord""bluesky""mastodon"application/json- body
externalId?stringYour reference, stored on the connected account(s)
length <= 200instance?stringMastodon: the server's domain, e.g. hachyderm.io (required for mastodon)
length <= 253handle?stringBluesky: the handle (e.g. yourname.bsky.social) or DID
appPassword?stringBluesky: an app password (xxxx-xxxx-xxxx-xxxx) from Settings → Privacy and security → App passwords. Stored encrypted
password{authUrl, expiresInSeconds}; for telegram {code, command, botUsername, instructions, expiresAt, expiresInSeconds}; for bluesky {platform, account}
application/json- response
authUrl?stringexpiresInSeconds?integercurl -X POST 'https://example.com/api/v1/connect/instagram' \ -H 'Content-Type: application/json' \ -d '{}'{ "authUrl": "string", "expiresInSeconds": 0}GET /api/v1/connect/{platform} GET
OAuth authorization URL for the account owner (valid 10 minutes, single use). Facebook: the owner picks Pages; the result may be a pending connection. WhatsApp: a Postgale page that runs Meta's Embedded Signup (several numbers → pending connection). Telegram has no OAuth: the answer is a one-time code (15 minutes) and instructions: a chat admin adds Postgale's bot as an admin with the right to post and sends /connect <code> in the channel or group (or forwards that channel post to the bot); the chat then appears in GET /api/v1/accounts and account.connected is emitted. Discord: a server admin installs Postgale's bot (scope bot) and picks channels, one account per channel (platformAccountId = channel id); POST /api/v1/connect/discord binds more channels of that server (without DISCORD_BOT_TOKEN the link creates a channel webhook instead, platformAccountId = webhook id). Mastodon needs instance (the server's domain; public DNS names only): Postgale registers itself on that server if needed and the link opens its authorization page (platformAccountId = <id>@<server>). Bluesky has no OAuth: POST {handle, appPassword} (a Bluesky app password, never the account password) connects the account right away and answers {platform, account}; a refused handle or password is a 400. Platforms that are not live on this instance answer 400
GET /api/v1/connect/linkedin GET
Not supported: LinkedIn session connect has no OAuth link. POST the session cookies instead