Connect your WhatsApp bot

WhatsApp stays outside Orkestra: your company keeps its own WhatsApp Business account and its own bot. This guide shows how that bot creates tasks in Orkestra and finds out what changes, using a personal token and webhooks.

How it fits

Orkestra does not send or receive WhatsApp messages, and never pays for them. Your bot does: it is a program of yours that talks to WhatsApp on one side and to Orkestra on the other.

  • From the bot to Orkestra: the bot uses the REST API with a personal token to create a task, comment on it or move it to another column.
  • From Orkestra to the bot: the bot receives a webhook when something changes, and tells the right person from your WhatsApp account.

The snippets below are only examples for you to build your own. They are not Orkestra code or a plugin, and they are in Node.js just to pick one: any language works.

An account for the bot

Give the bot its own member account, with the role and areas it needs and nothing more. What it does is then signed with its name in the history, and a token can never do more than the account that created it.

  1. Invite that account to your organization and give it the role and area it needs.
  2. Signed in as it, create a token under Your settings → AI connections. Choose the REST API, write access to tasks and projects, and limit it to your organization.
  3. Keep the ork_… key: it is shown only once.

A token gets 1000 requests every 15 minutes. To find out about changes, listen to webhooks instead of polling the API.

Create a task from a message

When an order arrives over WhatsApp, the bot creates a task in the right project:

const API = 'https://api.orkestra.team/api/v1';

async function createTask(projectId, title, description) {
  const res = await fetch(`${API}/projects/${projectId}/tasks`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.ORKESTRA_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ title, description, priority: 'MEDIUM' }),
  });
  const { data } = await res.json();
  return data;
}

If you already have the customer’s card in Contacts, the task accepts clientId to link it to that card. To find it, search by the phone number they wrote from, exactly as WhatsApp delivered it (+, spaces or dashes make no difference):

async function findContact(orgId, phone) {
  const res = await fetch(
    `${API}/organizations/${orgId}/agency/clients?phone=${encodeURIComponent(phone)}`,
    { headers: { Authorization: `Bearer ${process.env.ORKESTRA_TOKEN}` } },
  );
  const { data } = await res.json();
  return data; // several cards may share one number
}

With the card found, create the task with its clientId. The search needs at least 4 digits and only returns the cards your token can see.

To add what the customer writes later, comment on the task: POST /tasks/:id/comments with { "content": "…" }. To move it to another column, POST /tasks/:id/move with { "stateId": "…" }.

Receive a webhook

Under Organization settings → Connections → Webhooks create a webhook with your bot’s public address and subscribe it to these events:

  • task.moved: the task changed column (fromState and toState).
  • task.assigned: someone was assigned (addedAssigneeIds).
  • task.overdue: the due date passed and the task is still open.

A webhook with no projects chosen sends only those the whole organization can see. If your orders live in a private or area project, pick it in the webhook (see Which projects it sends).

Each delivery is a POST with JSON like this:

{
  "event": "task.moved",
  "timestamp": "2026-10-20T14:03:11.000Z",
  "organizationId": "…",
  "data": { "projectId": "…", "task": { "id": "…", "title": "…" } }
}

Verify the signature

Each delivery carries the X-Orkestra-Signature header: the HMAC-SHA256, in hexadecimal, of the raw body using your webhook’s secret. Check it before trusting the message. With Express you must read the body raw, unparsed:

import crypto from 'node:crypto';
import express from 'express';

const app = express();

app.post('/orkestra', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = crypto
    .createHmac('sha256', process.env.ORKESTRA_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
  const received = String(req.get('X-Orkestra-Signature') ?? '');

  const a = Buffer.from(expected);
  const b = Buffer.from(received);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.sendStatus(401);
  }

  const event = JSON.parse(req.body.toString('utf8'));
  // Here you tell the customer on WhatsApp, with your own bot.
  console.log(event.event, event.data.task?.title);
  res.sendStatus(200);
});

app.listen(3000);

Answer with a quick 2xx: on a 5xx or a timeout Orkestra retries, and on a 4xx it does not.

What stays on your side

The WhatsApp number, the bot provider, the messages and what they cost are yours. Orkestra only provides the tasks, the API and the webhooks.