Learning objectives
After reading this article you will be able to:
- Understand what Evolution API needs to run in production
- Start the API with Docker Compose and configure the .env file
- Create an instance, scan the QR code and send the first message
On this page
Evolution API turns a WhatsApp account into a REST API. Your system (a CRM, a chatbot, an admin panel) sends a POST and the message goes out; when a message arrives, it notifies you by webhook. That is why many teams use it instead of building a bot from scratch with a library.
Hosting it is different from running it on your laptop. The API keeps an open connection to WhatsApp and stores sessions and messages in a database. If the process stops, the connection drops. The steps below follow the repository's README; check the releases before installing, because scripts and variables can change between versions.
What does Evolution API need to run?#
According to the official README:
- The current Active LTS of Node.js (if you run it without Docker).
- PostgreSQL or MySQL, chosen in
DATABASE_PROVIDER. - Redis, recommended for caching.
- A process that stays on all the time, listening on port 8080 by default.
There is also a Docker image, evoapicloud/evolution-api:latest. The repository ships a docker-compose.yaml with the API, Redis and PostgreSQL.
How do you start it with Docker Compose?#
Create a folder with two files. First the .env, with your own values (don't reuse the repository's sample key):
SERVER_PORT=8080
SERVER_URL=http://localhost:8080
AUTHENTICATION_API_KEY=replace-with-a-long-random-key
DATABASE_PROVIDER=postgresql
DATABASE_CONNECTION_URI=postgresql://evolution:change-the-password@postgres:5432/evolution_db?schema=evolution_api
CACHE_REDIS_ENABLED=true
CACHE_REDIS_URI=redis://redis:6379/6
CACHE_REDIS_PREFIX_KEY=evolution
POSTGRES_DB=evolution_db
POSTGRES_USER=evolution
POSTGRES_PASSWORD=change-the-passwordThen the docker-compose.yaml, trimmed down from the official file:
services:
api:
image: evoapicloud/evolution-api:latest
restart: always
depends_on: [redis, postgres]
ports:
- "8080:8080"
env_file: .env
volumes:
- evolution_instances:/evolution/instances
redis:
image: redis:latest
restart: always
command: redis-server --port 6379 --appendonly yes
volumes:
- evolution_redis:/data
postgres:
image: postgres:15
restart: always
env_file: .env
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
evolution_instances:
evolution_redis:
postgres_data:Start it with docker compose up -d. The official file publishes the API only on 127.0.0.1; the example above exposes it on every interface, so put a reverse proxy with HTTPS in front and never leave the port open without the key.
How do you run it without Docker?#
This is for environments that run Node.js directly. The repository's steps are:
git clone https://github.com/EvolutionAPI/evolution-api.git
cd evolution-api
npm install
cp .env.example .env # edit database, Redis and AUTHENTICATION_API_KEY
npm run db:generate
npm run db:deploy
npm run build
npm run start:proddb:deploy applies the migrations for the provider set in DATABASE_PROVIDER, so define that variable first. start:prod runs the compiled dist/main.
db:generate generates the Prisma client for the chosen provider; without it, the API does not start. If the environment installs only dependencies (with NODE_ENV=production), two scripts break: build, because tsc is a devDependency, and prepare, because husky is one too. In that case, compile elsewhere and change prepare to husky || true, as the Husky docs suggest.
How do you create an instance and connect WhatsApp?#
Each WhatsApp number is an instance. The global key (AUTHENTICATION_API_KEY) goes in the apikey header:
curl -X POST http://localhost:8080/instance/create \
-H "apikey: $AUTHENTICATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{"instanceName":"my-instance","qrcode":true,"integration":"WHATSAPP-BAILEYS"}'The response carries the QR code in qrcode.base64. If you need a new one, request it with GET /instance/connect/my-instance. On your phone, open WhatsApp, go to Linked devices, Link a device, and scan the code. Then check the state:
curl http://localhost:8080/instance/connectionState/my-instance \
-H "apikey: $AUTHENTICATION_API_KEY"How do you send the first message?#
curl -X POST http://localhost:8080/message/sendText/my-instance \
-H "apikey: $AUTHENTICATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{"number":"15551234567","text":"Hello from Evolution API"}'The number includes the country code and the full number, without +. If the response returns the sent message's data and the text shows up on the phone, it worked. To receive messages, configure the instance's webhook to point at a URL of yours.
How do you secure the installation?#
AUTHENTICATION_API_KEY grants full access: it creates and deletes instances and sends messages from any connected number. Treat it like a production password.
- Generate a long random key and keep it in an environment variable, never in the repository (see what environment variables are).
- Do not expose PostgreSQL or Redis to the internet. In Compose, keep them on the internal network only and remove any
portsfrom those services. - Serve the API behind HTTPS and, if you can, restrict callers by IP.
- Set
SERVER_URLto the real public URL, because it appears in responses and webhooks. - To understand the packaging better, read how to dockerize an app.
Evolution API is a third-party project: follow the repository's releases before changing the image tag, instead of always relying on latest.
What are the common errors?#
- Database connection fails:
DATABASE_CONNECTION_URIhas the wrong host. Inside Compose the host is the service name (postgres), notlocalhost. - Migrations did not run: in a non-Docker install,
npm run db:deployor theDATABASE_PROVIDERvariable is missing. - TLS error on the database: if the database requires a client certificate, Prisma reads it from
DATABASE_CONNECTION_URIitself:sslmode=require,sslcertwith the server CA andsslidentitywith the client certificate in PKCS12 format (plussslpasswordif it has one). Paths are relative to theprismafolder. redis disconnectedin a loop withrediss://: Evolution API'sredisclient turns on TLS by itself withrediss://, but it only trusts public CAs. If the Redis uses its own CA, pointNODE_EXTRA_CA_CERTSat the CA file in the command that starts the process, not in.env: Node reads this variable only at startup.- 401 on every call: the
apikeyheader does not matchAUTHENTICATION_API_KEY. - QR code requested again after a restart: the instance data did not persist. Check volumes and the database, and read why a WhatsApp bot keeps disconnecting.
- Restricted number: the Baileys integration is unofficial. For commercial use at scale, compare it with the official API.
How to do this on Square Cloud#
Evolution API has to stay online all the time. On Square Cloud, a self-service host, containers are always on with no sleep mode, and automatic restart, which is on by default when you deploy from the dashboard, brings the process back when it exits with an error.
You run Evolution API on the Node.js runtime, using the install-from-source steps above. There is no Dockerfile, Docker Compose or build step, and dependencies are installed with NODE_ENV=production: compile in an external CI such as GitHub Actions, upload the project with the dist folder already built and adjust prepare as described above. Because Evolution API reads its port from SERVER_PORT, a START such as npm run db:generate && npm run db:deploy && SERVER_PORT=$PORT npm run start:prod makes the API listen on the port in the PORT variable, which the platform sets.
Environment variables are per application: the dashboard imports a .env file, and a change applies on the next restart. From the Standard plan up, you can host PostgreSQL, MySQL and Redis in the same datacenter as your applications; the Hobby plan doesn't include databases. The dashboard gives you the full connection URL and the certificate, and TLS is required. On PostgreSQL, the client also presents the downloaded certificate, set in the URL as explained under common errors above. The plan's RAM is a shared pool, with a minimum of 512 MB per web application.
To use a Redis hosted on the platform as the cache, download the Certificate CA (.crt) option on the database page, which saves ca-certificate.crt, put the file at the project root and set:
# application environment variables (the dashboard's connection URL)
CACHE_REDIS_ENABLED=true
CACHE_REDIS_URI=rediss://default:YOUR_PASSWORD@HOST:PORT
# START command
npm run db:generate && npm run db:deploy && NODE_EXTRA_CA_CERTS=./ca-certificate.crt SERVER_PORT=$PORT npm run start:prodUse the host from the dashboard URL, not an IP, so the name matches the certificate, and don't append /6: this Redis has a single logical database and doesn't ask for a client certificate.
If you'd rather build the bot directly with Baileys, WPPConnect, whatsapp-web.js or the official Cloud API, see WhatsApp bot hosting.
Bot hosting
Keep your bot online 24/7 with automatic restarts
FAQs
Is Evolution API free?
The code is open source (Apache 2.0, with additional branding conditions), so there is no license to pay for. You pay for the infrastructure it runs on: server, database and Redis. If you use the official Cloud API, Meta charges per delivered message, depending on the category and the country.
Does Evolution API need a database?
Yes. The README asks for PostgreSQL or MySQL, set in DATABASE_PROVIDER, and recommends Redis for caching. Without a database, instances and messages do not persist.
Can I run Evolution API without Docker?
Yes. Clone the repository, run npm install, configure the .env file, run npm run db:generate and npm run db:deploy, then npm run build and npm run start:prod.
Does Evolution API use the official WhatsApp API?
It supports both. The WHATSAPP-BAILEYS integration uses WhatsApp Web, which is unofficial. The integration with Meta's Cloud API is the official route.
More in Bots
See all 33 articles- Running a bot on your phone or PC vs hosting itA bot on your PC or phone (Termux) goes offline when the device shuts down, sleeps or loses its network. Compare the three options and when each one fits.
- How to host a Discord bot 24/7To keep a Discord bot online 24/7, run its process on an always-on machine with automatic restarts. Compare your PC, a VPS with pm2 or systemd, and bot hosting.
- Why your Discord bot keeps going offline (and how to fix it)A Discord bot goes offline when the process dies, the token is invalid, an intent is disabled or memory runs out. Learn to diagnose each cause and fix it.
- How to host a Telegram bot 24/7To keep a Telegram bot online 24/7, run its process on an always-on server using long polling or a webhook. See working code and the common errors.