Skip to content

Environment Variables & Secrets

pywa itself never reads environment variables for you — your project’s own code reads them via os.environ and passes them to WhatsApp(...), exactly like every pywa example does:

import os
from pywa import WhatsApp
wa = WhatsApp(
phone_id=os.environ.get("PYWA_PHONE_ID"),
token=os.environ.get("PYWA_TOKEN"),
verify_token=os.environ.get("PYWA_VERIFY_TOKEN"),
)

Pywa Cloud’s job is getting the values you set into the container’s environment at deploy time — nothing more magical than that.

Terminal window
pywa cloud env set <bot-id> PYWA_PHONE_ID 1234567890
pywa cloud env set <bot-id> PYWA_TOKEN "your-real-token" --secret

env set is create-or-update: if the key doesn’t exist yet, it’s created with whatever --secret flag you passed; if it already exists, only its value is updated.

The --secret designation is fixed the moment a key is first created, and can never change afterward — not by omitting --secret on a later env set, not any other way. If you try, the CLI updates the value but tells you the flag was ignored:

✅ Updated 'PYWA_TOKEN' on my-bot (--secret ignored: the secret/plain designation is fixed at creation)

A secret value is never returned by any command or API call once set — not in env get, not in env list, not right after the env set that created it. If you lose it, there’s no way to retrieve it: delete the key and set it again.

A plain value is always readable back — useful for non-sensitive config like PYWA_PHONE_ID, where seeing the current value is more useful than hiding it.

Terminal window
pywa cloud env list <bot-id>
pywa cloud env get <bot-id> PYWA_TOKEN # → PYWA_TOKEN=<secret, value not shown> (updated ...)
pywa cloud env get <bot-id> PYWA_PHONE_ID # → PYWA_PHONE_ID=1234567890
pywa cloud env delete <bot-id> PYWA_PHONE_ID

Secret values are encrypted at rest with authenticated Fernet encryption (AES-128-CBC + HMAC-SHA256) using the control plane’s PYWA_CLOUD_SECRETS_KEY. Combined with the write-once contract enforced at the API layer, secret values are never accessible in plain text over the wire or in database storage, and are decrypted only when injected into the running container process.