What is a long-lived access token?
A long-lived access token is a Meta User Access Token with a lifetime of about 60 days. Tokens issued by Facebook Login or the Graph API Explorer are short-lived — they expire within hours, typically an hour or two — and a server can trade one for a long-lived token by calling the oauth/access_token endpoint with grant_type=fb_exchange_token, the app's ID (client_id), the App Secret (client_secret) and the short-lived token (fb_exchange_token). The response returns a new token string with token_type bearer and expires_in in seconds.
The long-lived token carries the same permissions and the same user identity as the token it replaced; only the lifetime changes. Because it still belongs to a person, it stops working when that person changes their password, removes the app, loses their role on the business portfolio or WhatsApp Business Account, or simply lets 60 days pass. Once it has expired it cannot be exchanged again — the person signs in again and you start over from a fresh short-lived token.
It is easily confused with a System User Access Token. A system user belongs to the business portfolio rather than to a person, and its token can be generated to expire after 60 days or never, which is why Meta's WhatsApp documentation steers production integrations towards system users. Long-lived user tokens fit tools that act for a signed-in person — an internal dashboard, a partner onboarding flow — for weeks at a time.
Key takeaways
- A long-lived access token is a user token that lasts about 60 days instead of the hour or two of a short-lived one.
- You get it by calling
oauth/access_tokenwithgrant_type=fb_exchange_token, your app ID, app secret and the short-lived token. - The exchange needs your app secret, so it must run on your server — never in a browser or a mobile app.
- An expired token cannot be exchanged: the person must log in again, so plan renewal well before day 60.
- For unattended WhatsApp sending, a system user access token fits better because it is not tied to one person's login.
Why the difference matters
Why does a long-lived access token matter?
Token lifetime decides whether an integration fails quietly at 3 a.m. A short-lived token pasted into a config file breaks the same day; a long-lived one breaks after two months, usually at the worst moment, with Error 190 (Access Token Invalid) on every call. Knowing how long each token type lives, what ends it early and which one belongs in production lets you design renewal — or avoid needing it — instead of firefighting expired credentials during a campaign.
A long-lived access token: key facts and limits
- Lifetime
- About 60 days (expires_in ≈ 5,184,000 s)
- Input
- A short-lived user token (expires within hours)
- Endpoint
- GET /oauth/access_token, grant_type=fb_exchange_token
- Required parameters
- client_id, client_secret, fb_exchange_token
- Where to call it
- Server only — the request contains the app secret
- After expiry
- Cannot be exchanged; the person must log in again
- Ended early by
- Password change, app removal, revoked access
- Production alternative
- System user token: 60 days or never
How does a long-lived access token work?
- Step 1
Get a short-lived user token
From Facebook Login or Facebook Login for Business on your site, or from the Graph API Explorer while testing. It carries the permissions the person granted.
- Step 2
Exchange it on your server
GET
https://graph.facebook.com/v26.0/oauth/access_tokenwithgrant_type=fb_exchange_token,client_id,client_secretandfb_exchange_token. The app secret never leaves the server. - Step 3
Store the token with its expiry
Save the returned
access_tokenencrypted, withnow + expires_inas its expiry. It is a different string from the short-lived token, so replace the old one everywhere. - Step 4
Inspect it, then use it
Check scopes and expiry with the Access Token Debugger or the
debug_tokenendpoint, then send it asAuthorization: Beareron Graph calls. - Step 5
Renew before day 60
Ask the person to sign in again well before expiry and repeat the exchange. For server-to-server sending, move to a system user token instead of renewing a person's token.
A long-lived access token in code
curl -G "https://graph.facebook.com/v26.0/oauth/access_token" \--data-urlencode "grant_type=fb_exchange_token" \--data-urlencode "client_id={APP_ID}" \--data-urlencode "client_secret={APP_SECRET}" \--data-urlencode "fb_exchange_token={SHORT_LIVED_TOKEN}"# {"access_token":"{LONG_LIVED_TOKEN}","token_type":"bearer","expires_in":5183944}
expires_in is in seconds: 5,183,944 s is just under 60 days.
Common mix-ups
Common mistakes with a long-lived access token
Exchanging in the browser
The request contains your app secret. Running it in front-end JavaScript or a mobile app leaks the secret, letting anyone act as your app. Exchange on the server only.
Waiting until it expires
There is no grace period and no exchange for an expired token. Track
expires_atand ask the person to sign in again days before, or calls start failing with error 190.Using a person's token for production sending
If the developer who logged in leaves, changes their password or loses access to the WABA, sending stops. Use a System User Access Token assigned to the WhatsApp assets.
Assuming 60 days is guaranteed
Password changes, security checks, revoked permissions or app removal end a token early. Handle error 190 at any time, not only near the expiry date.
Example: An account-manager dashboard in Gurugram
A Gurugram marketing agency's internal dashboard lets account managers view client templates and quality ratings. When a manager signs in with Facebook Login, the server exchanges the short-lived token for a long-lived one and stores it, encrypted, with its expiry. A nightly job runs debug_token; seven days before expiry the manager sees a banner asking them to sign in again, so no one discovers an expired token mid-meeting. The agency's sending service, which runs unattended, uses system user tokens assigned to each client's WABA instead.
Rules of thumb
Best practices for a long-lived access token
- Store tokens encrypted with their expiry timestamp, never in source control.
- Run
debug_tokenon a schedule and alert when a token is within 7 days of expiry. - Request only the scopes you use; a narrower token is a smaller risk if it leaks.
- Keep separate tokens per environment so a test change never touches production.
- Schedule Token Rotation even for non-expiring system user tokens, so a leaked token has a limited useful life.