← Blog

·

Permanent WhatsApp Business API access token with a system user

Updated on October 25, 2026

A permanent WhatsApp Business API access token is a system user access token, created in your Meta business portfolio settings with the whatsapp_business_messaging, whatsapp_business_management and business_management permissions. When you generate it, you choose whether it never expires or lasts 60 days and must be refreshed. This is the token that belongs in production, instead of the temporary token from the app dashboard, which expires within hours.

This guide covers the steps in the dashboard, the assets the system user needs, how to generate, refresh and revoke the token through the API, and the security practices that go with it.

The three WhatsApp API token types

Meta’s access tokens documentation lists three types:

TypeWho it is forLifetime
User access tokenDevelopment and testing; the one shown in the app’s “API Setup” panelExpires quickly and must be regenerated every few hours
System user access tokenA business accessing its own data, direct integrationLong-lived; never expires or 60 days, depending on what you choose
Business Integration System User access tokenTech Providers and partners onboarding customers through Embedded SignupObtained by exchanging the Embedded Signup code

If you integrate your own business directly with the Cloud API, you need the second one. When your system starts returning error 190 (token expired) or 0 (could not authenticate) a few hours after going live, the temporary token almost always ended up in production. These codes are covered in WhatsApp API errors.

Before you start

You will need:

  • admin access to the business portfolio (formerly Business Manager);
  • an app in the Meta developer dashboard with the WhatsApp product added;
  • the WhatsApp Business Account (WABA) and phone number already set up in the portfolio.

If you are not there yet, how to get access to the WhatsApp API covers the portfolio, app, WABA and number.

Step by step: create the system user and generate the token

These steps follow Meta’s official documentation. Menu names may vary slightly by language and Meta Business Suite version.

  1. Open your portfolio’s Business settings and click System users.
  2. Click + Add, enter a name (e.g. whatsapp-integration-prod) and choose the Employee or Admin role.
  3. Click the new system user’s name, then Assign assets.
  4. Select your app, grant the Manage app permission and confirm.
  5. Reload the page until the app shows Full control. Meta notes the assignment can take a few minutes.
  6. Still on the system user, click Generate token, select the app and choose the expiration preference.
  7. Select the three permissions: business_management, whatsapp_business_management and whatsapp_business_messaging.
  8. Click Generate token and copy the value. It is shown only once.

Don’t forget access to the WhatsApp account

Generating the token with the right permissions is not enough. The system user also needs Partial or Full access to the WhatsApp assets it will query. According to the documentation, many endpoints require that access on both the WhatsApp account and the linked Messaging account, and without it the API returns error code 200.

In Meta Business Suite, go to Settings → Accounts, open the WhatsApp account, select the People tab, click + Add people, pick the system user and set the access level. Repeat for the Messaging account. Meta points out that in Business Suite an assignment does not carry over to the other account, so assign both explicitly.

Employee or admin?

An admin system user has full access to every account in the portfolio by default. An employee system user only reaches what was assigned to it. For an integration, the safer choice is employee, with access only to the app and the WhatsApp accounts it needs. Meta’s system users overview recommends one system user per access type and careful protection of the admin token, because a leaked token with a narrow scope does less damage.

Expiry: “never” or 60 days

When generating the token, Meta offers two options, described in Install Apps, Generate, Refresh, and Revoke Tokens:

OptionValidityRefreshWhen to use
Non-expiringNever expires based on timeNot neededWhen you accept the leak risk in exchange for no refresh routine
Expires in 60 days60 days from generation or last refreshRequired within the windowWhen you want to limit the impact of a leaked token. This is the option Meta marks as recommended

The “permanent token” name comes from the first option. It can still stop working for other reasons: the system user loses access to the app, permissions are removed, or someone revokes the token. Treat an authentication failure as something to monitor, not something impossible.

With the 60-day option, if the token is not refreshed in time, it is forfeited and you need to generate a new one. Put the refresh in a scheduled job, not in a calendar reminder.

Generate, refresh and revoke via the API

Everything the dashboard does can also be done with Graph API calls, which helps when you automate rotation.

Generate

The system user must have the app installed (POST /SYSTEM_USER_ID/applications). Then generate the token with the access_tokens endpoint, adding set_token_expires_in_60_days=true for a 60-day token:

curl -X POST "https://graph.facebook.com/vXX.X/SYSTEM_USER_ID/access_tokens" \
  -d "business_app=APP_ID" \
  -d "scope=business_management,whatsapp_business_management,whatsapp_business_messaging" \
  -d "set_token_expires_in_60_days=true" \
  -d "appsecret_proof=APPSECRET_PROOF" \
  -d "access_token=CURRENT_TOKEN"

appsecret_proof is the HMAC-SHA256 of the token, keyed with the app secret. It proves the call comes from your server:

import crypto from 'node:crypto';

const appsecretProof = crypto
  .createHmac('sha256', process.env.META_APP_SECRET)
  .update(process.env.META_ACCESS_TOKEN)
  .digest('hex');

Refresh

Refreshing uses the oauth/access_token endpoint with grant_type=fb_exchange_token. The response contains the new access_token and expires_in in seconds:

curl -G "https://graph.facebook.com/vXX.X/oauth/access_token" \
  -d "grant_type=fb_exchange_token" \
  -d "client_id=APP_ID" \
  -d "client_secret=APP_SECRET" \
  -d "set_token_expires_in_60_days=true" \
  -d "fb_exchange_token=CURRENT_TOKEN"

Revoke

curl -G "https://graph.facebook.com/vXX.X/oauth/revoke" \
  -d "client_id=APP_ID" \
  -d "client_secret=APP_SECRET" \
  -d "revoke_token=OLD_TOKEN" \
  -d "access_token=NEW_TOKEN"

A successful response is {"success":"true"}. The client_id app must match the app of both tokens.

Zero-downtime rotation

Meta describes rotation without downtime in three steps:

  1. Refresh: generate the new token. The old one keeps working until it expires.
  2. Deploy: update the token in your secrets manager and redeploy or reload the configuration.
  3. Revoke: only after confirming everything uses the new token, revoke the old one. Revocation takes effect immediately.

A weekly job that checks the token’s age and refreshes it after, say, 45 days leaves room for failed deploys.

Security practices

  • Store it in a secrets manager or environment variable. Never in a repository, spreadsheet or chat message.
  • Do not parse the token. Meta asks you to treat it as an opaque value and store it in a variable-length field with no fixed maximum size.
  • Send it in the Authorization: Bearer header, never in the URL, where it ends up in logs.
  • Minimum scope. One employee system user per integration, with access only to the accounts it needs.
  • Protect the app secret. With it and a token, tokens can be refreshed and revoked.
  • Inspect the token in Meta’s access token debugger, which shows permissions and expiry.

WhatsApp Business account security covers the PIN, portfolio access and scams.

How this works with Vectalk

With Vectalk, you don’t need to create a system user or manage Meta’s token. When you connect the number through Embedded Signup, Vectalk imports the phone_number_id, waba_id and access token, according to the quickstart. Your application uses a Vectalk token instead:

  • Organization token: reaches every instance and requires phone_number_id when sending.
  • Instance token: limited to one number, required for media and templates.

Per the tokens documentation, Vectalk tokens do not expire automatically, remain valid until revoked, are shown only once and are stored as a hash. You can also create and revoke them through the API, with POST /api/auth/api-tokens and DELETE /api/auth/api-tokens/{id}, described under Authentication. The same rotation routine applies: create the new one, deploy, revoke the old one.

To get started, create your account at apps.vectalk.com.br/register. The natural next step is to send your first message.

Frequently asked questions

Can I use the temporary token from the app dashboard in production?

No. It is a user access token meant for testing and expires within hours. For production, use a system user token.

Does the permanent WhatsApp token really never expire?

If you pick the non-expiring option, it does not expire based on time. It can still be invalidated if the system user loses access to the app or its permissions, or if it is revoked.

Which permissions does the token need?

business_management, whatsapp_business_management and whatsapp_business_messaging. On top of that, the system user needs access to the WhatsApp account and the Messaging account.

Why do I get error 200 even with the right token?

Usually because the system user was not given Partial or Full access to the WhatsApp assets. Assign both the WhatsApp account and the Messaging account to the system user.

I lost the token. Can I see it again?

No. The token is shown only when it is generated. Generate a new one and revoke the previous one.


Official sources consulted on October 25, 2026: Access tokens (WhatsApp Business Platform), Install Apps, Generate, Refresh, and Revoke Tokens, System users overview, Cloud API error codes, Vectalk quickstart, Vectalk docs: tokens, Vectalk docs: authentication.

Integre o WhatsApp oficial ao seu sistema

A Vectalk entrega a Cloud API da Meta com os mesmos payloads e webhooks, um token para todas as contas e documentação completa.