Skip to content
reelspanDocs

Accounts

White-label connect

Let your clients connect their own social accounts to a profile through a branded hosted page, or through your own connect page built on the Connect API.

POSTapi.reelspan.com/v1/connect-linksTry it →

When your clients own the social accounts, they should connect them themselves: they sign in on each network, and you never handle their passwords. Reelspan gives you two ways to do that without a Reelspan login for them:

  • A hosted connect link: one call returns a link to a page with your logo, texts and language. Send it to your client.
  • Your own connect page: you build the page, and call the Connect API to start each network's sign-in.
curl -X POST https://api.reelspan.com/v1/connect-links \
  -H "Authorization: Bearer $REELSPAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "my-brand",
    "platforms": ["tiktok", "instagram", "youtube"],
    "logo_image": "https://example.com/logo.png",
    "connect_title": "Connect your accounts to Example Studio",
    "redirect_url": "https://example.com/onboarding/done",
    "redirect_button_text": "Back to Example Studio",
    "language": "es",
    "connect_theme": "dark"
  }'
{ "success": true, "access_url": "https://app.reelspan.com/connect?token=eyJhbGciOiJIUzI1NiIs…", "duration": "48h" }

Send access_url to your client. It works for 48 hours; make a new one whenever you need it. Anyone with the link can connect accounts to that one profile, so send it only to the person it is for.

What the page shows

  • Your logo, title and description, or Reelspan's default texts.
  • Each network you listed in platforms (every network when you leave it out). OAuth networks have a Connect button that opens the network's sign-in; Bluesky and the other credentials networks show a short form for the token or key.
  • For each connected network: the account's name, a Disconnect button, and Reconnect when the account needs it.
  • The profile's scheduled posts, unless you send show_calendar: false.
  • A button back to your redirect_url, labelled with redirect_button_text (default "Done").

After each sign-in your client returns to the same page, which says whether the network connected, was cancelled, or failed and why.

Branding options

Field What it does Plans
username The profile the link connects accounts to. Required. All
platforms The networks to offer, by id (up to 20). Your client can't connect any other network with this link, here or through the Connect API. All
redirect_url Where the page's final button goes. An http or https address. All
show_calendar false hides the scheduled posts. All
readonly_calendar true makes a view-only link: your client sees the connections and scheduled posts, but can't connect or disconnect anything. All
language The page's language (see Languages). All
logo_image Your logo, as an http or https image URL. White-label
connect_title The heading, up to 120 characters. White-label
connect_description The text under it, up to 500 characters. White-label
redirect_button_text The final button's label, up to 60 characters. White-label
connect_theme light, dark or auto (the default). White-label
ui_labels Your own wording for any text on the page (see Your own wording). White-label

White-label is part of the Pro, Agency and Scale plans; those plans also drop the "Secure connection powered by Reelspan" line at the bottom of the page. On Free and Starter the link still works with Reelspan's look: the white-label fields are left out, and the answer says so in warnings.

{
  "success": true,
  "access_url": "https://app.reelspan.com/connect?token=…",
  "duration": "48h",
  "warnings": ["Branding (logo_image, connect_title) needs a plan with white-label; the link uses Reelspan's default look."]
}

Settings are remembered

Branding is saved on the profile, so the next link for that profile only needs username. Fields you send change only themselves; the rest stay as they were. Send ui_labels: null (or {}) to clear your labels.

readonly_calendar is fixed into each link when it is made: changing it later doesn't change links already sent.

Languages

The hosted page comes in English (en), Spanish (es), German (de), French (fr), Portuguese (pt), Polish (pl) and Turkish (tr). Without language, it follows your client's browser language, and falls back to English.

Your own wording

ui_labels replaces any text on the page, in any language. Send up to 100 labels, each up to 300 characters:

{ "username": "my-brand", "ui_labels": { "connect.button": "Link account", "calendar.title": "Coming up" } }
Key Default text
connect.title Connect your social accounts
connect.description Connect the accounts you want us to publish to. You can disconnect them here at any time.
connect.button Connect
connect.reconnect Reconnect
connect.disconnect Disconnect
connect.connected Connected
connect.success connected.
connect.cancelled was not connected: permission was not granted.
connect.error could not be connected
connect.expired This link has expired or is not valid. Ask for a new one.
connect.done Done
connect.maintenance Under maintenance. It can't be connected right now; check back soon.
calendar.title Scheduled posts
calendar.empty Nothing is scheduled.
bluesky.handle Bluesky handle
bluesky.password App password (Settings → Privacy and security → App passwords). Never your main password.
footer.powered Secure connection powered by Reelspan

connect_title and connect_description take priority over the connect.title and connect.description labels.

Embedding

The hosted page can be shown in an <iframe> on any https site, so your client can connect without leaving your app.

Your own connect page

To keep your client on your own site from start to finish, build the page yourself and use the Connect API for the OAuth networks:

  1. Start: call POST /v1/oauth/{platform}/start. The answer has an authorize_url.
  2. Send your client to authorize_url. They sign in on the network and allow access.
  3. They come back to your redirect_url with the outcome in the query string.

You can call it from your server with your API key and the profile:

curl -X POST https://api.reelspan.com/v1/oauth/youtube/start \
  -H "Authorization: Bearer $REELSPAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"profile": "my-brand", "redirect_url": "https://example.com/connected"}'
{ "success": true, "platform": "youtube", "authorize_url": "https://accounts.google.com/o/oauth2/v2/auth?…", "state": "q3J9…", "expires_in": 900 }

Or, from your client's browser, with a connect link's token instead of your key. Take the token from a link's access_url (the token parameter) and send it as the Bearer token, with no profile:

curl -X POST https://api.reelspan.com/v1/oauth/youtube/start \
  -H "Authorization: Bearer $CONNECT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"redirect_url": "https://example.com/connected"}'

A token can do only what its link allows: the link's platforms, nothing on a read-only link, and at most 20 sign-ins every 10 minutes. If the profile has a redirect_url saved, a token's redirect_url must be on the same site, or the saved one is used.

The flow

  • authorize_url works once, for 15 minutes (expires_in: 900).
  • platform is the network's id: youtube, tiktok, instagram, facebook, x (or twitter), threads, linkedin, pinterest, reddit or google_business (or google-business).
  • Always send redirect_url. Without one, your client ends on the Reelspan dashboard.

When your client comes back, read these query parameters:

Parameter Value
connect_status success, cancelled (they declined on the network) or error
platform The network
error_code On cancelled and error: for example ACCESS_DENIED, INVALID_STATE (the link expired or was used), PROVIDER_ERROR or CONNECTION_FAILED
error_description On cancelled and error: a readable reason
https://example.com/connected?connect_status=success&platform=youtube

Then confirm with GET /v1/profiles/{username}: the network's entry in social_accounts now has the account. Each connect and disconnect also fires the social_account_connected and social_account_disconnected webhooks.

Credentials networks on your page

Bluesky, Telegram, Discord and the other credentials networks have no sign-in to start: POST /v1/oauth/{platform}/start answers 400 NOT_OAUTH for them. Collect the fields on your page and send them from your server with Connect with credentials, or send your client the hosted link for those.

Check a token

GET /v1/connect-links/validate, with the connect token as the Bearer token, tells your page whether a link is still good and what the profile has connected:

curl https://api.reelspan.com/v1/connect-links/validate \
  -H "Authorization: Bearer $CONNECT_TOKEN"
{
  "success": true,
  "isValid": true,
  "profile": {
    "username": "my-brand",
    "social_accounts": {
      "youtube": "",
      "tiktok": { "username": "-000Abc…", "handle": "@mybrand", "display_name": "My Brand", "social_images": "https://…", "reauth_required": false, "capabilities": ["video", "draft", "video_privacy"] }
    },
    "ui_labels": {}
  }
}

An expired or altered token answers 401 with isValid: false.

Errors

Status error_code When
400 NOT_OAUTH The network connects with credentials, not a sign-in.
400 UNSUPPORTED_PLATFORM No such OAuth network.
400 PROVIDER_NOT_CONFIGURED The network can't be connected right now; the message says why.
401 The API key or connect token is invalid or expired.
403 ACCESS_DENIED The token's link doesn't offer this network, or is read-only.
403 PROFILE_FORBIDDEN The API key is limited to other profiles.
404 PROFILE_NOT_FOUND No profile has that username.
429 RATE_LIMITED More than 20 sign-ins started with one link in 10 minutes.

Creating links and starting sign-ins with an API key need the profiles scope.

POSTapi.reelspan.com/v1/connect-linksTry it →

Request body

application/json

  • redirect_urlstring
  • logo_imagestring
  • redirect_button_textstring
  • connect_titlestring
  • connect_descriptionstring
  • platformsstring[]
  • show_calendarboolean
  • readonly_calendarboolean
  • languagestring

    enesdefrptpltr

  • ui_labelsobject
  • connect_themestring

    lightdarkauto

  • usernamestringrequired

Responses

200 Link

{
  "success": true,
  "access_url": "string",
  "duration": "string",
  "warnings": [
    "string"
  ]
}

400 Invalid input

{
  "success": false,
  "message": "string",
  "error": "string",
  "error_code": "string"
}

401 Invalid key or token

{
  "success": false,
  "message": "string",
  "error": "string",
  "error_code": "string"
}
GETapi.reelspan.com/v1/connect-links/validateTry it →

Responses

200 Valid

{
  "success": true,
  "isValid": true,
  "profile": {}
}

401 Invalid or expired

{
  "success": false,
  "message": "string",
  "error": "string",
  "error_code": "string"
}
POSTapi.reelspan.com/v1/oauth/{platform}/startTry it →

Parameters

  • platformstring · pathrequired

Request body

application/json

  • profilestring
  • redirect_urlstring

Responses

200 Started

{
  "success": true,
  "platform": "string",
  "authorize_url": "string",
  "state": "string",
  "expires_in": 0
}

400 Invalid input

{
  "success": false,
  "message": "string",
  "error": "string",
  "error_code": "string"
}

401 Invalid key or token

{
  "success": false,
  "message": "string",
  "error": "string",
  "error_code": "string"
}

Something unclear or missing? Write to [email protected] and we’ll fix the page.