WhatsApp API

Your WhatsApp API token expires in 24 hours. Here is the permanent one.

The token in the Meta app dashboard is temporary and dies overnight, which is why every first WhatsApp integration breaks the next morning. The fix is a System User token, and it needs exactly three permissions.

This is step four of setting up the WhatsApp Business API, and doing it before you write any code saves you building the same integration twice.

Every first WhatsApp integration follows the same arc. You copy the token from the dashboard, everything works, you go home pleased. The next morning nothing sends and the log says:

(#190) Your access token has expired.

Nothing broke. The token you used was never meant to survive the night.

Why does my WhatsApp access token keep expiring?

Because the token displayed in the WhatsApp panel of your Meta app dashboard is a temporary one. Meta's documentation is blunt about it: that token "expires quickly and is not suitable for development purposes".

It exists so you can fire a test message within a minute of finding the page, which is a good onboarding decision and a terrible production credential. Nothing in the interface stops you shipping it.

Does it expire in 24 hours? Roughly, and that is how most people describe it, but be careful with the number. Meta's Cloud API getting-started guide does not publish a duration at all. Its exact wording is that the token "expires quickly and is not suitable for development purposes". Treat 24 hours as an observation rather than a guarantee, and do not build anything that assumes you have a day. The practical rule is simpler: if a token came from the App Dashboard, it is not a production credential no matter how long it happens to last.

What is whatsapp_access_token?

If you arrived here searching that exact string, you are almost certainly looking at a configuration field, an environment variable, or a form in some tool asking you to paste a value. Different products name it differently, WHATSAPP_ACCESS_TOKEN, whatsapp_token, WA_TOKEN, "System User Token", but they all want the same thing: the credential your server sends to Meta in the Authorization: Bearer header on every Cloud API call.

The important part is which token belongs there:

Authorization: Bearer <this is whatsapp_access_token>

If you paste the token from the WhatsApp panel of the App Dashboard, everything works immediately and stops working by tomorrow, which is the entire subject of this post. What belongs in that field is a System User token, created in Business Settings.

Two things worth knowing before you fill it in:

  • It is not the same as your App Secret. The App Secret is a separate value used to verify webhook signatures. Products that ask for both are asking for two genuinely different credentials, and pasting one into the other's field produces authentication errors that look like a permissions problem.
  • It is not the Phone Number ID or the WABA ID. Those are identifiers, not credentials. They are safe in configuration; the token is not.

What is a System User token?

A System User token is the permanent token for WhatsApp: a credential that belongs to the business rather than to a person. That distinction is the whole point, and it is why the permanent token cannot be generated from the app dashboard where you found the temporary one.

A user token is tied to you. It dies when you change your password, lose a role, or leave the company. We have watched a lead pipeline stop on a Tuesday afternoon because a marketing contractor who had connected the account in March was offboarded in June, with no deploy and no error anywhere in the application.

A System User is not a person, has no password to change and cannot be offboarded. Its token does not expire.

How do I create a permanent WhatsApp access token?

Four steps, all in Business Settings rather than in the app dashboard, which is why people do not find it.

1. Create the System User. Business Settings → System users in the sidebar → Add, then follow the prompts.

2. Assign the assets. Select the new system user and click Assign Assets, then:

  • choose your app and enable Manage app under Full control
  • choose your WhatsApp account and toggle Manage WhatsApp Business accounts under Full control
  • click Assign assets

3. Generate the token. Click Generate token and follow the prompts.

4. Grant exactly these three permissions:

Permission Why
whatsapp_business_messaging send messages
whatsapp_business_management manage templates and phone numbers
business_management read the business the account belongs to

Watch out: "Full control" on both assets is not optional. Partial access produces a token that authenticates correctly and then fails on the one call you need, which reads as a permissions bug rather than an assignment problem. Assign both, at Full control, and check the system user actually appears against both assets afterwards.

Which token do I need for which job?

The three token types are not interchangeable, and this is where a lot of days are lost.

Token Good for Dies when
Temporary (app dashboard) one test message, nothing else within hours
User token exploring the API as yourself you change your password or lose a role
System User token production sending and template management never
Page token reading Meta lead ads the user it was derived from does

That last row is the trap that catches people building both halves of a lead pipeline. A System User token is right for WhatsApp and wrong for reading lead ads: leadgen reads require a Page access token, and a system-user token will mint one, subscribe the Page, report success at every step, and still fail the one call that fetches the lead. That is covered in Meta says your webhook is connected and it still sends nothing.

After you have it

Store it as a secret, not as config. It does not expire, which is exactly why leaking it is worse than leaking a temporary one. It belongs in an environment variable or a secrets manager, never in the repository and never in a frontend bundle.

Encrypt it at rest if you are multi-tenant. If you hold tokens for several businesses, encrypt them with a key that is not your application's auth secret. We learned that the hard way: rotating a JWT secret, which you must be able to do freely, silently made every stored WhatsApp token undecryptable, and nothing failed until the next send was attempted.

Do not assume permanent means immortal. The token does not expire on a timer, but it stops working if the System User is deleted, its asset assignment is revoked, or the app loses the permission. Treat (#190) as an alert rather than a retry condition.

Four things that will still kill a "permanent" token, none of them time-based:

  1. Someone deletes the System User, or removes its assignment to the app or the WhatsApp account
  2. The permission is revoked at app level, which can happen after an App Review outcome
  3. You click Revoke token in Business Settings, which is instant and cannot be undone. Generating a replacement is easy; noticing you need one is not
  4. The whole Meta app is deleted or restricted

All four surface as (#190), identically to an expired temporary token. So the error code alone does not tell you which happened, and that is worth logging around: record which organisation and which token failed, because at any scale "the token stopped working" is not a debuggable sentence.

At Kredoo each client connects their own WhatsApp account and we hold the System User token encrypted per organisation, which is why nobody's integration dies when somebody leaves their marketing agency. See how it works.

Questions people ask

Why does my WhatsApp Cloud API access token expire?

Because the token shown in the WhatsApp panel of the Meta app dashboard is temporary. Meta's documentation states that it expires quickly and is not suitable for development purposes. It exists to let you send one test message, and there is no call to refresh it. The permanent replacement is a System User token created in Business Settings.

How do I get a permanent WhatsApp API access token?

Create a System User in Business Settings, assign it your app with Manage app under Full control and your WhatsApp account with Manage WhatsApp Business accounts under Full control, then click Generate token and grant business_management, whatsapp_business_messaging and whatsapp_business_management. That token does not expire.

What permissions does a WhatsApp System User token need?

Three: whatsapp_business_messaging to send messages, whatsapp_business_management to manage templates and phone numbers, and business_management to read the business the account belongs to. A token missing any of them authenticates successfully and then fails on the corresponding call.

What does Meta error 190 mean?

Error 190 means your access token has expired. It is not a transient failure and retrying will not clear it, because the credential no longer exists rather than having been rejected. If you are seeing it in production you are almost certainly using a temporary or user token where a System User token is required.

What is the difference between a System User token and a user token?

A user token belongs to a person and dies when that person changes their password, loses their role on the asset, or leaves the company. A System User token belongs to the business, has no password, cannot be offboarded, and does not expire. Production integrations should always use the latter.

What is whatsapp_access_token and where do I get it?

It is the credential your server sends to Meta in the Authorization Bearer header on every Cloud API call, and tools name the field variously WHATSAPP_ACCESS_TOKEN, whatsapp_token or "System User Token". The value that belongs there is a System User token generated in Business Settings, not the token shown in the App Dashboard. It is a different thing from the App Secret, which verifies webhook signatures, and from the Phone Number ID and WABA ID, which are identifiers rather than credentials.

Does the WhatsApp temporary access token expire in 24 hours?

Approximately, and that is how it is usually described, but Meta does not publish a duration. The Cloud API getting-started guide says only that the token "expires quickly and is not suitable for development purposes". Treat roughly a day as an observation rather than a guarantee, and do not build anything that depends on it.

Does a WhatsApp System User token ever expire?

Not on a timer. It stops working only if the System User is deleted, its asset assignment is revoked, the permission is withdrawn at app level, the token is manually revoked, or the Meta app itself is deleted or restricted. All of those return error 190, exactly as an expired temporary token does, so the code alone will not tell you which occurred.

Can I use a System User token to read Meta lead ads?

No. Leadgen retrieval requires a Page access token. A System User token can mint a Page token, subscribe the Page and report success at every step, while still failing the call that actually fetches the lead. Use a System User token for WhatsApp and a Page token for lead ads.

Stop losing leads to the follow-up gap

Kredoo captures leads from Meta and Google Ads, then follows up on WhatsApp automatically. Live in 5 minutes.

Get Started