POST/v1/connect/{platform}

Connect a social account

Kicks off the OAuth flow for a platform. Synposter gives you an authorization URL that you redirect the end user to. Once they approve, Synposter exchanges the authorization code for OAuth tokens behind the scenes, stores them safely encrypted, and registers the new connected account under the profile you chose, so you never have to handle access tokens or refresh logic yourself.

The flow

  1. 1

    Your backend asks Synposter for an authorization URL

    Your server sends a POST to /v1/connect/{platform} with the profile that the new connected account should belong to. You can optionally include a redirectUri of your own; if you omit it, Synposter will send the end user to its own hosted confirmation page once the flow finishes, which is useful for command-line tools and other headless integrations.

  2. 2

    Synposter responds with an authorization URL

    The response includes a single field, authUrl, that points to the platform's authorization page. Your server redirects the end user's browser there.

  3. 3

    The end user authorizes the connection on the platform

    The user signs in to the platform if they aren't already signed in, reviews the permissions Synposter is requesting, and approves the request.

  4. 4

    The platform sends the user back to Synposter

    Once the user approves, the platform redirects their browser to Synposter's callback URL. Synposter exchanges the authorization code for OAuth access and refresh tokens, encrypts them at rest, and stores them as a new connected-account record under the profile you chose in the first step.

  5. 5

    Synposter sends the user back to your application

    Finally, Synposter redirects the user's browser to your redirectUri, appending profileId, accountId, platform, handle, and the original state value you sent (if any) as query parameters so your application knows which connection just completed. If you didn't supply a redirectUri, the user instead lands on Synposter's built-in success page and can simply close the window.

Request

curl -X POST https://api.synposter.com/v1/connect/twitter \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profileId": "9b3a...",
    "redirectUri": "https://yourapp.com/connected",
    "state": "your-end-user-id"
  }'

Body

FieldTypeRequiredDescription
profileIdstringNoProfile to attach the connected account to. If omitted, your default profile is used.
redirectUristringNoWhere to send the user after the OAuth flow completes (success or failure). Must use either http:// or https:// — other schemes (javascript:, data:, file:, etc.) are rejected with 400 invalid_redirect_uri. If omitted, the user lands on a Synposter-hosted success page, useful for CLI tools and other headless integrations.
statestringNoOpaque value echoed back to your redirectUri. Use it to correlate the connection with your end user (e.g. their ID in your DB).

Response (200)

json
{
  "authUrl": "https://x.com/i/oauth2/authorize?response_type=code&client_id=..."
}

Redirect the end user's browser to authUrl, typically a 302 from your server.

Status codes

200Auth URL returned.
400Returned with one of invalid_json (the request body wasn't valid JSON or didn't parse to an object) or invalid_redirect_uri (the redirectUri wasn't a parseable URL or wasn't http(s)).
401The API key was missing or invalid.
404Returned with profile_not_found (the profileId doesn't exist or belongs to a different developer; same code in both cases for leak-proofness) or no_profile_found (you didn't pass a profileId and your account has no default profile).
500Returned with internal_error (Synposter is misconfigured or a database lookup failed) or failed_to_persist_state (we couldn't write the OAuth state row). Safe to retry.

Final redirect to your app

On success, Synposter redirects the user's browser to:

text
{your redirectUri}?profileId=...&accountId=...&platform=twitter&handle=...&state=...

Query parameters on success

FieldTypeRequiredDescription
profileIdstringYesProfile the account was attached to.
accountIdstringYesID of the new connected account.
platformstringYese.g. "twitter".
handlestringNoPlatform-side username.
statestringNoThe same value you passed in the request body, echoed back so you can correlate this redirect with the original connect call (e.g. your end-user ID). Only present if you sent one. Not Synposter's internal CSRF nonce.

On error

On any failure (user declined, token exchange failed, state expired, etc.) Synposter still redirects to your redirectUri but with an error param instead of accountId:

text
{your redirectUri}?error=token_exchange_failed&state=...
FieldTypeRequiredDescription
access_deniedstringNoUser declined on the platform consent screen.
missing_codestringNoPlatform redirected without an auth code.
state_expiredstringNoMore than 10 minutes passed between connect and callback.
token_exchange_failedstringNoPlatform rejected the auth code.
user_lookup_failedstringNoCouldn't fetch the connected user's profile after token exchange.
persist_failedstringNoInternal database error storing the tokens.
internal_errorstringNoSynposter is misconfigured (typically a missing platform credential). Capture the x-request-id and contact support.
platform_errorstringNoGeneric catch-all for any other OAuth 2 error code the platform returned (invalid_request, invalid_scope, server_error, temporarily_unavailable, unauthorized_client, unsupported_response_type). The original code is preserved verbatim only for the access_denied case; everything else is collapsed to platform_error so we never reflect arbitrary platform-supplied text into your redirect URL. Check the Synposter logs by request id for the raw cause.

For triage, every response from POST /v1/connect/{platform} includes an x-request-id header. Capture it on your backend before redirecting the user, and share it with support if a connection fails. We can trace the full chain (auth, profile lookup, token exchange, database write) from that single ID.

Platform OAuth apps

You don't need to register your own OAuth app with each platform. Synposter already has its own apps registered and receives the platform's callback at /api/callback/{platform}. Your redirectUri is optional: if you supply one, Synposter forwards the user there after the handshake completes; if you omit it, the user lands on a Synposter-hosted success page instead, useful for CLI tools and other headless integrations.