White-Label Integration
Embed PostPulse social media publishing inside your own product. Your users never see the PostPulse brand — only your own UX, your own login, and your own pricing.
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.
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).
Once at startup (and refreshed on expiry), exchange your clientId / clientSecret for an access token at https://auth.post-pulse.com/oauth/token.
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.
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.
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.
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
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.
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.
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.
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.
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, orX-Connect-External-User-Id: <externalUserId>— using your own ID directly.
Both headers are equivalent; pick whichever fits your data model.
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
redirectUriyou 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.
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 -> READYSchedule 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.
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <m2m_access_token> from the Auth0 client credentials grant. |
x-api-key | For /connect/authorize-url | Your partner clientId. Used to bind the signed Connect state to your account. |
X-Connect-User-Id | One of these two | The PostPulse uuid returned by /connect/users. |
X-Connect-External-User-Id | One of these two | The 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.
What the demo covers:
- Client-credentials token caching with expiry tracking.
- Transparent
getOrCreateUserusingexternalUserId. - OAuth bridge launch with a custom URL scheme (
vibestudio://callback). - Asynchronous media import with progress polling (
QUEUED→DOWNLOADING→READY). - 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.