Guide · For developers
How to generate a permanent WhatsApp Cloud API access token (system user)
Step by step: replace the temporary API Setup token with a system user token that does not expire, copy the phone number ID and WABA ID, test it with curl and fix common token errors.
By Broadchat teamPublished Updated 12 min read
In short
A permanent WhatsApp access token is a system user token generated in Meta Business settings with the expiry set to never. Create a system user, assign it your Meta app and your WhatsApp Business account with full control, generate a token with whatsapp_business_messaging, whatsapp_business_management and business_management, then test it with one template send. Keep it on your server only, and revoke it at once if it leaks.
Key takeaways
- The token on the App Dashboard API Setup page is a user access token that expires within hours; use it only for the first test message.
- A system user token can be set to never expire, or to expire after 60 days, which Meta recommends as the safer default.
- The system user needs two assets: your Meta app (Manage app) and your WhatsApp Business account with full control, or calls fail with error 200.
- Copy the phone number ID and the WhatsApp Business account ID at the same time; the send endpoint uses the phone number ID, not the phone number.
- Error 190 means the token expired or was invalidated; errors 10 and 200 mean a missing permission or missing asset access, not a bad token.
Generate a permanent WhatsApp Cloud API access token
Time needed: 20 min. You will need: A Facebook login with full control of your Meta business portfolio, A Meta app with the WhatsApp use case, A terminal with curl.
Check the prerequisites
Confirm you have full control of the business portfolio, a Meta app created with the WhatsApp use case, and a WhatsApp Business account connected to that app with at least one registered phone number.
Create a system user
Open Business settings, choose System users and click Add. Give it a name such as whatsapp-server and pick the Admin or Employee role. Employee is enough when the app needs only your own accounts.
Assign the app and the WhatsApp account
Select the system user and click Assign assets. Give it Manage app on your Meta app, and Manage WhatsApp Business accounts under Full control on your WhatsApp account. Reload the page until both appear as assigned.
Generate the token
Click Generate token, choose your app, choose the expiry (never, or 60 days), tick business_management, whatsapp_business_management and whatsapp_business_messaging, and click Generate token. Copy it immediately.
Copy the phone number ID and WABA ID
Take both IDs from the App Dashboard API Setup panel, or list your numbers with a GET call on the WhatsApp Business account. Store them next to the token in your server configuration.
Test the token with curl
Send one approved template to your own WhatsApp number through the messages endpoint. A response with a wamid message ID proves the token, permissions and IDs are all correct.
Store, rotate and revoke safely
Put the token in a server-side secret store, never in a browser, app or spreadsheet. Plan how you will replace it, and revoke it through Meta's revoke endpoint if it is ever exposed.
A permanent WhatsApp access token is a token generated for a system user in your Meta business portfolio with its expiry set to never. It is what a production server uses to call the WhatsApp Cloud API day after day without anyone logging in. This guide walks through the exact clicks in Business settings, the IDs you need alongside the token, a curl test, and the errors you will see when something is missing. If you only want the concept, read the glossary entry on WhatsApp API access tokens and system users first.
Temporary vs permanent token
Meta gives you three kinds of token. Only one of them belongs on a production server you run for your own business:
| Token | Where it comes from | How long it lasts | Use it for |
|---|---|---|---|
| User access token | App Dashboard → WhatsApp → API Setup (a new one each time you open the page) | A few hours | Your first test message only |
| System user token | Business settings → System users → Generate token | Never expires, or 60 days | Your own business's server and integrations |
| Business integration system user token | Exchanged from the code returned when a customer finishes Embedded Signup | Scoped to that one customer | Tech Providers and partners acting for their clients |
The API Setup token is tied to your personal Facebook login. Meta's own guide says user tokens "expire quickly, so you have to keep generating a new one every few hours". A system user is a non-human account owned by the portfolio, so its token keeps working when staff change.
Before you start
Check four things, because each one causes a different error later:
- Your Facebook login has full control (admin) of the business portfolio.
- You have a Meta app created with the Connect with customers through WhatsApp use case, owned by the same portfolio.
- The app is connected to your WhatsApp Business account in the API Setup panel.
- At least one phone number is registered on the Cloud API, and you have one approved template to test with.
If you have not connected a number yet, the WhatsApp Business API setup guide covers the portfolio, number and display name decisions first.
Step 1: create the system user
- Open Meta Business Suite, pick your business portfolio and open Settings (Business settings).
- In the sidebar, under Users, click System users.
- Click Add. In Create system user, enter a name you will recognise later, for example
whatsapp-server-prod. - Choose the role: Admin or Employee.
Which role? An admin system user automatically gets full access to every WhatsApp account and Messaging account the portfolio owns or has been shared. An employee system user sees only the accounts you assign to it. For one business with one or two numbers, an employee system user is the tighter choice: if the token leaks, it reaches only what you assigned.
Step 2: assign the app and the WhatsApp account
A token is only as useful as the assets its system user can reach. Select the system user and click Assign assets, then:
- Apps: select your Meta app and turn on Manage app (full control).
- WhatsApp accounts: select your WhatsApp Business account and turn on Manage WhatsApp Business accounts under Full control.
- Click Assign assets to confirm.
Reload the System users page and check that both assets now show as assigned; Meta notes that granting can take a few minutes. Meta is splitting the old WhatsApp Business account into a WhatsApp account and a Messaging account. Its access token guide says an employee system user needs access to both, and that in Meta Business Suite you must assign each one explicitly (under Accounts → WhatsApp accounts and Accounts → Messaging accounts, People tab). If your portfolio already shows a Messaging account, assign it too.
Step 3: generate the token
- With the system user selected, click Generate token.
- Choose your app.
- Choose the token expiry: never, or 60 days.
- Tick the three permissions below. Typing
businessin the search box finds them quickly. - Click Generate token and copy the value straight into your secret store.
| Permission | What it allows |
|---|---|
whatsapp_business_messaging | Sending messages and reading message-related data |
whatsapp_business_management | Templates, phone numbers and WhatsApp account settings |
business_management | Working with the business portfolio itself; Meta's guide lists it as one of the three to assign |
Treat the token as an opaque string. Meta warns that tokens vary in length and their format can change, so store it in a text field with no fixed maximum length and never try to parse it. You can paste it into Meta's Access Token Debugger to confirm its expiry and permissions.
Step 4: copy the phone number ID and WABA ID
Most "access token" searches are really about the set of values an integration needs. Collect them in one place now:
| Value | Looks like | Where to get it | Used in |
|---|---|---|---|
| Access token | EAAJB… | Step 3 | The Authorization: Bearer header |
| Phone number ID | A long number | App Dashboard → WhatsApp → API Setup | The send URL: /{phone-number-id}/messages |
| WhatsApp Business account ID (WABA ID) | A long number | API Setup panel (newer screens call it the Messaging account ID) | Template and phone number calls: /{waba-id}/message_templates |
| Graph API version | v26.0 | Meta's docs | Every URL |
You can also confirm the phone number ID from the API with the token you just made:
curl "https://graph.facebook.com/v26.0/$WABA_ID/phone_numbers" \
-H "Authorization: Bearer $WA_TOKEN"Each number in the response has an id (the phone number ID), its display_phone_number and its verified_name. The phone number ID is not the phone number: a URL such as /919876543210/messages fails because no phone number has that ID.
Step 5: test the token with curl
Send one approved template to your own WhatsApp number. Templates work whether or not you have messaged that number recently. If your account still has Meta's sample hello_world template in en_US, use it; otherwise use one of your own approved templates with its exact name and language code.
export WA_TOKEN="paste-the-system-user-token"
export PHONE_NUMBER_ID="123456789012345"
curl -X POST "https://graph.facebook.com/v26.0/$PHONE_NUMBER_ID/messages" \
-H "Authorization: Bearer $WA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messaging_product": "whatsapp",
"to": "919876543210",
"type": "template",
"template": { "name": "hello_world", "language": { "code": "en_US" } }
}'A working token returns a messages array with an ID starting wamid., and the message arrives on your phone. Run this from your terminal, not from a browser page: anything that runs in the browser exposes the token to every visitor. The template API tutorial shows the same call with variables and buttons, in Node.js and Python.
Step 6: store, rotate and revoke the token
Anyone holding the token can send messages as your business and create templates in your account. Store it like a database password:
- Keep it in environment variables or a secret manager on the server. Never put it in website JavaScript, a mobile app, a Google Sheet, a Postman collection you share, or a support chat.
- Use a separate system user per system (production server, staging, analytics script), so you can revoke one without stopping the others.
- Log who generated each token and when. A token you cannot trace is one you cannot safely revoke.
Rotating a 60-day token. Meta documents a refresh call on the oauth/access_token endpoint (with fb_exchange_token) that issues a new token valid for another 60 days. The old token keeps working until it expires, so deploy the new one first, then revoke the old one.
Revoking a token. Meta's oauth/revoke endpoint invalidates a system user token immediately, and it cannot be used again. Revoke at once if a token was pasted somewhere public, then generate a replacement, update every system that used it, and check recent message activity and billing for sends you did not make.
Common errors and fixes
Most token problems are one of five codes. Read error.code in the JSON response, not just the HTTP status:
| Code | Meaning | Usual cause | Fix |
|---|---|---|---|
| 190 (OAuthException) | Your access token has expired | The API Setup user token expired, a 60-day token lapsed, or the token was revoked | Generate a system user token (step 3) and deploy it |
| 0 | Unable to authenticate the app user | The token expired or was invalidated, or the user changed a setting that blocks apps | Switch to a system user token |
| 10 or 200-299 | Permission not granted or removed | A permission was not ticked when the token was generated | Check scopes in the Access Token Debugger; generate a new token with all three permissions |
| 200 | Request rejected: no access to the resource | The system user has no access to that WhatsApp account or Messaging account | Assign the account in step 2, then retry; no new token is needed |
| 100 | Invalid parameter | Phone number used instead of the phone number ID, a misspelt field, or an unsupported parameter | Use the ID from step 4 and compare your JSON with Meta's reference |
| 133010 | Phone number not registered | The number was added but never registered on the Cloud API | Register the number, then send again |
For delivery errors that appear after a successful send, such as 131047 (outside the 24-hour window) or 131026 (undeliverable), see our WhatsApp API error codes cheat-sheet.
If your number is on Broadchat
When you connect a number to Broadchat through Embedded Signup, the platform holds the Meta token for you and you never paste one. Developers who want to call the API from their own code use a Broadchat channel token instead:
- Open Channels → All Channels.
- On the channel card, open the ⋮ menu and choose Access Token.
- The API Details window shows the API URL, API Version, WABA ID, Phone Number ID and Business ID, each with a copy button.
- Click Generate new token and confirm. The token starts with
bc_and is shown once, so copy it before closing the window.
This channel token works only against your panel's own Graph-compatible API at the API URL (your panel address plus /api/meta) and only for that channel's phone number ID and WABA ID; it is not a Meta token and does not work on graph.facebook.com. Template sends made with it are charged to the channel's messaging wallet. Tokens you generated earlier keep working until you choose Revoke Previously Generated Token in the same menu, which revokes all of them without disconnecting the number. Only account owners can see this window. For the bigger picture of how the platform fits together, read what the WhatsApp Business API is or see the WhatsApp Business API overview.
Sources
- Access tokens guide (WhatsApp Business Platform) — Meta for Developers, checked 30 October 2026
- WhatsApp Cloud API: get started (system user and permanent token steps) — Meta for Developers, checked 30 October 2026
- Install apps, generate, refresh and revoke system user tokens — Meta for Developers, checked 30 October 2026
- WhatsApp Cloud API error codes — Meta for Developers, checked 30 October 2026
- Access Token Debugger — Meta for Developers, checked 30 October 2026
Broadchat team · Product and partner success team
The people who build and support Broadchat, the white-label WhatsApp Business API platform. We write from what we see while onboarding partners and their clients on the official WhatsApp Cloud API, and we check every article against Meta's current documentation.
Last updated:
Frequently asked questions
Does a WhatsApp system user access token really never expire?
It does not expire on a timer if you choose the never-expiring option when you generate it. It still stops working if it is revoked, if the system user is deleted, or if the system user loses access to the app or the WhatsApp account. Meta recommends the 60-day expiring option as the safer default.
Why does my WhatsApp access token expire after a few hours?
You are using the user access token from the App Dashboard API Setup page. It is tied to your Facebook login and is meant only for the first test message. Generate a system user token in Business settings for anything that runs unattended.
Which permissions does a WhatsApp Cloud API token need?
Meta's access token guide lists three for a system user token: whatsapp_business_messaging to send messages, whatsapp_business_management to manage templates and phone numbers, and business_management for the business portfolio.
Where do I find the WhatsApp access token and business account ID together?
Generate the token in Business settings under System users, then open App Dashboard, WhatsApp, API Setup to copy the WhatsApp Business account ID (shown as the Messaging account ID on newer screens) and the phone number ID. You can also list the phone numbers with a GET call on the account ID.
Should an agency use its own system user for a client?
For a single client's own integration, create the system user inside the client's business portfolio so the client owns it and staff changes at the agency do not break sending. Agencies serving many clients through Embedded Signup use business integration system user tokens, one per client.
What should I do if the token was shared by mistake?
Revoke it immediately with Meta's revoke endpoint, generate a new token for the same system user, update every system that used the old one, and review recent message activity and billing for anything you did not send.