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 osfrom 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.
Setting a variable
Section titled “Setting a variable”pywa cloud env set <bot-id> PYWA_PHONE_ID 1234567890pywa cloud env set <bot-id> PYWA_TOKEN "your-real-token" --secretenv 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.
Plain vs. secret
Section titled “Plain vs. secret”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.
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=1234567890pywa cloud env delete <bot-id> PYWA_PHONE_IDEncryption at rest
Section titled “Encryption at rest”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.