Get started
Authentication
API keys, abilities, live and test, and how to keep keys safe.
In a nutshell
Send your API key as a Bearer token on every request. sk_live_ keys work on real businesses, sk_test_ keys on sandbox businesses only. Each key has abilities; a request without the needed ability gets 403 missing_ability.
API keys
Every request carries one of your product's API keys:
Authorization: Bearer sk_live_4gVx...
Accept: application/json
sk_live_...keys work on your real businesses.sk_test_...keys work on sandbox businesses only - a separate set, with simulated WhatsApp that never reaches Meta (see Testing). The two never see each other's businesses.- Keys are created by a PaalChat operator and shown once. PaalChat stores only a
hash and the first characters (shown as
prefix), so a lost key cannot be recovered - it is replaced instead. Revoked or expired keys stop working at once (401). - A key can be limited to your servers' IP addresses; from anywhere else it is refused.
- The prefixes let secret scanners spot leaked keys. Older
<id>|ptw_...tokens still work, as live keys. - Operator console logins do not work on the API; only API keys do.
- If your product is suspended, every key is refused with
403 product_suspended.
Warning
Don't use your token in a frontend. Never call PaalChat from a browser or mobile app: all requests must come from your server, and your frontend talks to your server.
Abilities
Each token has abilities. Ask only for the ones your integration needs.
| Ability | Grants |
|---|---|
businesses.read |
List businesses, Get business |
businesses.write |
Create or update business |
connections.read |
WhatsApp state, phone numbers |
connections.manage |
Create connect link, Disconnect WABA |
templates.read |
List templates |
templates.manage |
Create template, Delete template |
messages.read |
Get message |
messages.send |
Send message |
contacts.read |
List contacts, Get contact, contact fields |
contacts.write |
Create or update contact, Update contact, Define a contact field |
conversations.read |
List conversations, Get conversation, List notes |
businesses.read (also) |
Get usage |
messages.send (also, test keys) |
Simulate an incoming message, Simulate a delivery status |
messages.urgent |
urgent: true on Send message - skip quiet hours |
data.manage |
Export business data, Get export, Erase contact |
campaigns.read / campaigns.manage |
Campaigns: list, get, preview / create, launch, pause, resume, cancel |
automations.read / automations.manage |
Automations: list, get, runs / create, update, delete |
billing.manage |
Get billing, Pay invoice |
conversations.manage |
Update conversation, Add note |
inbox.manage |
Sign staff in to the inbox, List inbox members, Remove inbox access |
webhooks.read / webhooks.manage are reserved for
endpoints that are coming; a token can hold them already.
Note
Until 1 October 2026 the scopes were businesses:read, businesses:write,
whatsapp:read, whatsapp:connect and whatsapp:send. Tokens issued with them
were converted automatically (whatsapp:read became connections.read,
templates.read and messages.read); GET /me shows a token's current scopes.
Check a token
GET /me returns your product and the token's abilities. Call it
when your app starts and fail loudly if an ability you need is missing.
Issuing, rotating and revoking
Operators manage tokens on the PaalChat server:
php artisan products:token multi-skuul --name=production --ability=messages.send --ability=connections.read --ability=templates.read
php artisan products:token multi-skuul --name=production --all --rotate # replace it
php artisan products:token multi-skuul --list
php artisan products:token multi-skuul --revoke=12
Rotate immediately if a token may have leaked.
Errors
| HTTP | error.code |
Meaning |
|---|---|---|
| 401 | unauthenticated |
Missing, wrong, revoked or expired token |
| 403 | missing_ability |
The token lacks the ability for this endpoint |
| 403 | product_suspended |
Your product is suspended on PaalChat |
| 403 | product_token_required |
The credential is not a product token |