Whatsflow Whatsflow Developers
AR Website Get an API key
From your app to a real conversation

Guide to Whatsflow API.

Connect WhatsApp to your app and send messages from one place.
Everything you need to get started, with clear examples you can adapt.

REST APIJSONAPI Key Auth
Your first steps

From zero to your first message

Start with the credentials provided when your API service is activated.

  1. 01

    Prepare your credentials

    Your service address BASE_URL, session name INSTANCE, and API_KEY.

  2. 02

    Connect your number

    Scan the QR code, then check that the connection state is open.

  3. 03

    Send your first message

    Try the message example with a test number you own, then add it to your app.

Service address BASE URLhttps://connect.whats-flow.netHTTPS

Use the service address above with the session name and key provided during activation. Replace my-business with your session name and .example and YOUR_… placeholders with your details. v1 is the documentation version; do not add /v1 or /docs/v1 to API request paths.

Terminal · Bash / Zsh
export BASE_URL="https://connect.whats-flow.net"
export INSTANCE="my-business"
export API_KEY="YOUR_API_KEY"

Set these variables once in your terminal session before running the cURL examples. In your app, keep them in your server configuration.

Authenticated requests

One key for your requests

Include your session key in the apikey header on every request. POST requests in this guide use JSON.

HeaderValueUsage
apikeyYOUR_API_KEYRequired for every request
Content-Typeapplication/jsonFor JSON request bodies
Keep your key on the server.

Make requests from your server. Never expose your key in browser code or a public repository. The {instance} path parameter is your assigned session name, not a phone number.

Request referenceAPI REFERENCE
Connection

Connect a WhatsApp number#

Request a QR code for the session provisioned for your account. Scan it in WhatsApp under Linked devices → Link a device.

GET/instance/connect/{instance}API KEY

Request parameters

instancepath · stringRequired

The session name supplied on activation, for example my-business.

This request does not require a body.

While waiting to connect, base64 contains the QR image. This abridged example is not a scannable code. Request a new code if it expires. An already connected session may return connection information instead.

Request · cURL
curl --request GET "${BASE_URL}/instance/connect/${INSTANCE}" \
  --header "apikey: ${API_KEY}"
Sample response (abridged)200
Response · JSON
{
    "pairingCode": null,
    "code": "QR_CODE_CONTENT",
    "base64": "data:image/png;base64,QR_IMAGE_DATA",
    "count": 1
}
Connection

Connection state#

Check that your session is ready before sending messages. Read state inside instance to see its current connection status.

GET/instance/connectionState/{instance}API KEY

Request parameters

instancepath · stringRequired

The session name supplied on activation, for example my-business.

This request does not require a body.

open: connected and ready to send. connecting: establishing a connection. close: disconnected; check the phone and reconnect if needed.

Request · cURL
curl --request GET "${BASE_URL}/instance/connectionState/${INSTANCE}" \
  --header "apikey: ${API_KEY}"
Sample response (abridged)200
Response · JSON
{
    "instance": {
        "instanceName": "my-business",
        "state": "open"
    }
}
Messages

Send a text message#

Send an order confirmation, shipping update, or follow-up message. Use the recipient's international phone number with digits only, without + or spaces.

POST/message/sendText/{instance}API KEY

Request parameters

instancepath · stringRequired

The session name supplied on activation, for example my-business.

numberstringRequired

Recipient phone number including the country code, for example 201000000000.

textstringRequired

The text of the message to send.

linkPreviewbooleanOptional

Enable link previews in the message.

delayintegerOptional

Delay before sending, in milliseconds.

This response is abridged. Store key.id to track the message. An accepted request or PENDING status does not confirm delivery; follow message updates through webhooks.

Request · cURL
curl --request POST "${BASE_URL}/message/sendText/${INSTANCE}" \
  --header "apikey: ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "number": "201000000000",
    "text": "Hi Ahmed, your order #1042 is confirmed. Thank you for choosing us!",
    "linkPreview": false
}'
Sample response (abridged)201
Response · JSON
{
    "key": {
        "remoteJid": "201000000000@s.whatsapp.net",
        "fromMe": true,
        "id": "EXAMPLE_MESSAGE_ID"
    },
    "status": "PENDING"
}
Messages

Send images and files#

Share a product image, video, or document such as a PDF invoice using a direct URL the service can access.

POST/message/sendMedia/{instance}API KEY

Request parameters

instancepath · stringRequired

The session name supplied on activation, for example my-business.

numberstringRequired

Recipient phone number in international format.

mediatypestringRequired

Media type: image, video, or document.

mediastringRequired

A direct file URL or its Base64-encoded contents.

mimetypestringOptional

The MIME type matching the file, such as application/pdf.

fileNamestringOptional

The filename shown to the recipient, especially for documents.

captionstringOptional

A caption or text accompanying the file.

Replace the example file URL with a real one that serves the file directly without a login page. Set mediatype and mimetype to match. File size and sending limits depend on your account settings.

Request · cURL
curl --request POST "${BASE_URL}/message/sendMedia/${INSTANCE}" \
  --header "apikey: ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "number": "201000000000",
    "mediatype": "document",
    "mimetype": "application/pdf",
    "media": "https://your-store.example/invoices/1042.pdf",
    "fileName": "invoice-1042.pdf",
    "caption": "Invoice for your order #1042"
}'
Sample response (abridged)201
Response · JSON
{
    "key": {
        "id": "EXAMPLE_MEDIA_MESSAGE_ID",
        "fromMe": true
    },
    "status": "PENDING"
}
Events

Receive events · Webhooks#

Receive messages and connection updates on your server automatically. Create an HTTPS endpoint that accepts POST requests with JSON, then register it for your session.

POST/webhook/set/{instance}API KEY

Request parameters

instancepath · stringRequired

The session name supplied on activation, for example my-business.

webhook.enabledbooleanRequired

Enable or disable event delivery.

webhook.urlstringRequired

The HTTPS URL on your server that will receive events.

webhook.eventsarrayOptional

The events to subscribe to. Specify them as shown in the example.

webhook.byEventsbooleanOptional

Set to false to send all events to the same URL.

webhook.base64booleanOptional

Include media as Base64 when enabled.

webhook.headersobjectOptional

Custom headers for verifying requests on your server.

Verify X-Webhook-Secret before processing the request. Return 200 promptly and handle longer tasks in the background. Deduplicate events using the message ID, event type, and update status. Do not expose API keys or full event payloads in public logs.

Request · cURL
curl --request POST "${BASE_URL}/webhook/set/${INSTANCE}" \
  --header "apikey: ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "webhook": {
        "enabled": true,
        "url": "https://your-app.example/webhooks/whatsflow",
        "byEvents": false,
        "base64": false,
        "headers": {
            "X-Webhook-Secret": "YOUR_WEBHOOK_SECRET"
        },
        "events": [
            "MESSAGES_UPSERT",
            "MESSAGES_UPDATE",
            "CONNECTION_UPDATE"
        ]
    }
}'
Sample response (abridged)201
Response · JSON
{
    "enabled": true,
    "url": "https://your-app.example/webhooks/whatsflow",
    "events": [
        "MESSAGES_UPSERT",
        "MESSAGES_UPDATE",
        "CONNECTION_UPDATE"
    ]
}

Key events

Subscription eventWhen is it sent?
MESSAGES_UPSERTWhen a message is added. Check data.key.fromMe to distinguish incoming from outgoing messages.
MESSAGES_UPDATEWhen a message is updated, including delivery or read status changes when available.
CONNECTION_UPDATEWhen the session connection state changes.
What does an incoming message event look like?

An abridged text message example. Incoming event names use a format such as messages.upsert. The data structure depends on the event and message type.

Incoming event · JSON
{
    "event": "messages.upsert",
    "instance": "my-business",
    "data": {
        "key": {
            "remoteJid": "201000000000@s.whatsapp.net",
            "fromMe": false,
            "id": "EXAMPLE_INCOMING_ID"
        },
        "pushName": "Ahmed",
        "message": {
            "conversation": "When will my order arrive?"
        },
        "messageType": "conversation"
    }
}
Build a reliable integration

Understand the response. Know your next step.

Check both the HTTP status and the error message. Error details may vary with the request and service configuration.

CodeMeaningWhat should you check?
200 / 201Successful requestRead the response. A successful send request does not confirm delivery.
400Invalid requestCheck required fields, phone number formatting, and the media type.
401Authentication failedCheck the value of your apikey header.
403Access deniedCheck that the key has access to the requested session.
404Resource not foundVerify the base URL, request path, and session name.
429Rate limit exceeded, if enabledReduce your request rate and respect Retry-After if returned.
5xxService errorCheck the connection and retain request details for support, excluding secret keys.

Manage your sending

Queue outgoing messages and respect your account limits. If a response is lost, check the result before retrying to avoid sending the same message twice.

Keep conversations welcome

Send messages to people who have agreed to hear from you, and respect opt-out requests. Use a test number before messaging customers.

Start your integration

Ready for your next step?

Contact us for API credentials or help with your integration.

Talk to the Whatsflow team