On Cloud API
WhatsApp Business API Platform
Ready100%
Platform FeaturesEverything you need across WhatsApp, Instagram & Messenger
WhatsApp Team InboxOne number, many agents — zero missed chats
Instagram InboxDMs, story replies & comments in one place
Messenger InboxPage DMs & post comments as conversations
AI Agent (RAG)A smart agent trained on your own business data
Multiple Human Live ChatHandle chats from several agents at once
Ask AIAI-powered smart replies & suggestions
Chatbot Flow BuilderBuild automated reply flows, no coding needed
Retarget Users on WhatsAppRe-engage past contacts with targeted messages
WhatsApp SchedulerSchedule messages for the perfect moment
Import, Broadcast & TrackBulk send campaigns & monitor delivery rates
Ads that Click to WhatsAppTurn ad clicks directly into WhatsApp chats
Multi-Agent Live ChatOne number, many agents — zero missed chats
Connect No Code A.I. ChatbotsPlug in AI bots with zero lines of code
Broadcast CampaignsNo campaign cap from us — Meta’s messaging limits apply
Official, Not a Grey ToolMeta-approved Cloud API — no unofficial workarounds
See all features & pricing
Industries We PowerPurpose-built WhatsApp automation for every sector
Education & EdtechCoaching, Institutes & Online Learning
Banking & FintechDigital Payments, Lending & Finance
HealthcareClinics, Hospitals & Wellness
Events & WebinarConferences, Meetups & Live Events
EcommerceOnline Stores, D2C & Marketplaces
Real EstateAgents, Developers & Property Listings
IT Services & InternetTech Support, SaaS & Web Services
Offline & RetailStores, Outlets & Local Businesses
HR & RecruitmentHiring, Onboarding & Talent Acquisition
Spas & SalonsBookings, Promotions & Client Loyalty
AutomobileDealerships, Service Centers & Rentals
Travel & TourismBookings, Tours & Hospitality
Marketing AgenciesCampaigns, Leads & Client Updates
GovernmentPublic Services & Citizen Engagement
Gym & Fitness CentersMemberships, Classes & Reminders
Blogs
All Blogs/Article
Article

How to Create a Permanent WhatsApp Business API Access Token for Production

On Cloud API TeamSeptember 27, 202615 min read13 views

The token on Meta's WhatsApp API Setup page is fine for a quick test. It is not what should be running your CRM, chatbot, order alerts or n8n workflow. This guide walks through the system user setup that keeps a WhatsApp Cloud API integration authenticated for the long run, and the checks that save you from a 2 a.m. "messages stopped sending" call.

How to Create a Permanent WhatsApp Business API Access Token for Production

WhatsApp Cloud API · Production authentication · 2026

How to Create a Permanent WhatsApp Business API Access Token for Production

The token on Meta's WhatsApp API Setup page is fine for a quick test. It is not what should be running your CRM, chatbot, order alerts or n8n workflow. This guide walks through the system user setup that keeps a WhatsApp Cloud API integration authenticated for the long run, and the checks that save you from a 2 a.m. "messages stopped sending" call.

By On Cloud API team · Updated · Checked against Meta's access token documentation on the same date

Under 24 hoursLife of the test (user) token from API Setup
60 days or NeverExpiry options for a system user token
3 permissionsMeta lists for system user tokens

Quick answer

To get a permanent WhatsApp Cloud API access token, create a system user in Meta Business Settings, assign it your Meta app and your WhatsApp Business Account (WABA), then click Generate token, choose Never as the expiry and select business_management, whatsapp_business_management and whatsapp_business_messaging. Test it with one small API call, then store it on your server, never in frontend code.

Here's how this usually goes wrong. You create a Meta app, add WhatsApp, copy the token from the API Setup page and send a test message. It works, so the job looks done.

The next morning, order confirmations aren't going out. Your Laravel queue is full of authorization errors, the n8n workflow that was fine yesterday is red, and the webhook is still receiving messages while nothing goes out.

Nothing is wrong with the code. Production was running on a test token, and test tokens expire in less than a day.

Test token vs production system user token

Both are Meta access tokens, and both go in the same Authorization: Bearer header. What differs is who they represent and how long they last.

TokenRepresentsLifetimeUse it for
User access tokenYou, the person logged inShort-lived; Meta says it expires in less than 24 hoursQuick tests only
System user access tokenYour business's backend softwareLong-lived; you choose the expiry when generating itYour own production integration
Business integration system user tokenOne customer onboarded by a Tech ProviderLong-lived, scoped to that customerTech Providers using Embedded Signup

Meta describes system users as identities for servers and automated services. That's the whole point: your backend shouldn't depend on an employee logging in and pasting a fresh token every morning.

Simple way to think about it: your personal Meta account sets things up. The system user is what your production software logs in as.

What "permanent" actually means

When you generate a system user token, Business Settings asks you to set an expiry. At the time of writing the options are a fixed period (60 days) or Never. Pick Never and there's no scheduled expiry, so no daily token swaps.

That's not the same as "works forever no matter what". A permanent token stops working if:

  • someone revokes it or generates a replacement and invalidates the old one,
  • the system user loses access to the app or the WABA,
  • a permission is removed, or
  • the system user itself is deleted.
Don't let "permanent" make you careless. A token that never expires is worth more to anyone who steals it. Permanent means you don't rotate it daily. It doesn't mean it's safe to hard-code in your app.

What you need before creating the token

  • Admin access to the Meta Business Portfolio that owns your WhatsApp setup.
  • A Meta app with the WhatsApp product added.
  • A WhatsApp Business Account with your number already connected to Cloud API.
  • Your WABA ID and Phone Number ID (both on the app's WhatsApp → API Setup page).
Keep everything from one setup. A token from one app paired with a WABA ID copied from a different business portfolio is a classic cause of errors. Every value looks right, and the request still fails.

Step by step: create a permanent WhatsApp Cloud API access token

Meta renames menu items now and then, but the flow stays the same: system user → assign assets → generate token → pick permissions.

  1. Open the right business. Go to Meta Business Settings (business.facebook.com/settings) and switch to the portfolio that owns your WhatsApp app and WABA. If your personal account can see several businesses, double-check this.
  2. Create a system user. Go to Users → System users → Add. Give it a clear name such as whatsapp-production and make it an Admin system user. An Employee system user works too, but you'll have to grant each WABA to it one by one.
  3. Assign your Meta app. With the system user selected, click Assign assets → Apps, pick your WhatsApp app and give it full control (Manage app).
  4. Assign your WhatsApp account. Still under Assign assets, open WhatsApp accounts, pick your WABA and give full control. Skip this step and your token will authenticate fine, then fail on every WABA request.
  5. Click Generate token. Select the same Meta app you just assigned.
  6. Set the expiry to Never. This is the "permanent" part. If your security policy requires rotation, choose 60 days instead and schedule the renewal.
  7. Select the permissions: business_management, whatsapp_business_management and whatsapp_business_messaging. Leave everything else unticked.
  8. Copy the token straight into your secrets store. Meta shows it once. Don't park it in a notes app, a screenshot or a Slack message.
  9. Verify before you deploy. Run the checks in the next section before you touch your live app.

Which permissions should you select?

Meta's current access token guide lists three permissions for system user tokens:

PermissionWhat it covers
whatsapp_business_messagingSending and receiving messages, registering numbers, media
whatsapp_business_managementManaging the WABA: phone numbers, message templates, settings, webhook subscriptions
business_managementBusiness portfolio access that system user setups rely on

Some older tutorials only tick whatsapp_business_messaging. That's enough to send a message, but the first time your app tries to sync templates or list phone numbers, you'll get a permissions error. Select all three and nothing beyond them.

Verify and test the token before going live

1. Check it in the Access Token Debugger

Paste the token into Meta's Access Token Debugger. Confirm four things:

  • Type: System User.
  • App: the WhatsApp app you intended.
  • Expires: Never (or the date you chose).
  • Scopes: all three permissions listed above.

2. Confirm it can reach your WABA

curl -X GET \
"https://graph.facebook.com/<GRAPH_API_VERSION>/<WABA_ID>/phone_numbers" \
-H "Authorization: Bearer <SYSTEM_USER_ACCESS_TOKEN>"

If your number comes back, the token works, the system user can see the WABA and you've got the right Phone Number ID. If you get an error here, fix the asset assignment first. There's no point testing a message yet.

3. Send one template message

curl -X POST \
"https://graph.facebook.com/<GRAPH_API_VERSION>/<PHONE_NUMBER_ID>/messages" \
-H "Authorization: Bearer <SYSTEM_USER_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
  "messaging_product": "whatsapp",
  "to": "<YOUR_OWN_TEST_NUMBER>",
  "type": "template",
  "template": {
    "name": "hello_world",
    "language": { "code": "en_US" }
  }
}'

Use a current Graph API version from Meta's changelog in place of <GRAPH_API_VERSION> (for example v25.0), and send the test to your own number first.

How to store a permanent token safely

Keep it in a server environment variable or a secrets manager:

WHATSAPP_ACCESS_TOKEN=your_system_user_access_token
WHATSAPP_WABA_ID=your_waba_id
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id

Never like this:

const accessToken = "EAA...REAL_PRODUCTION_TOKEN...";
  • Backend only. Anything shipped to a browser or a mobile app can be read by the person using it.
  • Keep it out of Git, including private repos and old commits.
  • Mask it in logs; never print the full value.
  • Limit who on the team can read production secrets.
  • Write down how to revoke and replace it, so a leak is a 10-minute fix, not a panic.

Swap the test token for the permanent one without downtime

  1. Create and verify the new token first. Keep the old setup running until the new token passes both test calls.
  2. Update the value in one place: your .env, secrets manager or hosting panel, not scattered across the code.
  3. Restart everything that caches config. Laravel queue workers, PHP-FPM, Docker containers and Node.js processes can keep the old token in memory. In Laravel, run php artisan config:clear and restart the queue workers.
  4. Send one controlled message to an internal number.
  5. Watch the logs for an hour. Auth errors right after a swap almost always mean one service is still holding the old token.

Permanent WhatsApp token not working? Check these first

Before you generate yet another token, work down this chain. A new token with the same broken setup will fail in exactly the same way.

Token type → Permissions → App assigned → WABA assigned → Phone Number ID → Message payload

What you seeLikely causeFix
Error 190 (OAuthException)Expired, revoked or test tokenCheck the token in the Debugger; replace any user token with a system user token
Error 200 or 10Missing permissionRegenerate with all three permissions
Error 100Wrong ID in the requestCheck the Phone Number ID and WABA ID; never put +92… or +971… in the URL
Token valid, WABA call failsWABA not assignedAssign the WhatsApp account to the system user
Worked before the swap, fails afterOld token cachedRestart workers, containers and services
"Permanent" token suddenly diesRevoked or access removedCheck the Debugger and the system user's assets in Business Settings

Using the permanent token in n8n, Laravel, Node.js or Python

The token works the same in every stack. Only the HTTP client changes. In n8n, save it once in the Credentials section rather than pasting it into a Code or Set node. That way, when you rotate it, you change it in one place. Our WhatsApp Business API + n8n guide covers the full workflow, including triggers and webhooks.

In Laravel/PHP read it from .env, in Node.js from process.env, and in Python from os.environ. The token process is also the same whether your business is in Pakistan, the UAE, India, Bangladesh, the UK or the US. What changes by country is message pricing, not authentication.

Don't want to manage tokens at all?

If you connect your number through a Meta Tech Provider using Embedded Signup, the provider receives a business integration token scoped to your account. You don't generate, store or rotate anything yourself. On Cloud API is a Meta Verified Tech Provider on the official WhatsApp Cloud API, with a shared inbox, chatbot builder, campaigns and a REST API on top. See the On Cloud API overview if you'd rather skip the credential work.

Production token checklist

  • The token is a system user token, not the one copied from API Setup.
  • The system user has the right app and WABA assigned.
  • The token has all three permissions: business_management, whatsapp_business_management, whatsapp_business_messaging.
  • The Debugger shows the expected type, app and expiry.
  • The /phone_numbers call and one test template both work.
  • The token is stored server-side, out of Git and masked in logs.
  • Workers and containers were restarted after the swap.
  • The team knows how to revoke and replace it.

Frequently asked questions

How do I create a permanent WhatsApp Business API access token?

In Meta Business Settings, create a system user, assign it your Meta app and WhatsApp Business Account, then click Generate token, set the expiry to Never and select business_management, whatsapp_business_management and whatsapp_business_messaging.

How long does the WhatsApp Cloud API test token last?

The user access token from the API Setup page is short-lived. Meta says it expires in less than 24 hours, so it should only be used for quick tests.

Can a WhatsApp system user access token really be permanent?

Yes, in the sense that you can generate it with no expiry by choosing Never. It still stops working if it is revoked, if the system user loses access to the app or WhatsApp account, or if a permission is removed.

Which permissions does a WhatsApp system user token need?

Meta's access token guide lists business_management, whatsapp_business_management and whatsapp_business_messaging for system user tokens. Select those three and nothing more.

How do I check whether my token is a system user token?

Paste it into Meta's Access Token Debugger. It shows the token type, the app it belongs to, its expiry and the permissions it has.

Why is my permanent WhatsApp token valid but messages still fail?

A valid token does not mean the system user can reach your WhatsApp account. Check that the app and WABA are assigned to the system user, that all three permissions are present and that you are using the Phone Number ID, not the visible phone number.

What does WhatsApp API error 190 mean?

Error 190 is an OAuthException that usually means the access token has expired, been revoked or is invalid. It is the typical error when a test token was deployed to production.

Can I use the permanent token in n8n, Laravel, Node.js or Python?

Yes. The token works the same in every stack. Store it in n8n credentials or a server environment variable, never in frontend code or a Git repository.

Do I need a permanent token if I use a Tech Provider like On Cloud API?

Usually not. When you connect through a Tech Provider's Embedded Signup, the provider receives a business integration token scoped to your account, so you do not generate or store a token yourself.

Ready to Start with WhatsApp Business API?

Join 5,000+ businesses. Meta Verified. 0% markup on Meta rates. Live in 10 minutes.