TikTok API Access Token: Get, Refresh, and Fix Errors
A TikTok API access token comes from an OAuth flow, and TikTok runs two separate ones. TikTok for Developers issues tokens from open.tiktokapis.com/v2/oauth/token/. TikTok API for Business issues them from business-api.tiktok.com's tt_user/oauth2/token/ endpoint. On both, the access token lasts 24 hours and the refresh token lasts one year. Adeli refreshes TikTok tokens for every connected account.
A TikTok API access token is the OAuth credential TikTok issues when a user authorizes your app, and TikTok has two separate systems for it. TikTok for Developers (Login Kit) issues tokens from open.tiktokapis.com. TikTok API for Business issues them from business-api.tiktok.com. On both, the access token lasts 24 hours and the refresh token lasts one year, so you refresh every day and send the user back through login once a year.
Below are both flows with the exact requests from TikTok's docs, a refresh schedule, and the errors that mean a token is dead. If you haven't picked a portal, read TikTok API for Business vs. TikTok for Developers first.
Which TikTok access token do you need?
The portal your app is registered in decides the token. A token from one portal doesn't work on the other, and the request formats differ in small ways that break copied code.
| TikTok for Developers | TikTok API for Business (Accounts API) | |
|---|---|---|
| Authorize URL | https://www.tiktok.com/v2/auth/authorize/ |
The "TikTok account holder authorization URL" in your app's Basic Information |
| Token endpoint | POST open.tiktokapis.com/v2/oauth/token/ |
POST business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/token/ |
| Refresh endpoint | Same endpoint, grant_type=refresh_token |
.../tt_user/oauth2/refresh_token/ |
| Body format | application/x-www-form-urlencoded |
application/json |
| App credentials | client_key, client_secret |
client_id, client_secret |
| Code parameter | code |
auth_code (valid 10 minutes, single use) |
| Access token | 24 hours | One day |
| Refresh token | 365 days from first issuance | One year |
| Revoke | /v2/oauth/revoke/ |
/tt_user/oauth2/revoke/ |
Sources: TikTok's user access token management, Login Kit for Web, and the Accounts API authorization and authentication guides.
Getting the app approved on either portal comes first. Our guide on how to get TikTok API access covers that.
How to get a TikTok access token (TikTok for Developers)
Send the user to TikTok's authorize page, catch the code, and POST it to /v2/oauth/token/.
- Redirect the user. Build the URL with
client_key,scope(comma-separated),redirect_uri,state, andresponse_type=code:
https://www.tiktok.com/v2/auth/authorize/?client_key=<CLIENT_KEY>&response_type=code&scope=user.info.basic,video.publish&redirect_uri=<REDIRECT_URI>&state=<STATE>- Read the callback. TikTok appends
code,scopes, andstateto your redirect URI. Check thatstatematches what you sent. A failure comes back aserrorwith an optionalerror_description. - Exchange the code from your server. URL-decode the code first:
curl --location --request POST 'https://open.tiktokapis.com/v2/oauth/token/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_key=<CLIENT_KEY>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>' \
--data-urlencode 'code=<CODE>' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri=<REDIRECT_URI>'The response holds open_id, scope, access_token, expires_in (86400), refresh_token, refresh_expires_in (31536000), and token_type (Bearer). Mobile and desktop apps also send a PKCE code_verifier.
Redirect URIs have strict rules. They must be absolute, start with https, have no query string or # fragment, stay under 512 characters, and you can register at most 10.
How to refresh a TikTok access token (TikTok for Developers)
POST the refresh token to the same endpoint with grant_type=refresh_token. TikTok says the access token "can be refreshed without user consent", so a scheduled job can do it.
curl --location --request POST 'https://open.tiktokapis.com/v2/oauth/token/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_key=<CLIENT_KEY>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=<REFRESH_TOKEN>'Save the refresh token from every response. TikTok's docs say the returned refresh_token "may be different than the one passed in the payload", and you must use the new one. A job that stores only the access token works until the day TikTok rotates the refresh token, and then every refresh for that account fails.
To check a token, call GET https://open.tiktokapis.com/v2/user/info/?fields=open_id with an Authorization: Bearer header. It needs the user.info.basic scope.
How to get a TikTok business API access token
On TikTok API for Business, the user authorizes through your app's TikTok account holder authorization URL, and you POST the auth_code as JSON. The Accounts API authorization guide lays it out:
- Share the authorization URL. Copy it from My Apps > App Detail > Basic Information. It only appears once your app has the "TikTok Accounts" permission scope. Add a
stateparameter for CSRF protection. - Upload an app logo first. Without one, users hit an error page during authorization.
- Exchange the code within 10 minutes. The
auth_codeis valid for 10 minutes and works once:
curl --location --request POST 'https://business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/token/' \
--header 'Content-Type: application/json' \
--data '{
"client_id": "<APP_ID>",
"client_secret": "<SECRET>",
"grant_type": "authorization_code",
"auth_code": "<AUTH_CODE>",
"redirect_uri": "<REDIRECT_URI>"
}'The data object returns access_token (expires_in 86400), refresh_token (refresh_token_expires_in 31536000), open_id, scope, and token_type. To see which scopes a token carries, POST app_id and access_token to /tt_user/token_info/get/.
Business redirect URLs are stricter still. They must end with /, use https://, and carry no query parameters, anchors, or ports. You can register up to 10, but TikTok keeps one active URL at a time. TikTok's suggested workaround is to JSON-encode what you'd have put in the query string into state.
How to refresh a TikTok business API access token
POST the refresh token to /tt_user/oauth2/refresh_token/ before the one-day token lapses.
curl --location --request POST 'https://business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/refresh_token/' \
--header 'Content-Type: application/json' \
--data '{
"client_id": "<APP_ID>",
"client_secret": "<SECRET>",
"grant_type": "refresh_token",
"refresh_token": "<REFRESH_TOKEN>"
}'The response returns a new access token and a refresh token. Don't assume the refresh resets the year. In TikTok's example renewal response, refresh_token_expires_in is lower than at first issuance, so store the value each response returns. When the refresh token expires, TikTok says the user has to authorize your app again.
Marketing API tokens are a different thing. If you authorize an ad account or Business Center, the long-term access token from /oauth2/access_token/ doesn't expire and has no refresh step. It doesn't work for the Accounts API.
How long do TikTok access tokens last?
| Token | Lifetime | How you renew it |
|---|---|---|
| User access token (TikTok for Developers) | 24 hours | Refresh token, no user consent |
| Refresh token (TikTok for Developers) | 365 days from first issuance | User authorizes again |
Client access token (client_credentials) |
2 hours | Request a new one |
| TikTok account access token (API for Business) | One day | /tt_user/oauth2/refresh_token/ |
| TikTok account refresh token (API for Business) | One year | User authorizes again |
| Marketing API long-term token | Doesn't expire | Revoke with /oauth2/revoke_token/ |
The client access token is for app-level calls such as the Research API and Commercial Content API, per TikTok's client token docs. It can't post or read a user's data.
A refresh schedule that works for both portals:
- On connect. Store the access token, the refresh token, and both expiry times.
- Every few hours. Refresh any access token that expires within the next few hours, and save both returned tokens.
- On a 401. Refresh once and retry. If the refresh fails, mark the account for reconnection.
- Near the one-year mark. Ask the user to reconnect before the refresh token expires.
Why is my TikTok access token not working?
Read the error code first. These come from TikTok's API error codes and OAuth error codes:
| Error | Meaning | Fix |
|---|---|---|
access_token_invalid (401) |
Token expired, invalid, or missing | Refresh it and retry |
scope_not_authorized (401) |
The user didn't grant a scope this call needs | Ask the user to authorize it again |
scope_permission_missed (400) |
Token is valid but some fields need more scopes | Request the scopes named in the message |
invalid_grant |
Code or refresh token is invalid, expired, revoked, or from another client | Send the user back through authorization |
invalid_client |
Client authentication failed | Check the key, secret, and which portal's credentials you're using |
rate_limit_exceeded (429) |
Too many requests | Back off and retry later |
A few more catches:
- Expired business
auth_code. Ten minutes is short. Exchange the code in the callback handler, not in a queued job. - Wrong portal. Developer credentials sent to the business endpoint, or
codeinstead ofauth_code, fail before any token is issued. open_idis app-scoped. When we moved Adeli's TikTok connection to TikTok API for Business, each account'sopen_idchanged when it reconnected. Key accounts on your own ID, not TikTok's.- Every error carries a
log_id. Send it with any support request to TikTok.
How does Adeli handle TikTok token refresh?
Adeli refreshes the TikTok token for every connected account, so your code never sees one. Your users connect TikTok through Adeli's connect flow, which runs through TikTok API for Business. Adeli exchanges the code server-side, stores the token, and keeps it fresh. You authenticate to Adeli with one API key.
To force a refresh for a profile, call:
curl -X POST "https://app.tryadeli.com/api/v1/profiles/<PROFILE_ID>/accounts/refresh" \
-H "Authorization: Bearer rk_live_..."The refresh tokens endpoint returns an account only after its new token and expiry are written. If a TikTok account can't be refreshed, it comes back in errors with connection_expired, and the account's connectionStatus reads reconnect_required until the user connects again. Reconnecting keeps the same accountId.
The TikTok API page shows what Adeli supports on TikTok, and the posting API publishes to TikTok from the same endpoint as Instagram, Facebook, YouTube, X, and Bluesky. If you're building the publish call itself, see how to post to TikTok via API.