Skip to main content
Evolution API uses API key authentication via the apikey header. The system supports two levels of authentication: global API keys and per-instance tokens.

Authentication Architecture

Authentication is handled by the auth guard middleware (src/api/guards/auth.guard.ts:10-51) which validates every protected request.

Two-Level Authentication

Evolution API implements a hierarchical authentication model:
  1. Global API Key: Administrative access for creating and managing all instances
  2. Instance Tokens: Scoped access for operations on specific instances
This dual-key system provides security through least-privilege access. Use instance tokens for client applications and reserve the global key for administrative operations.

Global API Key

The global API key provides unrestricted access to all instances and administrative operations.

Configuration

Set the global API key using the AUTHENTICATION_API_KEY environment variable:
.env
AUTHENTICATION_API_KEY=your-secure-global-api-key-here
Default Value: If not set, the system uses BQYHJGJHJ as the default key. You must change this in production environments.See src/config/env.config.ts:407 for the default configuration.

Using the Global API Key

Include the global API key in the apikey header:
curl -X POST https://api.yourdomain.com/instance/create \
  -H "apikey: your-secure-global-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "instanceName": "my-instance",
    "token": "instance-specific-token",
    "qrcode": true
  }'

Global Key Permissions

The global API key grants access to:
  • Instance creation: POST /instance/create
  • Fetch all instances: GET /instance/fetchInstances
  • All instance operations: Full CRUD on any instance
  • Administrative endpoints: Metrics, health checks, configuration

Instance Tokens

Each instance has a unique token that provides scoped access to only that instance’s operations.

Token Generation

Instance tokens are set during instance creation:
{
  "instanceName": "customer-support",
  "token": "cs-prod-2024-secure-token",
  "qrcode": true
}
token
string
required
A unique identifier for this instance. This becomes the instance’s authentication token.Requirements:
  • Must be unique across all instances
  • Recommended: Use UUID or similar cryptographically random strings
  • Avoid predictable patterns for security

Using Instance Tokens

Once an instance is created, use its token for all instance-specific operations:
curl -X POST https://api.yourdomain.com/message/sendText/customer-support \
  -H "apikey: cs-prod-2024-secure-token" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "5511999999999",
    "text": "Hello from Evolution API!"
  }'

Token Scope and Isolation

Instance tokens are validated against the database (src/api/guards/auth.guard.ts:30-35):
const instance = await prismaRepository.instance.findUnique({
  where: { name: param.instanceName },
});
if (instance.token === key) {
  return next();
}
Security Boundary: Instance tokens can only access their own instance data. Attempts to access other instances will result in a 401 Unauthorized error, even with a valid token.

Authentication Flow

The authentication guard implements the following flow (src/api/guards/auth.guard.ts:10-51):

Authentication Priority

  1. Global API Key: Checked first, grants immediate access if valid
  2. Instance Token: Checked if global key doesn’t match
  3. Database Validation: Instance tokens are verified against the database

Per-Instance Access Control

Evolution API enforces strict per-instance access control:

Instance Name Validation

All instance-specific endpoints require the instanceName parameter:
/message/sendText/:instanceName
/chat/findChats/:instanceName
/group/create/:instanceName
The instance name is extracted and validated before processing (src/api/abstract/abstract.router.ts:34).

Database-Level Isolation

All database queries include instance-scoped filters:
const messages = await prismaRepository.message.findMany({
  where: {
    instanceId: instance.id  // Always filter by instance
  }
});
This architecture ensures complete data isolation between tenants, even in the event of application-level bugs.

Common Authentication Scenarios

Scenario 1: Administrative Dashboard

Use the global API key for administrative interfaces:
// Create new instance for customer
const createInstance = async (customerName) => {
  const response = await fetch('/instance/create', {
    headers: { 'apikey': GLOBAL_API_KEY },
    method: 'POST',
    body: JSON.stringify({
      instanceName: `customer-${customerName}`,
      token: generateSecureToken(),
      qrcode: true
    })
  });
  return response.json();
};

Scenario 2: Client Application

Provide instance tokens to client applications:
// Client receives their instance token
const INSTANCE_TOKEN = 'customer-xyz-token';
const INSTANCE_NAME = 'customer-xyz';

// Send messages using instance token
const sendMessage = async (number, text) => {
  const response = await fetch(
    `/message/sendText/${INSTANCE_NAME}`,
    {
      headers: { 'apikey': INSTANCE_TOKEN },
      method: 'POST',
      body: JSON.stringify({ number, text })
    }
  );
  return response.json();
};

Scenario 3: Multi-Instance Management

Use the global key to manage multiple instances:
// Fetch all instances
const instances = await fetch('/instance/fetchInstances', {
  headers: { 'apikey': GLOBAL_API_KEY }
});

// Operate on specific instances
for (const instance of instances) {
  await fetch(`/instance/connectionState/${instance.name}`, {
    headers: { 'apikey': GLOBAL_API_KEY }
  });
}

Authentication Error Responses

Evolution API returns specific error responses for authentication failures:

Missing API Key

Request:
GET /instance/connectionState/my-instance
# Missing apikey header
Response (401):
{
  "status": 401,
  "error": "Unauthorized",
  "message": "Unauthorized"
}
See src/exceptions/401.exception.ts:3-11 for the exception implementation.

Invalid API Key

Request:
GET /instance/connectionState/my-instance
apikey: invalid-key-here
Response (401):
{
  "status": 401,
  "error": "Unauthorized",
  "message": "Unauthorized"
}

Wrong Instance Token

Request:
POST /message/sendText/instance-a
apikey: instance-b-token

{ "number": "123", "text": "test" }
Response (401):
{
  "status": 401,
  "error": "Unauthorized",
  "message": "Unauthorized"
}

Missing Global Key for Administrative Operations

Request:
POST /instance/create
apikey: some-instance-token

{ "instanceName": "new-instance" }
Response (403):
{
  "status": 403,
  "error": "Forbidden",
  "message": [
    "Missing global api key",
    "The global api key must be set"
  ]
}
See src/exceptions/403.exception.ts:3-11 for the Forbidden exception.

Verifying Credentials

Test your authentication credentials using the verify endpoint:
POST /verify-creds
apikey: your-api-key
Success Response (200):
{
  "status": 200,
  "message": "Credentials are valid",
  "facebookAppId": "...",
  "facebookConfigId": "...",
  "facebookUserToken": "..."
}
This endpoint is defined in src/api/routes/index.router.ts:207-216.

Security Best Practices

Follow these security guidelines to protect your Evolution API deployment:

1. Secure API Key Generation

Generate cryptographically secure API keys:
// Node.js example
const crypto = require('crypto');
const apiKey = crypto.randomBytes(32).toString('hex');
# Python example
import secrets
api_key = secrets.token_hex(32)

2. Environment Variable Management

Never commit API keys to version control:
# .env (not committed)
AUTHENTICATION_API_KEY=production-secure-key-here

# .env.example (committed)
AUTHENTICATION_API_KEY=change-this-in-production

3. Key Rotation

Implement regular key rotation:
  • Global keys: Rotate quarterly or after team changes
  • Instance tokens: Rotate when clients request or after security events
  • Process: Create new key → update clients → revoke old key

4. HTTPS Only

Always use HTTPS in production to prevent key interception:
SERVER_TYPE=https
SERVER_URL=https://api.yourdomain.com

5. IP Allowlisting

Restrict API access to known IP addresses at the infrastructure level (reverse proxy, firewall, or API gateway).

6. Monitor Authentication Failures

Log and alert on repeated authentication failures:
// The auth guard logs errors
logger.error(error);  // src/api/guards/auth.guard.ts:47

7. Instance Token Management

Control instance token visibility:
# Hide tokens in fetchInstances response
AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=false
When set to false, the /instance/fetchInstances endpoint will not return instance tokens in the response.

Next Steps

Error Handling

Learn about authentication error codes and troubleshooting

Create Instance

Create your first WhatsApp instance

API Overview

Return to API overview

Security

Read the full security documentation

Build docs developers (and LLMs) love