How to connect Tiktok account using API
The TikTok connection lives partly in your product and partly on TikTok's developer platform.
Connecting TikTok to your app, start to finish
Every screen your user taps, every request your server makes, and every token you need to keep safe — laid out as one continuous path from an empty integrations page to a working TikTok connection.
What you need before you open a single tab
The TikTok connection lives partly in your product and partly on TikTok's developer platform. Gather these first — most delays in this process come from missing one of them halfway through.
- A TikTok account you're comfortable registering as a developer (personal or business).
- A live HTTPS domain for your app — TikTok will not redirect to
localhostor plain HTTP in production. - A backend that can make server-to-server requests and store secrets — the token exchange must never happen in the browser.
- A clear answer to "what will this connection actually do?" — read a profile, list videos, or publish content. This decides which scopes you request.
- A privacy policy and terms of service URL, both publicly reachable — required for app review later.
Register on TikTok for Developers
Go to TikTok's developer portal and sign in with the account you decided on in step 0. Complete the developer profile — company name, category, and a contact email your team actually monitors, since app-review correspondence lands there.
Create an app and collect your keys
Inside the developer portal, create a new app. Give it the name your users will actually see on TikTok's authorization screen — this is customer-facing copy, not an internal codename. Once created, TikTok issues two values:
| Value | Lives where | Purpose |
|---|---|---|
| client_key | Frontend + backend | Identifies your app in the authorization URL |
| client_secret | Backend only | Proves your server's identity when exchanging a code for a token |
Add products and pick your scopes
In the app dashboard, add the products that match the feature you scoped out in step 0. Each product unlocks a set of permission scopes you'll later request from the user.
A profile-display feature needs only user.info.basic. A scheduling feature that actually posts on the user's behalf needs video.publish, which sits behind a stricter review — plan for that lead time.
Register your redirect URI
Set the URL on your server that TikTok will send users back to after they approve access — for example https://app.yourproduct.com/integrations/tiktok/callback. TikTok compares this value byte-for-byte against what your authorization request sends, including trailing slashes.
/callback and /callback/ are different strings to TikTok's servers, and a mismatch fails silently with a generic redirect error.Understand the full authorization handshake
Before writing any code, it helps to see the handshake as one loop. Six things happen, in this order, every time a user connects their TikTok account:
The detail worth remembering: the authorization code in stage 4 is not the access token. It's a one-time voucher, valid for a few minutes, that only your server can redeem — and only by presenting the client secret alongside it.
Send the user to TikTok
When someone clicks "Connect TikTok," redirect their browser to TikTok's authorization endpoint with your app's identifying details. Generate a fresh, random state value every time and save it against that user's session — you'll check it when they come back.
// 1. Create a random state and save it to the session const state = crypto.randomUUID(); session.tiktokState = state; // 2. Build the authorization URL const params = new URLSearchParams({ client_key: process.env.TIKTOK_CLIENT_KEY, scope: "user.info.basic,video.list", response_type: "code", redirect_uri: "https://app.yourproduct.com/integrations/tiktok/callback", state, }); const authUrl = `https://www.tiktok.com/v2/auth/authorize/?${params}`; // redirect the user's browser to authUrl
Catch the redirect and check the state
TikTok redirects back with ?code=...&state=... in the query string. Before doing anything else, compare the returned state against the one you saved in step 6.
app.get("/integrations/tiktok/callback", async (req, res) => { const { code, state } = req.query; if (state !== session.tiktokState) { // stop here — this request did not originate from your own flow return res.status(400).send("State mismatch"); } // safe to continue — move to the token exchange in step 8 });
Trade the code for real tokens
Still on your server, send the code to TikTok's token endpoint along with your client key and secret. This request must happen server-to-server — never from the user's browser.
const response = await fetch("https://open.tiktokapis.com/v2/oauth/token/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ client_key: process.env.TIKTOK_CLIENT_KEY, client_secret: process.env.TIKTOK_CLIENT_SECRET, code, grant_type: "authorization_code", redirect_uri: "https://app.yourproduct.com/integrations/tiktok/callback", }), }); const tokens = await response.json(); // tokens.access_token → short-lived, ~24 hours // tokens.refresh_token → long-lived, ~365 days // tokens.open_id → the TikTok user's stable ID
Store what you just received
Save access_token, refresh_token, and the expiry timestamps against the connected user's row, encrypted at rest. This is the moment the connection becomes real from your product's point of view.
Make your first authenticated call
With a stored access token, your server can now speak for the connected account. A basic profile check is a good first call to confirm everything is wired correctly.
const profile = await fetch("https://open.tiktokapis.com/v2/user/info/?fields=open_id,display_name,avatar_url", { headers: { Authorization: `Bearer ${accessToken}` }, });
A successful response returns the fields you asked for under data.user. Show a piece of it back to your user immediately — their name or avatar — so the connection feels confirmed rather than invisible.
Refresh tokens before they expire
Access tokens are short-lived on purpose. Run a background job that checks for tokens expiring soon and refreshes them proactively, rather than waiting for an API call to fail.
const refreshed = await fetch("https://open.tiktokapis.com/v2/oauth/token/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ client_key: process.env.TIKTOK_CLIENT_KEY, client_secret: process.env.TIKTOK_CLIENT_SECRET, grant_type: "refresh_token", refresh_token: storedRefreshToken, }), });
Plan for the responses you don't want
A production integration spends more time handling the edge cases below than the happy path above.
Test with sandbox users first
Add your own account and a few teammates as sandbox testers in the developer portal. Run the entire loop — connect, call the API, disconnect, reconnect — before asking anyone outside your team to try it.
- Connecting works on a fresh account with no prior authorization.
- Disconnecting on TikTok's side (revoking access) is detected and handled the next time you call the API.
- Denying the permission screen returns the user to a clear, non-broken state in your app.
- Refreshing a token works without the user noticing anything happened.
Submit your app for review
Scopes like video.publish stay restricted to your sandbox testers until TikTok reviews your app. Prepare a short screen recording of the real feature in use, a working privacy policy link, and a plain description of why each requested scope is needed.
Go live
Once approved, switch any sandbox-only configuration to production values, confirm your redirect URI points at your live domain, and remove test-only accounts from the sandbox tester list. From here, monitor connection health the same way you'd monitor any other critical dependency.
The short version
Sixteen steps compress into two habits: keep secrets server-side, and never trust a redirect without checking its state.
Do
- Validate
stateon every callback - Keep
client_secreton the server only - Request the smallest scope set the feature needs
- Refresh tokens proactively, on a schedule
- Show the user something real right after connecting
Don't
- Store tokens in local storage or client-readable cookies
- Skip sandbox testing before requesting review
- Retry a 429 on a fixed interval
- Assume a refresh token lasts forever
- Reuse one redirect URI across environments