P

PostHub

Waking up your workspace

All articles
Help Center26 September 2026 21 min read

How to Connect Your First Social Account to PostHub

A complete walkthrough of the Connect button: which platforms need an app key, which connect with a password, what every status badge means, and how to fix a connection that will not stick.

MTMuhammad TayyabProduct Support Lead

CONNECT

Everything you want to do with PostHub starts in one place: telling the app which accounts it is allowed to post to. Until that step is done the composer will show an empty platform picker, the queue has nothing to aim at, and the scheduler has nowhere to send anything. So this is the first thing to get right, and it is also the step where most people get stuck, because "connect your account" means three completely different things depending on which network you are connecting.

On LinkedIn you are redirected to LinkedIn and click Allow. On Bluesky you paste an app password you generated thirty seconds ago. On Telegram you paste a token that a chat bot gave you. None of that is obvious from the button, and the button is labelled the same thing for all three.

This guide covers the whole surface: where connections live, what each button actually does, what every status badge is telling you, a per-platform list of exactly where to get credentials, and the fixes for the failures we see most often in support.

Where connections live

Sign in and open Connected Accounts from the sidebar. The page is the single source of truth for every network PostHub can talk to. Nothing else in the app creates, edits or removes a connection — if something on another screen looks out of date, this page is the reference.

The header tells you three numbers at once, and they answer three different questions:

  • N of 15 channels connected counts the accounts your user has authorised — the rows that will actually receive posts.
  • N of 15 integrations configured on this server counts the app-level credentials the deployment has been given. A platform can be configured on the server while you personally have not connected an account yet, and vice versa.
  • The N active chip counts connections that are currently usable.

Below that sits a Re-check config button. Press it any time you have just added a key in your hosting panel and want the page to re-read the server environment without reloading the whole app.

Then comes the grid: one card per platform, each with the platform name, a one-line summary of what the integration can do, a status badge, and a primary action.

The four status badges

The badge is the fastest way to diagnose a problem, so it is worth learning the four values and the order in which they are decided.

Connected means a live row exists for your user on that platform. The account name and handle come from the platform's own "who am I" call that ran during the connect flow, not from anything you typed. This is the only badge that means posts can go out.

Keys missing means the integration exists in PostHub but the server does not have the environment variables it needs — typically TWITTER_CLIENT_ID and TWITTER_CLIENT_SECRET, or their equivalents for another platform. The card lists the exact variable names, so you do not have to guess which of the four possible names is missing. Until they are set, the Connect button is disabled and the card will offer an Add API keys action instead. This is a server-side problem: no amount of clicking in the browser will fix it, because the keys must never be sent to the browser at all.

Not available means this deployment cannot offer the platform for a structural reason rather than a missing secret — the integration is turned off, or the platform is one PostHub does not ship for your configuration. You will see this far less often than Keys missing.

Disconnected is the neutral state: the platform is fully configured, but you have not connected an account yet (or you disconnected one earlier). Pressing Connect starts the flow.

One nuance worth knowing: the health check that produces the Keys missing badge looks at environment variable names only. It does not know whether the values inside them are correct, and it does not know whether the platform's own app has been approved by that platform. A fully green badge can still fail at the moment you press Connect if the secret is wrong or the app is in a restricted mode. That is a different class of problem and we cover it in the troubleshooting section below.

The three ways PostHub connects

Every platform in the product uses one of three mechanisms, and knowing which one you are about to hit makes the whole flow predictable.

1. Redirect-based OAuth (the common case)

X, Instagram, Facebook, Threads, LinkedIn, YouTube, Google Business Profile, TikTok, Vimeo, Dribbble, Pinterest and Tumblr all work the same way. You press Connect, PostHub builds a signed state token and stores it in a short-lived cookie, then sends you to the platform's own authorisation page. You approve there. The platform sends your browser back to PostHub's callback URL with a short-lived code, PostHub exchanges that code for tokens on the server, reads your account identity, stores the tokens encrypted, and lands you back on Connected Accounts with a green success toast.

You never type a token. You never see a secret. The only thing you personally configure for this flow is the callback URL inside the platform's developer console, which is what tells the platform that sending the user back to PostHub is legitimate.

2. Username and password style credentials

Bluesky is the only platform that works like this. There is no app registration, no developer portal and no callback URL. You generate an app password inside your Bluesky settings and paste it into the PostHub modal together with your handle. PostHub uses it directly when publishing. It is revocable from Bluesky at any time, which makes it the least scary of the three mechanisms.

3. A bot token

Telegram connects by pasting the token that BotFather hands you when you create a bot, together with the chat or group id the bot should post into. Again, no developer portal, no callback URL. The practical requirement is that the bot has been added to the target chat and has seen at least one message there, otherwise Telegram refuses to let it write.

Mastodon sits between OAuth and credentials: you enter your instance URL, PostHub registers an application on that instance at that moment, and then runs the normal redirect flow against it. So the flow is a redirect, but there is no developer portal for you to visit and nothing for you to configure in advance.

Connect an OAuth platform, step by step

The generic flow is the same for every redirect platform. We will use X as the concrete example because it is the one with the most moving parts.

Step 1 — Create the app on the platform's side. Open the developer portal for the network you want (the full list is in the next section). Create a project and an application. The application is what issues the keys; the name you give it only matters for what the approval screen shows your own users.

Step 2 — Set the app permissions. For X, choose Read and write under app permissions, because PostHub only ever publishes — it does not need to read your direct messages. For Meta platforms, add the products you need (Facebook Login, the Instagram API, or the Threads API) and grant the publishing scopes each one lists.

Step 3 — Paste the callback URL. This is the step everybody misses. PostHub's callback is always the same shape:

https://posthub.shorix.io/api/platforms/twitter/callback

Replace twitter with the platform key for the network you are configuring — instagram, facebook, threads, linkedin, youtube, google_business, tiktok, vimeo, dribbble, pinterest or tumblr. If you are testing on a local build, swap the domain for your local origin; the path never changes. Every platform calls this field something slightly different — Callback URI, Redirect URL, Valid OAuth Redirect URIs, Default callback URL — and every platform will silently reject a redirect that does not match it exactly, including trailing slashes and http versus https.

Step 4 — Copy the client credentials into your hosting environment. Save the app and copy the Client ID and Client Secret (some portals call them API Key and API Secret, Tumblr calls them Consumer Key and Secret). Put them in your host's environment variable panel using the exact names the card on Connected Accounts shows, then restart the Node application so the new values are read.

Step 5 — Press Connect and approve. Back on Connected Accounts, the button is now enabled. Press it, approve the request on the platform, and you will return to PostHub with a success toast naming the platform.

Step 6 — Confirm with Re-check config. If the badge does not read Connected, press Re-check config. It re-reads the server environment and refreshes the health data without a full reload.

That is the whole loop. The reason it feels heavy the first time is that steps 1 to 4 happen on someone else's website and only step 5 and 6 happen in PostHub. After the first platform, steps 1 to 4 take about two minutes each.

Platforms that connect without an app

Three networks skip the developer portal entirely, which makes them the fastest way to get a real post out if you want to validate the workflow before investing time in API keys.

Bluesky

Open your Bluesky settings, go to App passwords, create a password (give it a name you will recognise, such as posthub) and copy it. In PostHub, press Connect on the Bluesky card and a credential modal asks for your handle and that password. Two constraints worth knowing before you try to publish: Bluesky images must be under about 976 KB — it is a small platform with small limits — and Bluesky does not support video at all through this path.

Telegram

Message BotFather, send newbot, follow the prompts, and copy the token. Then find the chat id of the group or channel you want to post into. In PostHub, open the Telegram credential modal, paste both, and save. Add the bot to that chat first and send any message in the chat so the bot has a valid target. Telegram posts can include one image or a short video up to 50 MB, and the text limit is generous at 4096 characters.

Mastodon

Enter your instance URL — mastodon.social, or your own domain if you self-host. PostHub registers an application on that instance during the connect flow, so nothing has to be configured in advance. Some instances restrict which third-party applications may register; if yours does, you will see a clear error from the instance rather than a PostHub one, and the fix is to ask your instance administrator to allow the application.

A per-platform checklist

Keep this section open while you work through your first few platforms. It is the short version of everything above, in one pass.

X (Twitter) — Portal at developer.x.com, project plus app, User authentication settings set to Web App, permissions Read and write, callback at the twitter path, and copy the OAuth 2.0 Client ID and Secret rather than the old consumer keys. Publishing on X is the one platform that costs money per post.

Instagram — Create a Meta app, add the Instagram API product, whitelist the callback at the instagram path, and make sure your Instagram account is Professional (Business or Creator) with a linked Facebook Page. Personal accounts cannot publish through the API at all.

Facebook — Same Meta app, add Facebook Login, whitelist the callback at the facebook path, and add your domain to App Domains. PostHub publishes to Pages; personal profile posting is not offered by Meta's API.

Threads — Add the Threads API product to the same Meta app and whitelist the callback at the threads path. During development only the test users you list can approve the connection.

LinkedIn — Create an app at linkedin.com/developers/apps, request the Sign In with LinkedIn and Share on LinkedIn products, then put the callback in the OAuth2.0 redirect URLs field. PostHub publishes to your personal profile with member-level permissions.

YouTube — In Google Cloud, enable the YouTube Data API v3, create a Web application OAuth client, and add the callback at the youtube path to Authorised redirect URIs. Add yourself as a test user on the consent screen until the app is verified.

Google Business Profile — A second OAuth client (or the same client with both callbacks listed) plus the Business Profile APIs. The scope PostHub requests is a restricted one, so expect Google to require app review before it works for anyone other than test users.

TikTok — Create an app at developers.tiktok.com, add the callback at the tiktok path, and verify your domain with the DNS record TikTok gives you. TikTok publishing is video only and requires the video publish permission, which is granted through app review; until then you can only publish as a listed test user.

Vimeo — New app at developer.vimeo.com, paste the callback at the vimeo path into the Redirect URL field, and make sure the token includes write scope. Free accounts are capped at 500 MB of uploads per week.

Dribbble — Create an application at dribbble.com/settings/applications and paste the callback at the dribbble path. Dribbble's upload permission is enabled per application on request, so plan for a short email if you are publishing shots rather than reading them.

Tumblr — Register an application at tumblr.com/oauth/apps, put the callback in Default callback URL, and verify your email address on the Tumblr account itself or the API will refuse you.

Pinterest — Create an app at developers.pinterest.com, paste the callback at the pinterest path, and note that write access to Pins requires a business account and approval.

Bluesky, Telegram, Mastodon — No callback, no keys, no portal. Use the credential modal as described above.

Disconnecting, reconnecting and token lifetimes

Every card on a connected account has a disconnect action, and it really removes the row — it does not merely hide it. After disconnecting, the platform drops out of the composer's picker immediately, because the picker only ever lists accounts that are connected.

Reconnecting is simply pressing Connect again. There is no separate "re-authorise" button, because the flow is identical: a fresh redirect, a fresh code exchange, a fresh set of tokens.

Tokens do expire, and the reason varies by platform. Meta's short-lived tokens are exchanged for long-lived ones during the callback and then refreshed automatically by PostHub's publishing path, but the underlying grant can still be revoked if you remove the app from your account's connected-apps list. Google issues a refresh token that PostHub uses to obtain new access tokens quietly, provided you authorised the app while it was not in a restricted testing mode — otherwise no refresh token is issued and the connection stops working within the hour. If a connection suddenly fails with an authorisation error, disconnect and connect again; that always mints a new grant and is the correct first response to a token problem.

Revoking access from the platform's side (Facebook's Apps and websites, Google's third-party access page, X's connected apps) has the same effect as disconnecting in PostHub, but PostHub will not know until the next publish attempt fails. If you have revoked access somewhere else, come back here and disconnect so the composer stops offering a dead account.

When Connect fails

These are the failures we see most, in the order they are likely to bite you.

You are bounced back with an error toast. The callback ran and the platform refused, or the state token did not match. Read the message in the toast — it carries the platform's own wording. A mismatch error usually means the callback URL registered on the platform does not match the one PostHub sent, which is almost always a typo, a missing trailing path segment, or http versus https. Compare the value in the developer console character by character with the URL printed on your Connected Accounts card.

The platform says redirect URI mismatch. Same cause, different wording. Also check that you saved the change in the developer console; several portals require a separate Save after pasting, and a few cache the value for a minute.

The button stays disabled and says Keys missing. The environment variables are absent. The card names them. Add them in your host's environment panel and restart the application — editing the variable is not enough on most hosts, because the running process only reads the environment at boot.

The keys are present but the platform rejects the token exchange. Either the secret is wrong (pasting the API key into the secret field is a classic), or the app is in a mode that forbids the flow — for example a Google app still in Testing with you not listed as a test user, or a TikTok app whose domain is not verified. The platform's error text in the toast will name the actual reason.

You get sent to a login page for an account you are not expecting. The browser has a session for a different account on that platform. Log out of the platform in another tab and run Connect again. OAuth follows the browser session; PostHub cannot choose the account for you.

The success toast appears but the badge is not Connected. Refresh the page. If it still is not connected, the callback reached PostHub but the identity lookup failed, which means the app is missing a profile or identity scope. Re-check the products you enabled on the platform's side, then disconnect and connect again.

You are using the site over a different domain than usual (a www variant, a preview URL, a bare domain). The callback is registered for posthub.shorix.io, so a connection started from any other origin will bounce back to a domain the platform does not know. Connect from the canonical domain.

Security notes worth knowing

Two properties of this design matter if you are evaluating where your credentials live.

First, the client secret never reaches the browser. The exchange happens on the server inside the callback route, so the secret exists only in the server environment and in memory during the exchange. Nothing in the front-end bundle can leak it.

Second, the state token that ties the redirect back to your session is encrypted, short-lived and bound to a cookie that is not readable from JavaScript. That is what stops an attacker from starting a connect flow on their own account and tricking you into finishing it on yours.

Stored account tokens are encrypted at rest. If you disconnect an account, the row — and with it the tokens — is deleted rather than marked inactive.

What PostHub asks for on your behalf

During the redirect the platform shows you a list of permissions. It is worth knowing what PostHub actually requests, because a permission you do not recognise is usually a good reason to pause, and a permission that is missing is the usual reason a publish later fails.

X requests tweet read, tweet write, users read, media write and offline access. The write and media permissions are what let PostHub publish a caption and upload an image; offline access is what allows the token to be refreshed instead of expiring in two hours.

Instagram requests instagram business basic and instagram business content publish. There is no read-your-messages permission in there and no permission to act as another user.

Facebook requests pages manage posts, pages read engagement and pages show list. PostHub needs the list to know which Pages you manage, read engagement to attach media correctly, and manage posts to actually publish.

Threads requests threads basic and threads content publish — the smallest set of any Meta product, which is also why Threads has the strictest daily caps.

LinkedIn requests openid, profile and member social. The openid and profile permissions exist so PostHub can read your own member id, because LinkedIn addresses posts to a member URN rather than to a username. The member social permission is the one that allows sharing on your behalf.

YouTube requests youtube upload and youtube readonly. Google Business Profile requests business manage, which is a restricted scope and the reason that integration tends to need an app review.

TikTok requests user info basic and video publish. Vimeo requests public, private, create, edit, upload and upload is the one that matters for publishing. Dribbble requests public and upload. Pinterest requests boards read, pins read and pins write. Tumblr and Mastodon request read and write.

If a platform shows you a permission list that includes anything about reading direct messages, posting as someone else, or managing your security settings, that is not PostHub — that would be a different application entirely, and you should cancel.

If a platform shows you fewer permissions than you expected, the app on that platform is misconfigured: someone edited the scope list, or the product you enabled does not grant the scope you need. The connection will succeed and publishing will fail later with an insufficient-permissions message, which is far more annoying to diagnose. Cancel, fix the products and scopes on the platform side, then connect again.

One account per platform: how switching works

PostHub keeps one connection row per platform per user in the common case, and the composer picks the account it finds for that platform when it builds the target list. In practice this means you should decide which account of each network is the PostHub account before you connect it.

If you already connected your personal X account and now need to connect the brand's account, disconnect first, then connect the new one. Connecting a second account without disconnecting the first leaves two rows for the same platform, and the composer will target the one it finds first — which is not something you want to discover when a client post goes out from the wrong handle.

This also matters if you are an agency. The cleanest arrangement is one PostHub user per brand, so that every connection, every scheduled post and every analytics row belongs to one place. Multi-brand workspaces inside a single user are not something this build offers, and pretending otherwise in the documentation would just set you up for a confusing afternoon.

The same rule applies to media and drafts: they belong to the user who created them, so if you hand a login to a colleague, they see everything that account can see. We will come back to that in the settings and team guide.

Moving your connections to a new server

If you migrate hosting, the connections move with your database, but the keys do not — they live in the environment of the machine, not in the database. So a migration is a two-part job:

Export and import the database so that socials_socialaccount rows, with their encrypted tokens, arrive intact. Then recreate every platform's environment variables on the new host and restart the Node application. Without the second step the health page will flip from configured to Keys missing, because the process cannot find the client secrets it needs to refresh a token.

Tokens that are already stored continue to work after a migration as long as the encryption key is also carried over. If you rotate the encryption key without migrating the tokens, every stored token becomes unreadable and every account has to be reconnected by hand. If you must rotate it, rotate it as a planned change with an hour set aside to reconnect.

The checklist for a migration is short: database, environment variables including the encryption key, restart, Re-check config, then open the composer and confirm the platform picker still lists your accounts. The last step is the one that catches a partially completed migration, because it exercises a real token rather than a stored row.

The diagnostic checklist for support

If a connection refuses to work and you decide to ask for help — ours, or a colleague's — the fastest possible answer comes from four pieces of information that you can gather in two minutes.

First, the platform and the exact badge it shows: Connected, Keys missing, Not available or Disconnected. That single word eliminates half the possibilities.

Second, the error text from the toast. PostHub passes the platform's own message through rather than replacing it with a generic apology, and those messages are specific — redirect URI mismatch, invalid client secret, scope not granted and so on all point at completely different fixes.

Third, the timestamp of the last Re-check config, so whoever helps you knows whether they are looking at the environment as it is now or as it was before your last change.

Fourth, whether the account connects but fails at publish time, or fails at connect time. Those are different problems: connect failures are about identity, state and redirect URIs; publish failures are about tokens, scopes, permissions and content rules.

A screenshot of the Connected Accounts header, showing both counters and the Re-check config button, carries all of the badge information in one image and is worth sending on its own.

Checking a connection is still healthy

Connections are not fire-and-forget. Tokens age, platforms revoke grants, and accounts change type — so a monthly check is worth building into the same routine as the two-minute queue review.

Open Connected Accounts and press Re-check config. The badges refresh against the live configuration. Anything that has drifted — a missing key, a variable lost during a migration — shows up here as a badge rather than as a failure during someone else's publish.

Look at the connected-apps list on each platform. This is the authoritative view of what has been granted and by whom, and it lives on the platform's side where you can see grants that PostHub did not create. Revoking something you do not recognise there is always safe.

Publish one small test post to the least-used platform. A badge says the configuration is present; only a real publish proves the token still works end to end. Once a month, one post, and then delete it on the platform if it serves no purpose.

Note the connection dates. If a platform starts failing every two months like clockwork, you have found its refresh behaviour, and a calendar reminder beats a morning of troubleshooting.

Reconnect anything you have not published to in a while. Stale grants are the single most common cause of a failure on an account that was working perfectly last week.

Five minutes a month, and the first sign of a problem is a badge you noticed rather than an error someone else received.

What to do next

Once two or three accounts show Connected, go back to the composer. The platform picker will now be populated with real accounts, and the first post you schedule will have somewhere to go. If you have not written a post yet, the scheduling guide walks through the composer, the calendar and the queue in order.

Before you leave this page, run the 60-second version of the checklist:

  • At least one OAuth platform connected end to end through the redirect flow.
  • Bluesky or Telegram connected through the credential modal, to prove the non-OAuth path works on your deployment.
  • Re-check config pressed, so the health numbers on the header reflect the environment as it is right now.
  • Every platform you intend to use showing a green Connected badge — not just configured, not just ready, but connected.

If a platform will not go green, do not move on and hope. The composer will happily let you select an account whose token has since been revoked, and the failure will surface later as a publish error with less context than the connect error would have had. Fix it here, where the message is specific.

#connect accounts#setup#oauth#getting started#help

Put this playbook on autopilot

PostHub queues, publishes and reports across every platform you use — so the strategy above actually happens without you babysitting a tab.

Keep reading