ConvoAI
Menu

Integrations

SDKs & integrations

Call ConvoAI from your own code with any HTTP client, or wire it into Zapier, Make and n8n with their built-in webhook and HTTP modules. No extra infrastructure required.

Client libraries#

There are no official SDK packages yet. The API is plain JSON over HTTPS with a Bearer key, so any HTTP client works. The helpers below are small, dependency-light snippets you can paste into your project and adapt.

All examples use the base URL https://convoai.cloud/api/v1/ and read the key from an environment variable. See the API reference for every endpoint.

Python#

A thin wrapper around requests (pip install requests).

python · convoai_client.py
import os

import requests

BASE_URL = "https://convoai.cloud/api/v1"


class ConvoAIError(Exception):
    def __init__(self, status, body):
        super().__init__(f"{status} {body.get('error')}: {body.get('detail')}")
        self.status = status
        self.body = body


class ConvoAI:
    def __init__(self, api_key=None):
        self.session = requests.Session()
        self.session.headers["Authorization"] = f"Bearer {api_key or os.environ['CONVOAI_API_KEY']}"

    def request(self, method, path, **kwargs):
        resp = self.session.request(method, f"{BASE_URL}{path}", timeout=30, **kwargs)
        if resp.status_code == 204:
            return None
        body = resp.json() if resp.content else {}
        if resp.status_code >= 400:
            raise ConvoAIError(resp.status_code, body)
        return body

Chat with an agent

python
client = ConvoAI()

first = client.request("POST", "/agents/42/chat/", json={
    "message": "Do you have availability this Friday?",
})
print(first["reply"])

# Continue the same conversation
follow_up = client.request("POST", "/agents/42/chat/", json={
    "message": "10am works. Book it for Jane Doe.",
    "session_id": first["session_id"],
})

Page through open conversations

python
page = 1
while True:
    data = client.request("GET", "/agents/42/conversations/",
                          params={"status": "open", "page": page})
    for conv in data["results"]:
        print(conv["id"], conv["contact_name"], conv["last_message_at"])
    if not data["next"]:
        break
    page += 1

Add a knowledge document

python
doc = client.request("POST", "/agents/42/knowledge/", json={
    "title": "Shipping policy",
    "doc_type": "text",
    "content": "Standard delivery is 5 to 7 business days…",
})
print(doc["id"], doc["chunk_count"])

To receive events, see the signature verification examples.

JavaScript / TypeScript#

Uses the built-in fetch, so it runs on Node.js 18+ and edge runtimes with no dependencies.

typescript · convoai.ts
const BASE_URL = "https://convoai.cloud/api/v1";

export class ConvoAIError extends Error {
  constructor(public status: number, public body: { error?: string; detail?: string }) {
    super(`${status} ${body.error}: ${body.detail}`);
  }
}

export async function convoai<T = unknown>(
  method: "GET" | "POST" | "PATCH" | "DELETE",
  path: string,
  body?: unknown,
): Promise<T> {
  const res = await fetch(`${BASE_URL}${path}`, {
    method,
    headers: {
      Authorization: `Bearer ${process.env.CONVOAI_API_KEY}`,
      ...(body ? { "Content-Type": "application/json" } : {}),
    },
    body: body ? JSON.stringify(body) : undefined,
  });
  if (res.status === 204) return undefined as T;
  const data = await res.json();
  if (!res.ok) throw new ConvoAIError(res.status, data);
  return data as T;
}

Send a WhatsApp message

typescript
await convoai("POST", "/agents/42/messages/", {
  to: "+15551234567",
  type: "text",
  text: "Hi! Your order #4821 has shipped.",
});

// Outside the 24-hour window, use an approved template
await convoai("POST", "/agents/42/messages/", {
  to: "+15551234567",
  type: "template",
  template_name: "order_shipped",
  template_params: ["4821"],
  language_code: "en_US",
});

Create a contact and tag it

typescript
// Returns 201 for a new contact, 200 if that phone already exists for the agent
const contact = await convoai<{ id: number }>("POST", "/contacts/", {
  agent_id: 42,
  phone: "+15551234567",
  name: "Maria Garcia",
  email: "maria@example.com",
  stage: "prospect",
});

await convoai("POST", `/contacts/${contact.id}/tags/`, { tags: ["vip", "spanish"] });

Receive webhooks in a Next.js route handler

typescript · app/api/webhooks/convoai/route.ts
import crypto from "node:crypto";

export async function POST(req: Request) {
  const raw = Buffer.from(await req.arrayBuffer());
  const header = req.headers.get("x-convoai-signature") ?? "";

  const expected = crypto
    .createHmac("sha256", process.env.CONVOAI_WEBHOOK_SECRET!)
    .update(raw)
    .digest();
  const received = Buffer.from(header.replace(/^sha256=/, ""), "hex");

  if (received.length !== expected.length || !crypto.timingSafeEqual(received, expected)) {
    return Response.json({ error: "Invalid signature" }, { status: 403 });
  }

  const event = req.headers.get("x-convoai-event");
  const payload = JSON.parse(raw.toString("utf8"));
  // ... handle the event
  return Response.json({ received: true });
}

Zapier#

There is no ConvoAI app in the Zapier directory. Use Zapier's built-in Webhooks by Zapier steps instead: a catch hook to receive ConvoAI events, and a request action to call the API.

  1. 1

    Catch ConvoAI events

    Create a Zap whose trigger is Webhooks by Zapier → Catch Hook and copy the URL Zapier gives you.
  2. 2

    Register that URL in ConvoAI

    Add it on your agent's Integrations page in the dashboard, or with POST /agents/{agent_id}/webhooks/, choosing the events you want.
  3. 3

    Call the API from an action

    Add a Webhooks by Zapier action (POST or Custom Request) pointing at a ConvoAI endpoint, with the header Authorization: Bearer YOUR_API_KEY and a JSON body.
Example: when appointment.created arrives, post the appointment to Slack and add a row to a spreadsheet, all in one Zap.

Make#

Make scenarios use the Webhooks → Custom webhook module as a trigger and the HTTP → Make a request module for API calls.

  1. 1

    Add a Custom webhook trigger

    Make generates a unique URL. Register it in ConvoAI on your agent's Integrations page or through the webhooks API.
  2. 2

    Build the scenario

    Chain modules (Google Sheets, a CRM, Slack, email) after the trigger and map fields from the event's data object.
  3. 3

    Call ConvoAI with the HTTP module

    Configure the request as below, then activate the scenario.
make · http module
URL:     https://convoai.cloud/api/v1/agents/42/messages/
Method:  POST
Headers: Authorization: Bearer YOUR_API_KEY
         Content-Type: application/json
Body (raw JSON):
{
  "to": "{{contact.phone}}",
  "type": "text",
  "text": "Hi {{contact.name}}, your appointment is confirmed for {{appointment.date}}."
}

n8n#

In n8n, use the Webhook node to receive events and the HTTP Request node to call the API.

  1. 1

    Create a credential

    Under Credentials → New → Header Auth, set the name to Authorization and the value to Bearer YOUR_API_KEY. Save it as “ConvoAI API”.
  2. 2

    Receive events with a Webhook node

    Add a Webhook node (method POST) as the trigger, copy its production URL and register it in ConvoAI.
  3. 3

    Call the API with HTTP Request nodes

    Select the “ConvoAI API” credential, set the method and URL, and use expressions to pass data from earlier nodes.
Verifying signatures in n8n: compute the HMAC over the raw request body, not over JSON.stringify() of the parsed body. ConvoAI serialises JSON with spaces after : and ,, so re-serialising in JavaScript produces different bytes and the check always fails. Enable the Webhook node's raw body option and hash those bytes, as in the Node.js example.

Other languages#

Every ConvoAI feature is reachable over standard HTTP. Sending a message from PHP, Ruby and Go:

php
<?php
$ch = curl_init('https://convoai.cloud/api/v1/agents/42/messages/');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . getenv('CONVOAI_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'to'   => '+15551234567',
        'type' => 'text',
        'text' => 'Hello from PHP!',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
echo $response['status']; // queued
ruby
require "net/http"
require "json"

uri = URI("https://convoai.cloud/api/v1/agents/42/messages/")
req = Net::HTTP::Post.new(uri, {
  "Authorization" => "Bearer #{ENV.fetch("CONVOAI_API_KEY")}",
  "Content-Type"  => "application/json",
})
req.body = { to: "+15551234567", type: "text", text: "Hello from Ruby!" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts JSON.parse(res.body)["status"] # queued
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

func main() {
	body, _ := json.Marshal(map[string]string{
		"to": "+15551234567", "type": "text", "text": "Hello from Go!",
	})
	req, _ := http.NewRequest("POST", "https://convoai.cloud/api/v1/agents/42/messages/", bytes.NewBuffer(body))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("CONVOAI_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	var result map[string]any
	json.NewDecoder(resp.Body).Decode(&result)
	fmt.Println(resp.StatusCode, result["status"]) // 201 queued
}