Integrate an app
Identity Hub is an OAuth 2.0 authorization server. People sign in with a social platform or with an email and password, and your app receives their identity plus the accounts they chose to share. Platform tokens stay on the hub; your server asks for one only when it needs to publish.
1. Register the app
Sign in, open Apps and register the app with its homepage and exact redirect URIs. Copy the client secret when it is shown; it is stored only as a hash.
2a. Quick start: the sign-in widget
On the app's page, tick the sign-in methods you want (any configured platform and email and password), pick a theme, and copy the code. The preview shows exactly what your visitors will see. Method and theme changes reach live widgets within a minute without touching the code.
<div id="identity-hub"></div>
<script src="{HUB}/widget.js"
data-client-id="ihub_pk_..."
data-redirect-uri="https://your.app/callback"
data-scope="profile" async></script>Visitors see one Sign in button. Opening it lists each sign-in method you turned on, plus Sign up with email. Each of those opens the hub in a popup: passwords are only ever typed on Identity Hub, never on your site. When the person is done the popup closes and your page goes to your redirect URI with code and state, exactly as a full-page redirect would (which is what happens if popups are blocked). Before leaving, the widget stores a random state in the cookie ihub_state on your site. Your callback must check that the state query parameter equals that cookie, then continue with step 3. The widget's styles live in a shadow root and use a constructed stylesheet, so they neither leak into your page nor need style-src 'unsafe-inline' in your CSP; allow the hub origin in script-src and connect-src.
2b. Or send the person to the hub yourself
Redirect the browser to /authorize. Use a fresh random state and check it when they come back. Scope is profile, publish or both, space separated.
GET {HUB}/authorize
?client_id=ihub_pk_...
&redirect_uri=https://socialpostapi.makketing.com/auth/identityhub/callback
&scope=profile publish
&state=RANDOM
[&method=twitter|instagram|...|password]With method, the hub skips its own choice screen and goes straight to that platform or to the email form. They sign in (if needed), pick accounts and allow. The hub redirects to your redirect URI with code and state, or with error=access_denied.
3. Exchange the code on your server
Codes are single use and expire after ten minutes. Client credentials go in the body or HTTP Basic auth.
POST {HUB}/api/v1/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=code_...&redirect_uri=...
&client_id=ihub_pk_...&client_secret=ihub_sk_...{
"access_token": "ihub_at_...",
"token_type": "Bearer",
"user": { "id": "...", "display_name": "...", "avatar_url": "...",
"email": "person@example.com" },
"accounts": [
{ "id": "...", "platform": "twitter", "platform_account_id": "...",
"handle": "@studio", "display_name": "Studio", "avatar_url": "...",
"scopes": ["profile", "publish"] }
]
}The access token does not expire. Store it server side; it stops working when the person removes your app or you revoke it. Use user.id as the stable id for your own user record. email is null for people who only sign in with a platform, and when present it has been confirmed by its owner. accounts can be empty: a person may sign in without sharing any platform account.
4. Read the current grant
GET {HUB}/api/v1/me
Authorization: Bearer ihub_at_...Same user and accounts shape as the token response. Accounts the person disconnected or un-shared are gone.
5. Get a platform token to publish
For an account granted with publish, the hub returns a current platform access token, refreshing it first when it is about to expire. Call it right before each platform request instead of storing the result.
POST {HUB}/api/v1/accounts/{account id}/token
Authorization: Bearer ihub_at_...
{ "access_token": "...", "expires_at": "2026-10-12T14:00:00.000Z",
"platform": "facebook", "platform_account_id": "1234" }403 insufficient_scope means publish was not granted. 409 reconnect_required means the platform refused a refresh; ask the person to reconnect the account in Identity Hub.
6. Revoke
POST {HUB}/api/v1/oauth/revoke
token=ihub_at_...&client_id=ihub_pk_...&client_secret=ihub_sk_...Errors
Errors are JSON: { "error": "invalid_client", "error_description": "..." }. Codes: invalid_client (401), invalid_grant (400), unsupported_grant_type (400), invalid_token (401), insufficient_scope (403), not_found (404), reconnect_required (409).
Platforms
X, Instagram, Facebook (one account per Page), TikTok, LinkedIn, YouTube and Reddit support profile and publish. Snapchat is sign-in only: Snap offers no API for posting, so its accounts only ever carry profile.
How email and password accounts are protected
- Passwords: at least 15 characters, no composition rules, checked against known breaches (k-anonymity, only a 5-character hash prefix leaves the hub), stored with Argon2id.
- An account is only created when its owner clicks the emailed link; sign-up, sign-in and reset never reveal whether an address is registered.
- Repeated failures are limited per address and per IP; optional authenticator-app two-factor with single-use recovery codes.
- Changing or resetting a password signs out every other session and emails the owner.
- Sessions use a __Host- cookie (HttpOnly, Secure, SameSite=Lax) with idle and absolute timeouts; every page sends a nonce-based Content-Security-Policy and refuses framing.