How to let clients connect their social media accounts A branded link instead of shared passwords
Do not ask for passwords. Create one Upload-Post profile per client and send them a branded connection link, or build the connection into your own app. They log in to TikTok, Instagram, LinkedIn and the rest with each network’s own OAuth, and you post for them by naming their profile.
# 1. One profile per client
curl -X POST https://api.upload-post.com/api/uploadposts/users \
-H "Authorization: Apikey $UPLOAD_POST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username": "bakery-co"}'
# 2. A branded connection link for that profile
curl -X POST https://api.upload-post.com/api/uploadposts/users/generate-jwt \
-H "Authorization: Apikey $UPLOAD_POST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username": "bakery-co",
"logo_image": "https://youragency.com/logo.png",
"connect_title": "Connect your accounts",
"platforms": ["instagram", "tiktok", "linkedin"],
"redirect_url": "https://youragency.com/thanks"}'
# Response
{ "success": true, "duration": "48h",
"access_url": "https://app.upload-post.com/connect?token=..." } Three ways to get access to a client’s accounts
Only one of them scales past a handful of clients and networks.
| Route | How it holds up | Work per client |
|---|---|---|
| Ask for the password | Breaks on two-factor login, is against most networks’ terms, and you cannot revoke one tool without changing it everywhere | Low, until it breaks |
| Get added as an admin or partner in each network | Fine for one network (Meta Business partner access, LinkedIn Page admin, YouTube channel permissions), but every client repeats it for every network | One setup per client per network |
| Send a connection link (Upload-Post) | One link covers every network; the client logs in on each network’s own consent screen and can revoke access at any time | One API call per client |
Onboard a client in four steps
Two API calls on your side; a few clicks on theirs.
- 1
Create one profile per client
POST /users with a username that maps to the client in your own system, such as your client ID. Each profile holds one account per network.
- 2
Generate a branded connection link
POST /users/generate-jwt with that username, your logo, a title, the networks to show and where to send the client afterwards, or click Share next to the profile in the dashboard. You get an access_url, valid for 48 hours.
- 3
Send the link
The client opens it, clicks each network and approves that network’s own consent screen. They never create an Upload-Post account and never share a password with you.
- 4
Post for them
Pass the profile username as user on any upload, schedule or analytics call. The same profile is also available in the dashboard and to AI assistants such as Claude and ChatGPT.
curl -X POST https://api.upload-post.com/api/upload \
-H "Authorization: Apikey $UPLOAD_POST_API_KEY" \
-F "user=bakery-co" \
-F "platform[]=instagram" -F "platform[]=tiktok" \
-F "title=New autumn menu" \
-F "video=@menu.mp4" A hosted link or your own connect page
Both store the client’s accounts in the same profile; they differ in who builds the page.
| Hosted link (generate-jwt) | Your own page (Connect API) | |
|---|---|---|
| What you build | Nothing: one API call returns the link | Your page and buttons; the API returns each network’s authorize URL |
| Branding | Your logo, title, description, button text, language | Entirely yours, on your domain |
| What the client sees | A connect page at app.upload-post.com with your branding | Your app, plus each network’s consent screen |
| Best for | Agencies and freelancers onboarding clients | SaaS products where users connect inside the app |
Building your own page
Your backend gets a profile JWT from generate-jwt. Your page sends it to POST /oauth/{platform}/start, which returns the network’s authorize URL; you redirect the user there. Upload-Post completes the OAuth exchange and sends the user back to your redirect_url with the outcome.
Key your UI on connect_status (success, cancelled or error) and error_code. Each start is single-use and valid for 15 minutes, so request a fresh one per attempt.
// Your connect page, with the profile JWT from generate-jwt
const resp = await fetch('https://api.upload-post.com/api/uploadposts/oauth/instagram/start', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${profileJwt}`,
},
body: JSON.stringify({ redirect_url: 'https://yourapp.com/social/connected' }),
});
const { authorize_url } = await resp.json();
window.location.href = authorize_url;
// Back on redirect_url:
// ?connect_status=success&platform=instagram
// ?connect_status=cancelled&platform=instagram&error_code=ACCESS_DENIED What you can brand on the link
All optional fields of generate-jwt. A field you leave out is cleared on that profile, except the theme, calendar and UI label settings.
| Field | What it changes |
|---|---|
logo_image | Your logo on the connect page |
connect_title, connect_description | Your own heading and text |
platforms | Only the networks you want the client to connect |
redirect_url, redirect_button_text | Where the client goes when done, and the button label |
language | en, es, de, fr, pt, pl or tr; otherwise the browser language |
show_calendar, readonly_calendar | Show the client their scheduled posts, or a calendar they can see but not edit |
connect_theme | Force light or dark |
ui_labels | Replace any other text on the page |
Full reference: white-label integration guide and Connect API.
Let clients see what is scheduled
The same link can show the client a calendar of their posts. With readonly_calendar they see each post’s network, date, preview and caption, but cannot edit, reschedule or delete anything, or touch their connections. Agencies use it to share the plan for approval.
Working from an AI assistant? Ask Claude or ChatGPT with the Upload-Post connector to “create a profile for Bakery Co and give me a connection link with our logo”, or run /upload-post:whitelabel-connect in Claude Code.
When a client cannot connect
The cases that come up first, and what to do about each.
The link stopped working
Links are valid for 48 hours. Generate a new one with the same username; the client’s connected accounts stay where they are.
generate-jwt returns 404
The profile does not exist yet. Create it first with POST /users, or list profiles with GET /users to check the username.
The client came back with connect_status=cancelled
They closed or declined the network’s consent screen (error_code ACCESS_DENIED). Show a retry button.
INVALID_STATE on your own connect page
Each start is single-use and valid for 15 minutes. Request a fresh authorize URL for every attempt.
Instagram does not appear for the client
The Instagram API needs a Business or Creator account. The client switches in Instagram’s settings (free and reversible) and connects again.
Posts fail after a few weeks
The client changed a password or removed the access. Send a new connection link and retry the failed posts once the account is reconnected.
Connecting client accounts: frequently asked questions
How can clients connect their social media accounts without giving me their passwords?
Send them a connection link. With Upload-Post you create a profile per client and call generate-jwt, which returns a branded link. The client logs in on each network’s own OAuth screen, the tokens are stored in that profile, and you post by naming the profile. No password changes hands.
Is a connection link safe for my clients?
Yes. It uses each network’s official OAuth flow, so the client approves access on Instagram, TikTok or LinkedIn itself and can revoke it there or in the connect page at any time. The link expires after 48 hours and only opens that client’s profile.
Can I put my own branding on it?
Yes. Pass your logo, title, description, button text and language when you generate the link. For full control, build the page yourself with the Connect API and keep the client on your own domain.
Can I build the connection into my own app?
Yes. Your page calls POST /oauth/{platform}/start with the profile JWT, redirects the user to the authorize URL it returns, and gets them back on your redirect_url with connect_status set to success, cancelled or error.
Which networks can clients connect?
TikTok, Instagram, Facebook, LinkedIn, YouTube, X, Threads, Pinterest, Google Business Profile and Snapchat connect with OAuth. Discord, Telegram, Mastodon and WordPress connect with a webhook or token instead.
Do my clients need an Upload-Post account?
No. The link opens the connect page for their profile directly. They only log in to their own social networks.
Can clients see or approve what I schedule?
Yes. Generate the link with show_calendar to let them see their scheduled posts, or readonly_calendar for a calendar they can view but not edit, which suits approvals.
Can I create the link from Claude or ChatGPT?
Yes. With the Upload-Post connector, ask “create a profile for Bakery Co and give me a connection link with our logo”. In Claude Code, the plugin’s /upload-post:whitelabel-connect command does the same.
Send your first client a connection link
Free plan, no card. Create a profile, generate the link and post for the client from the API, the dashboard or an AI assistant.