Overview

The PostPulse white-label (Connect) integration lets you offer multi-platform social publishing to your users without building any of the OAuth, scheduling, or platform publishing infrastructure yourself. You authenticate as a partner using a single machine-to-machine credential, and you act on behalf of your end-users by passing a lightweight identity header on every request.

🏷️ Your Brand

Your users never see the PostPulse name — emails are suppressed, billing is yours, and the only PostPulse-hosted UI is the OAuth bridge.

🔐 One Credential

Auth0 client credentials grant. One clientId / clientSecret covers all of your users.

🆔 Identity Mapping

Provision a PostPulse user once with your own externalUserId, then impersonate it on every call.

📱 9 Platforms

Instagram, TikTok, YouTube, Facebook, X, LinkedIn, Threads, Bluesky, Telegram — same API surface as the rest of PostPulse.

No subscription, no seat limits, no email noise. White-label users are isolated from PostPulse's regular subscription and notification flows. You handle pricing and communication with your end-users; PostPulse handles publishing.

How It Works

Three actors are involved: your backend (holds the M2M credential), your end-user (clicks "Connect Instagram" inside your product), and PostPulse (handles the OAuth dance with the social platform and stores the tokens).

1Your backend gets an M2M access token from Auth0

Once at startup (and refreshed on expiry), exchange your clientId / clientSecret for an access token at https://auth.post-pulse.com/oauth/token.

2Provision the PostPulse user for your end-user

Call POST /connect/users with your stable externalUserId. PostPulse returns a uuid. Cache it — you'll send it on every subsequent call as X-Connect-User-Id.

3Generate a one-time Connect URL

Call POST /connect/authorize-url with the target platform and a redirectUri (a URL or app deep-link you own). PostPulse returns a short-lived signed URL on app.post-pulse.com/oauth/connect.

4Open the URL in a browser / WebView

PostPulse handles the platform OAuth (PKCE, state, scopes, callback). When the user finishes, PostPulse stores the tokens against your end-user and redirects the browser to the redirectUri you supplied.

5Use the rest of the PostPulse API as that user

From your backend, call /accounts, /media/upload/import, /posts, etc. with Authorization: Bearer <m2m_token>and X-Connect-User-Id: <uuid>. Everything works exactly like the standard API — just with partner auth.

Prerequisites

1

Get partner credentials

White-label access is provisioned manually. Reach out at [email protected] with a short description of your product. We will issue an Auth0 clientId and clientSecret scoped for the PostPulse API audience.

2

Pick your redirect URIs

Decide where the OAuth bridge should hand the user back when a connection completes — a URL on your site (e.g. https://yourapp.com/connected), http://localhost:<port>/... while developing, or a custom scheme for mobile (e.g. myapp://callback). You don't need to pre-register them with PostPulse.

3

Store credentials server-side

The clientSecret must never reach a browser or mobile binary that ships to end-users. Hold it in your backend and proxy the calls.

Why no redirect-URI allowlist? The redirectUri you pass to /connect/authorize-url is sealed inside a short-lived, HMAC-signed whitelabel_state JWT produced by your M2M-authenticated backend — it can't be tampered with mid-flow. The hand-off back to your app happens only after PostPulse has exchanged the OAuth code for tokens and stored them server-side; no code, state, or access_token is ever appended to that final redirect. The dangerous redirect — the one that actually carries the OAuth code from the social platform — is locked down by PostPulse and pre-registered with each platform's developer console.

Authentication (M2M)

All white-label endpoints accept a standard Auth0 client credentials bearer token. Issue one token, cache it until it expires, and reuse it across all of your users.

Request a token

POST https://auth.post-pulse.com/oauth/token
Content-Type: application/json

{
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "grant_type": "client_credentials",
  "audience": "https://api.post-pulse.com"
}

The response contains an access_token and expires_in (seconds). Cache the token until shortly before expiry, then refresh.

Security: Treat the clientSecret like a database password. Rotate it via PostPulse support if it leaks. Do not embed it in mobile apps or SPAs.

Provision a User

The first time one of your end-users does anything social-related, provision them. The call is idempotent on (apiClientId, externalUserId) — safe to call repeatedly.

Endpoint

POST https://api.post-pulse.com/v1/connect/users

POST /v1/connect/users
Authorization: Bearer <m2m_access_token>
Content-Type: application/json

{
  "externalUserId": "user_42",
  "name": "Jane Doe",
  "email": "[email protected]"
}

Response

{
  "uuid": "0fe1b3a2-8b40-4d4c-9bb9-2f0d9dca57ad",
  "name": "Jane Doe",
  "email": "[email protected]"
}

Persist the returned uuid alongside your own user record. From this point forward, send it on every API call as either:

  • X-Connect-User-Id: <uuid> — using the PostPulse UUID, or
  • X-Connect-External-User-Id: <externalUserId> — using your own ID directly.

Both headers are equivalent; pick whichever fits your data model.

Email is optional but recommended. White-label users are excluded from PostPulse marketing, posting-success, and posting-failure emails — you own the user relationship. Email is only stored for your reference.

Connect a Social Account

Connecting a social account is the only step that involves a user-visible browser redirect. PostPulse hosts a thin OAuth bridge at app.post-pulse.com/oauth/connectthat handles the platform-specific OAuth flow on your behalf.

Step 1: Generate the Connect URL

POST /v1/connect/authorize-url
Authorization: Bearer <m2m_access_token>
x-api-key: YOUR_CLIENT_ID
X-Connect-User-Id: <uuid_from_provision>
Content-Type: application/json

{
  "platform": "INSTAGRAM",
  "redirectUri": "https://yourapp.com/connected"
}

Supported platform values: INSTAGRAM, FACEBOOK, YOUTUBE, TIKTOK, X_TWITTER, LINKEDIN, THREADS.

The response body is a single string — a short-lived signed URL such as https://app.post-pulse.com/oauth/connect?whitelabel_state=eyJhbGc....

Step 2: Open the URL in a browser

Open the returned URL in the user's browser (web), an in-app browser, or a system browser tab (mobile). PostPulse will:

  • Verify the signed state and PKCE parameters.
  • Redirect the user to the social platform's authorization screen.
  • Receive the platform callback and exchange it for tokens.
  • Store the tokens against your end-user.
  • Redirect the browser to the redirectUri you supplied.

When you receive the redirect at redirectUri, the connection is complete — no extra exchange is required from your side. Refresh your UI / call /accountsto reflect the new connection.

Mobile deep-links: Use a custom URL scheme like myapp://callbackso the browser hands control back to your native app after the redirect. Make sure the scheme is registered in your iOS Info.plist and Android intent filters so the OS routes the hand-off to your app.

Publishing & Media

Once an account is connected, the rest of the PostPulse API is identical to the standard product — just keep sending the partner auth headers.

List a user's connected accounts

GET /v1/accounts
Authorization: Bearer <m2m_access_token>
x-api-key: YOUR_CLIENT_ID
X-Connect-User-Id: <uuid>

Asynchronous media import (recommended for large files)

For videos and large images, use the asynchronous import endpoint and poll until status: "READY":

POST /v1/media/upload/import
{
  "url": "https://cdn.example.com/big-video.mp4",
  "filenameHint": "promo.mp4"
}

GET /v1/media/upload/import/{id}    # poll: QUEUED -> DOWNLOADING -> READY

Schedule a post

POST /v1/posts
Authorization: Bearer <m2m_access_token>
x-api-key: YOUR_CLIENT_ID
X-Connect-User-Id: <uuid>
Content-Type: application/json

{
  "platform": "INSTAGRAM",
  "accountId": 12345,
  "content": "Hello from your app",
  "mediaPaths": ["<path_returned_by_import>"],
  "scheduledTime": "2026-05-10T15:00:00Z",
  "publicationType": "REEL"
}

For the full schema of /posts, including platform-specific fields, see the API Documentation. Behaviour is identical to the non-white-label flow.

Reference: Required Headers

Every white-label call takes the same three headers. Memorise these and you know the integration.

HeaderRequiredDescription
AuthorizationYesBearer <m2m_access_token> from the Auth0 client credentials grant.
x-api-keyFor /connect/authorize-urlYour partner clientId. Used to bind the signed Connect state to your account.
X-Connect-User-IdOne of these twoThe PostPulse uuid returned by /connect/users.
X-Connect-External-User-IdOne of these twoThe same externalUserId you used to provision the user.

Calls to /connect/users only need Authorization — you don't have a user UUID yet at that point.

Demo App

We maintain an open-source Flutter demo — VibeStudio Mobile Demo — that shows the full end-to-end integration: M2M auth, user provisioning, connecting accounts via deep-link, async media import, and scheduling posts.

The demo is reference code, not a production starter. It's the fastest way to see every white-label call in context and to estimate the scope of work for your own integration.

View Demo on GitHub →

What the demo covers:

  • Client-credentials token caching with expiry tracking.
  • Transparent getOrCreateUser using externalUserId.
  • OAuth bridge launch with a custom URL scheme (vibestudio://callback).
  • Asynchronous media import with progress polling (QUEUEDDOWNLOADINGREADY).
  • Platform-specific publish settings (Instagram Reels, TikTok privacy level, etc.).

Get Access

White-label access is provisioned per partner. Email [email protected] with:

  • A short description of your product and how social publishing fits in.
  • Estimated user volume and target launch date.
  • The redirect URIs (web and / or mobile) you'll be using.

We'll issue your Auth0 client credentials and walk you through a sandbox integration.