Skip to Content
API ReferenceAccounts

Accounts

Connect and manage social media accounts. VoxBurst supports OAuth-based account connection for all major platforms.

Base URL

https://api.voxburst.io/v1/accounts

List Accounts

GET /v1/accounts

List all connected social media accounts.

Query Parameters

ParameterTypeDefaultDescription
statusstringFilter by status. Accepted values: ACTIVE, INACTIVE, ERROR, DISCONNECTED, or all. Uppercase required for query params; response values are lowercase. DISCONNECTED accounts are excluded by default unless includeArchived=true is passed.
platformstringFilter by platform slug (e.g. twitter)
includeArchivedbooleanfalseWhen false (default), DISCONNECTED accounts are excluded from results. Pass true to include disconnected (archived) accounts in the response.
limitinteger20Results per page
cursorstringPagination cursor from previous response

Default behavior changed 2026-06-15: Previously, DISCONNECTED accounts were implicitly included in list results. They are now excluded by default. Integrations that iterate all accounts and act on disconnected ones must add includeArchived=true to their requests.

curl "https://api.voxburst.io/v1/accounts?status=ACTIVE&platform=twitter" \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response

{ "data": [ { "id": "acc_123", "platform": "twitter", "username": "@voxburst", "displayName": "VoxBurst", "avatarUrl": "https://cdn.example.com/avatar.jpg", "accountType": "personal", "status": "active", "connectedAt": "2026-01-15T10:00:00Z" } ], "pagination": { "has_more": false, "next_cursor": null, "limit": 20 } }

The list is paginated using cursor-based pagination. Pass cursor=<nextCursor> as a query parameter to fetch the next page.


Connect Account

POST /v1/accounts/connect/:platform

Initiate OAuth connection for a social media platform. Returns an authorization URL to redirect the user to.

Required scopes: accounts:write

Supported platforms: twitter, linkedin, instagram, facebook, bluesky, threads, youtube, mastodon, tiktok, pinterest, snapchat, reddit, telegram, googlebusiness, whatsapp

Request Body

FieldTypeRequiredDescription
callbackUrlstringYesURI to redirect to after OAuth authorization
forcePromptbooleanNoIf true, forces the OAuth consent screen to re-display even if the user has previously authorized
pageModebooleanNoFor LinkedIn: true to connect as a LinkedIn Page (requires Pages app credentials), false or omit to connect as a personal profile
curl -X POST https://api.voxburst.io/v1/accounts/connect/linkedin \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "callbackUrl": "https://yourapp.com/oauth/callback", "pageMode": true }'

Response

{ "authorizationUrl": "https://x.com/i/oauth2/authorize?...", "state": "oauth_state_token" }

Redirect your user to the authorizationUrl. After authorization, the platform will redirect back to your callbackUrl with a code and state parameter.

The callbackUrl you pass here is validated server-side against an allowlist of permitted domains. URIs that do not match an approved domain are rejected. Use your production app domain (HTTPS required) or localhost for local development.


OAuth Callback

POST /v1/accounts/callback/:platform

Complete the OAuth flow by exchanging the authorization code for access tokens.

Required scopes: accounts:write

curl -X POST https://api.voxburst.io/v1/accounts/callback/twitter \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "code": "oauth_authorization_code", "state": "oauth_state_token" }'

Response

{ "account": { "id": "acc_789", "platform": "twitter", "username": "@newuser", "displayName": "New User", "status": "active", "connectedAt": "2026-02-20T10:00:00Z" } }

Disconnect Account

DELETE /v1/accounts/:id

Disconnect and remove a social media account.

Required scopes: accounts:write

curl -X DELETE https://api.voxburst.io/v1/accounts/acc_123 \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response (200):

{ "success": true }

Refresh Account Token

POST /v1/accounts/:id/refresh

Manually refresh the OAuth token for an account. VoxBurst refreshes tokens automatically, but this endpoint is available for troubleshooting.

Required scopes: accounts:write

curl -X POST https://api.voxburst.io/v1/accounts/acc_123/refresh \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response (200):

{ "success": true }

Test Connection

POST /v1/accounts/:id/test

Test the connection for a social account by making a lightweight API call to the platform.

curl -X POST https://api.voxburst.io/v1/accounts/acc_123/test \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response

{ "success": true, "message": "Connection verified" }

On success, some platforms return additional details:

{ "success": true, "message": "Connection verified", "details": { "platformUserId": "1234567890", "username": "@voxburst", "displayName": "VoxBurst" } }

Get Account

GET /v1/accounts/:id

Retrieve a single connected account by ID.

curl https://api.voxburst.io/v1/accounts/acc_123 \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

List Pages

GET /v1/accounts/:id/pages

List the pages or business accounts associated with a connected account. Currently supported for LinkedIn and Instagram (Facebook Login) accounts.

  • LinkedIn: Returns the organizations the connected user administers. Use these to populate a page selector before creating a LinkedIn post targeting a company page.
  • Instagram (Facebook Login only): Returns the Instagram Business accounts linked to the connected Facebook user token. Legacy Instagram Direct Login accounts return an empty pages array.

For all other platforms, returns an empty pages array.

curl https://api.voxburst.io/v1/accounts/acc_123/pages \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response — LinkedIn

{ "pages": [ { "id": "page_001", "name": "VoxBurst Official", "urn": "urn:li:organization:12345678", "type": "organization", "logoUrl": "https://cdn.example.com/logo.png" } ] }

Response — Instagram

{ "pages": [ { "id": "<ig_user_id>", "name": "@username", "pageId": "<fb_page_id>", "pageName": "Page Display Name", "type": "instagram", "avatarUrl": "https://..." } ] }

The response shape differs by platform. LinkedIn entries include urn and logoUrl; Instagram entries include pageId, pageName, type, and avatarUrl. Both use the top-level id and name fields.


Select Page

POST /v1/accounts/:id/select-page

Persist a page selection for an account. Supported for LinkedIn and Instagram accounts.

  • LinkedIn: Saves the selected LinkedIn Page. Subsequent posts to this account are published to the selected page.
  • Instagram (Facebook Login only): Re-fetches Instagram Business accounts from the Graph API, matches on pageId, and updates the account with username, instagramAccountId, pageAccessToken, pageId, pageName, and oauthVersion: 'fb_login'. Returns 400 INVALID_PAGE_ID if the provided pageId is not found among the accounts accessible via the connected Facebook token.

Required scopes: accounts:write

Request Body

FieldTypeRequiredDescription
pageIdstringYesID of the page to select. For LinkedIn, this is the page’s internal ID. For Instagram, this is the Facebook Page ID (pageId from the List Pages response).
pageNamestringNoDisplay name of the selected page
# LinkedIn example curl -X POST https://api.voxburst.io/v1/accounts/acc_123/select-page \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "pageId": "page_001", "pageName": "VoxBurst Official" }' # Instagram example curl -X POST https://api.voxburst.io/v1/accounts/acc_456/select-page \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "pageId": "<fb_page_id>", "pageName": "Page Display Name" }'

Error Codes

CodeHTTPDescription
INVALID_PAGE_ID400Instagram only — the provided pageId was not found among the Instagram Business accounts accessible via the connected Facebook token. Re-fetch pages with GET /v1/accounts/:id/pages and use a valid pageId from that response.

YouTube Playlists

GET /v1/accounts/:id/youtube/playlists

Returns the YouTube playlists accessible by a connected YouTube account. Use this to populate a playlist selector before creating a YouTube post.

curl https://api.voxburst.io/v1/accounts/acc_123/youtube/playlists \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response (200)

{ "playlists": [ { "id": "PLxxxxxxxxxxxxxxxxxx", "title": "My Tutorial Series" }, { "id": "PLyyyyyyyyyyyyyyyyyy", "title": "Product Demos" } ] }

If the connected account does not have the YouTube playlist read scope, the response returns an empty list with a requiresReauth flag:

{ "playlists": [], "requiresReauth": true }

When requiresReauth is true, prompt the user to reconnect their YouTube account to grant the required scope.


Account Backfill

Get Backfill Status

GET /v1/accounts/:id/backfill

Get the backfill status for a connected account. Backfill pulls historical analytics from the platform.

curl https://api.voxburst.io/v1/accounts/acc_123/backfill \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Trigger Backfill

POST /v1/accounts/:id/backfill

Trigger a historical analytics backfill for a connected account.

Required scopes: accounts:write

curl -X POST https://api.voxburst.io/v1/accounts/acc_123/backfill \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Optimal Posting Times

GET /v1/accounts/:id/optimal-times

Returns the optimal posting time slots for a connected account based on historical engagement data.

Query Parameters

ParameterTypeDescription
timezonestringIANA timezone identifier (default: America/Chicago)
limitintegerNumber of slots to return (1–10, default: 5)
curl "https://api.voxburst.io/v1/accounts/acc_123/optimal-times?timezone=America/New_York&limit=5" \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

GET /v1/instagram/audio/search

Search for audio tracks available for use in Instagram Reels. Returns trending tracks when q is omitted, or filtered results when a search term is provided.

Auth: Bearer token required (read:posts scope)

Feature flag: This endpoint returns 503 FEATURE_DISABLED until the INSTAGRAM_AUDIO_ENABLED environment variable is set. The feature is currently pending Meta App Review and is not yet available in production.

Facebook Login required: The account identified by accountId must have been connected via Facebook Login. Legacy Instagram Direct Login accounts return 400 — prompt the user to reconnect via Facebook Login to use this endpoint.

Query Parameters

ParameterTypeRequiredDescription
accountIdstringYesID of a connected Instagram account (must be Facebook Login-connected)
qstringNoSearch term. Omit to retrieve trending tracks.
limitintegerNoNumber of tracks to return (1–50, default: 20)
# Trending tracks curl "https://api.voxburst.io/v1/instagram/audio/search?accountId=acc_456&limit=10" \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" # Search by term curl "https://api.voxburst.io/v1/instagram/audio/search?accountId=acc_456&q=summer&limit=20" \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx"

Response (200)

{ "tracks": [ { "id": "1234567890", "title": "Track Title", "artistName": "Artist Name", "audioUrl": "https://...", "coverImageUri": "https://...", "durationMs": 30000 } ] }

Response Fields

FieldTypeDescription
tracksobject[]Array of audio track objects
tracks[].idstringTrack identifier (use this when attaching audio to a Reel)
tracks[].titlestringTrack title
tracks[].artistNamestring | undefinedArtist name (may be absent for original audio)
tracks[].audioUrlstring | undefinedDirect audio URL (may be absent depending on Meta’s response)
tracks[].coverImageUristring | undefinedCover art URL
tracks[].durationMsnumber | undefinedTrack duration in milliseconds

Error Codes

CodeHTTPDescription
FEATURE_DISABLED503Audio search is not yet enabled in this environment (pending Meta App Review)
GRAPH_API_ERROR502Meta Graph API returned an error. The message field contains the Meta error detail.
404The accountId was not found or does not belong to this workspace
400The account does not have a pageAccessToken — it was connected via Direct Login rather than Facebook Login. Prompt the user to reconnect via Facebook Login.

Shared Accounts

When the same social media account (identified by platform + platform user ID) is connected in more than one VoxBurst workspace, VoxBurst marks it as a shared account. Posts published from any workspace that share the account count toward a combined platform publishing limit.

When you connect an account that is already connected in another workspace, the connect response includes a warning:

{ "account": { "id": "acc_789", "platform": "instagram", "username": "brandname", ... }, "warning": "This account is already connected in another workspace. Posts to this account from all connected workspaces share a combined publishing limit." }

The isSharedAccount field on the account record is true when this condition applies.


Account Fields

All string enum fields (platform, status, accountType) are returned as lowercase strings in REST API responses.

FieldTypeDescription
idstringAccount ID (cuid2 format, starts with c)
platformstringPlatform slug — always lowercase (e.g. "twitter", "instagram")
usernamestring | nullPlatform username or handle
displayNamestring | nullDisplay name on the platform
avatarUrlstring | nullProfile avatar URL
accountTypestring | nullpersonal, business, or creator — platform-dependent
statusstringSee Account Status below
connectedAtstringISO 8601 timestamp of when the account was connected
needsPlaylistReauthbooleanYouTube only — true when the account lacks the playlist read scope

Account Status

All status and platform values in REST API responses are lowercase strings (e.g. "twitter", "active"). This applies to all account endpoints: list, get, connect callback, refresh, and test.

Query parameters that filter by status or platform accept UPPERCASE values (e.g. status=ACTIVE, platform=TWITTER). The response always returns lowercase regardless of how the query parameter was cased.

Webhook payloads (account.connected, account.error) use UPPERCASE for platform and status — this is intentionally different from REST responses. See Webhooks for details.

Status (response)Query parameter valueDescription
activeACTIVEAccount is connected and tokens are valid
expired(use ERROR)Token has expired — call /refresh or reconnect
disconnectedDISCONNECTEDAccount was disconnected by the user. Excluded from list results by default — pass includeArchived=true to include.
suspended(not filterable)Account has been suspended by the platform
errorERRORPublishing error — check the account’s error details

OAuth Edge Cases

Reconnecting an already-connected account

If a user completes the OAuth flow for an account that is already connected in the same workspace (same platform + platform user ID), VoxBurst upserts the account record: tokens are refreshed, status is reset to ACTIVE, and any previous errors are cleared. No duplicate account is created.

Connecting an account that exists in another workspace

When the same social account is connected across multiple workspaces, VoxBurst flags it as a shared account. The callback response includes a warning field:

{ "account": { "id": "acc_789", "platform": "instagram", ... }, "warning": "This account is already connected in another workspace. Posts to this account from all connected workspaces share a combined publishing limit." }

OAuth state expiry

The OAuth state token stored during the connect step expires after 10 minutes. If the user does not complete authorization within that window, the callback endpoint will return:

{ "error": { "code": "INVALID_PARAM", "message": "Invalid or expired OAuth state" } }

Restart the connect flow to get a fresh state token.

OAuth error codes

CodeHTTPWhen it occurs
INVALID_PARAM400Invalid or expired state, or invalid auth code
PLATFORM_RESTRICTED403Platform is not permitted in this workspace
PLAN_LIMIT_EXCEEDED402Workspace has reached its connected account limit for the current plan

Token expiry and refresh

VoxBurst refreshes tokens automatically when they are within 5 minutes of expiry. If automatic refresh fails (e.g. the user revoked access), the account status is set to EXPIRED or ERROR. At that point:

  • Call POST /v1/accounts/:id/refresh to attempt a manual refresh
  • If refresh fails, the user must reconnect via the full OAuth flow

Bluesky and Mastodon accounts do not use expiring tokens and do not require refresh.


User Endpoints

Store GA4 Client ID

POST /v1/users/me/ga4-client-id

Stores the browser-side GA4 client ID for server-side Measurement Protocol event stitching. Call this once per session after the GA4 client ID becomes available in the browser (typically via gtag('get', ...) or ga.getAll()[0].get('clientId')).

Auth: Bearer token required

Request Body

FieldTypeRequiredDescription
clientIdstringYesGA4 client ID in the format XXXXXXXXX.XXXXXXXXX (two numeric segments separated by a dot). Must match /^\d+\.\d+$/.
curl -X POST https://api.voxburst.io/v1/users/me/ga4-client-id \ -H "Authorization: Bearer vb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "clientId": "1234567890.9876543210" }'

Response (200)

{ "ok": true }

Error Codes

HTTPDescription
400clientId is missing or does not match the required format
401Bearer token is missing or invalid
Last updated on