Skip to content
Back to Home

API Documentation

Complete REST API reference for the AIVO Connect platform. Manage calls, contacts, appointments, knowledge base, and business info programmatically.

Base URL

https://aivo.bz/api/v1

Auth

Bearer aivo_...

Format

JSON (application/json)

Overview

The AIVO Connect API allows you to programmatically manage your AI voice assistant. You can list and search call logs, manage contacts, create and update appointments, maintain your knowledge base, and retrieve business information.

All API access requires authentication via API key. You can generate keys with specific scopes from your Settings → API Keys page.

Authentication

All API requests require a Bearer token

Include your API key in the Authorization header of every request.

Authentication header
Authorization: Bearer aivo_sk_your_api_key_here

API keys are prefixed with aivo_sk_ and have scoped permissions. Available scopes:

  • calls:read - Read call logs and transcripts
  • contacts:read / contacts:write - Read and manage contacts
  • appointments:read / appointments:write - Read and manage appointments
  • messages:read / messages:write - Read and send SMS/MMS messages
  • knowledge:read / knowledge:write - Read and manage knowledge base articles
  • business:read - Read business profile information
Example: Authenticate and list calls
curl -s -H 'Authorization: Bearer aivo_sk_your_api_key_here' \
  'https://aivo.bz/api/v1/calls?limit=5'

If the API key is missing or invalid, you'll receive a 401 Unauthorized response:

401 Response
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing or invalid API key"
  }
}

Base URL & Format

All API endpoints are served under /api/v1. Requests and responses use JSON (application/json).

Base URL: https://aivo.bz/api/v1

Content-Type: application/json
Accept: application/json

API Endpoints

The following resources are available:

MethodEndpointDescriptionScope
GET/callsList call logscalls:read
GET/calls/:idGet call detailscalls:read
GET/contactsList contactscontacts:read
POST/contactsCreate a contactcontacts:write
GET/contacts/:idGet contact detailscontacts:read
PATCH/contacts/:idUpdate a contactcontacts:write
DELETE/contacts/:idDelete a contactcontacts:write
GET/appointmentsList appointmentsappointments:read
POST/appointmentsCreate an appointmentappointments:write
GET/appointments/available-slotsGet available time slotsappointments:read
GET/messagesList messagesmessages:read
POST/messagesSend a message (SMS/MMS)messages:write
GET/messages/:idGet message detailsmessages:read
GET/knowledgeList knowledge articlesknowledge:read
POST/knowledgeCreate a knowledge articleknowledge:write
GET/businessGet business profilebusiness:read
GET/openapi.jsonOpenAPI 3.1 specnone

Calls

List and retrieve call logs with optional filtering.

GET /api/v1/calls
curl -s -H 'Authorization: Bearer aivo_sk_...' \
  'https://aivo.bz/api/v1/calls?limit=2&status=completed'
Response 200
{
  "data": [
    {
      "id": "clx1abc...",
      "callerNumber": "+5012279446",
      "from": "+5012279446",
      "to": "+5012001234",
      "direction": "inbound",
      "durationSeconds": 142,
      "status": "completed",
      "summary": "Customer asked about business hours and booked an appointment for Tuesday.",
      "aiConfidenceScore": 0.94,
      "costCents": 12,
      "startedAt": "2026-03-29T10:15:00Z",
      "endedAt": "2026-03-29T10:17:22Z",
      "createdAt": "2026-03-29T10:15:00Z"
    }
  ],
  "meta": {
    "cursor": "clx1abc...",
    "hasMore": true
  }
}

Query parameters:

  • limit - Number of results (1–100, default: 20)
  • cursor - Cursor for pagination
  • status - Filter by status: completed, missed, failed
  • direction - Filter: inbound or outbound

Contacts

Create, list, update, and delete contacts.

POST /api/v1/contacts
curl -s -X POST -H 'Authorization: Bearer aivo_sk_...' \
  -H 'Content-Type: application/json' \
  'https://aivo.bz/api/v1/contacts' \
  -d '{
    "name": "Maria Santos",
    "phone": "+5016123456",
    "email": "maria@example.com",
    "notes": "Prefers morning appointments"
  }'
Response 201
{
  "data": {
    "id": "clx2def...",
    "name": "Maria Santos",
    "phone": "+5016123456",
    "email": "maria@example.com",
    "notes": "Prefers morning appointments",
    "createdAt": "2026-03-29T11:00:00Z",
    "updatedAt": "2026-03-29T11:00:00Z"
  }
}

Appointments

List appointments and check available time slots.

GET /api/v1/appointments/available-slots
curl -s -H 'Authorization: Bearer aivo_sk_...' \
  'https://aivo.bz/api/v1/appointments/available-slots?date=2026-04-01'
Response 200
{
  "data": [
    { "start": "2026-04-01T09:00:00Z", "end": "2026-04-01T09:30:00Z" },
    { "start": "2026-04-01T09:30:00Z", "end": "2026-04-01T10:00:00Z" },
    { "start": "2026-04-01T10:00:00Z", "end": "2026-04-01T10:30:00Z" }
  ]
}

Messages

Send and retrieve SMS/MMS messages through your AIVO phone number. Messages can be sent to contacts or arbitrary phone numbers.

POST /api/v1/messages
curl -s -X POST -H 'Authorization: Bearer aivo_sk_...' \
  -H 'Content-Type: application/json' \
  'https://aivo.bz/api/v1/messages' \
  -d '{
    "to": "+5016001234",
    "body": "Your appointment is confirmed for tomorrow at 10:00 AM.",
    "type": "sms"
  }'
Response 201
{
  "data": {
    "id": "msg_abc123",
    "to": "+5016001234",
    "from": "+5012279446",
    "body": "Your appointment is confirmed for tomorrow at 10:00 AM.",
    "type": "sms",
    "status": "queued",
    "direction": "outbound",
    "createdAt": "2026-04-01T14:30:00Z"
  }
}

To send MMS (multimedia messages), include a mediaUrl field:

POST /api/v1/messages (MMS)
curl -s -X POST -H 'Authorization: Bearer aivo_sk_...' \
  -H 'Content-Type: application/json' \
  'https://aivo.bz/api/v1/messages' \
  -d '{
    "to": "+5016001234",
    "body": "Here is your receipt",
    "type": "mms",
    "mediaUrl": "https://aivo.bz/receipts/inv-001.pdf"
  }'

Retrieve message history with optional filters:

GET /api/v1/messages
curl -s -H 'Authorization: Bearer aivo_sk_...' \
  'https://aivo.bz/api/v1/messages?direction=inbound&limit=20'

Message statuses: queuedsentdelivered (or failed). Inbound messages trigger the message.received webhook event.

Knowledge Base

Manage the articles that train your AI voice agent.

POST /api/v1/knowledge
curl -s -X POST -H 'Authorization: Bearer aivo_sk_...' \
  -H 'Content-Type: application/json' \
  'https://aivo.bz/api/v1/knowledge' \
  -d '{
    "title": "Business Hours",
    "content": "We are open Monday through Friday, 8am to 5pm. Closed on weekends and public holidays.",
    "type": "faq"
  }'

Business Info

Retrieve your business profile and settings.

GET /api/v1/business
curl -s -H 'Authorization: Bearer aivo_sk_...' \
  'https://aivo.bz/api/v1/business'
Response 200
{
  "data": {
    "name": "Casa Maya Restaurant",
    "phone": "+5012279446",
    "timezone": "America/Belize",
    "plan": "professional",
    "businessHours": {
      "monday": { "open": "08:00", "close": "22:00" },
      "tuesday": { "open": "08:00", "close": "22:00" }
    }
  }
}

Webhooks

Real-time event notifications

Configure webhook URLs in your dashboard to receive HTTP POST callbacks when events occur in your account.

Available webhook events:

  • call.completed - Fired when a call ends
  • call.missed - Fired when a call goes unanswered
  • appointment.created - Fired when AIVO AI books an appointment
  • appointment.cancelled - Fired when an appointment is cancelled
  • contact.created - Fired when a new contact is created
  • message.received - Fired when an SMS/MMS is received
Webhook payload example
POST https://your-app.com/webhooks/aivo
Content-Type: application/json
X-AIVO-Signature: ed25519:<base64-signature>
X-AIVO-Timestamp: 1711699200

{
  "event": "call.completed",
  "timestamp": "2026-03-29T12:00:00Z",
  "data": {
    "id": "clx1abc...",
    "direction": "inbound",
    "from": "+5012279446",
    "to": "+5012001234",
    "durationSeconds": 142,
    "status": "completed",
    "summary": "Customer booked an appointment for Tuesday."
  }
}

Webhook Signature Verification

Every webhook request includes an Ed25519 signature in the X-AIVO-Signature header. You should verify this signature to ensure the request originated from AIVO and was not tampered with.

Verification steps:

  1. Get the X-AIVO-Timestamp and X-AIVO-Signature headers from the request
  2. Construct the signed payload: timestamp + "." + raw_body
  3. Verify the Ed25519 signature against the signed payload using your webhook signing public key (available in your dashboard under Settings → Webhooks)
  4. Reject requests where the timestamp is more than 5 minutes old to prevent replay attacks
Node.js verification example
import { verify } from "crypto";

function verifyWebhook(req: Request, publicKey: string): boolean {
  const signature = req.headers.get("X-AIVO-Signature")?.replace("ed25519:", "");
  const timestamp = req.headers.get("X-AIVO-Timestamp");
  const body = await req.text();

  if (!signature || !timestamp) return false;

  // Check timestamp freshness (5 min window)
  const age = Date.now() / 1000 - parseInt(timestamp);
  if (Math.abs(age) > 300) return false;

  // Verify Ed25519 signature
  const payload = timestamp + "." + body;
  return verify(
    null,
    Buffer.from(payload),
    { key: publicKey, format: "pem" },
    Buffer.from(signature, "base64")
  );
}

Rate Limits

Plan-based rate limits

Rate limits are enforced per API key. Higher plans get higher limits.

PlanStandard RequestsBulk Operations
Starter60 req/min10 req/min
Professional100 req/min20 req/min
Enterprise500 req/min100 req/min

Rate limit headers are included in every response:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1711699260

When rate limited, you'll receive a 429 Too Many Requests response with a Retry-After header indicating seconds until the limit resets.

Error Handling

All errors return a consistent JSON format with an error code and human-readable message:

Error response format
{
  "error": {
    "code": "NOT_FOUND",
    "message": "The requested resource was not found"
  }
}
StatusCodeMeaning
400BAD_REQUESTInvalid parameters or malformed request body
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENAPI key lacks required scope
404NOT_FOUNDResource does not exist
429RATE_LIMITEDToo many requests - see Retry-After header
500INTERNAL_ERRORUnexpected server error

Pagination

All list endpoints use cursor-based pagination. Response includes a meta object with pagination info:

{
  "data": [...],
  "meta": {
    "cursor": "clx1abc...",  // Pass as ?cursor= for next page
    "hasMore": true           // false when no more results
  }
}
Paginating through results
# First page
curl -s -H 'Authorization: Bearer aivo_sk_...' \
  'https://aivo.bz/api/v1/calls?limit=20'

# Next page (use cursor from previous response)
curl -s -H 'Authorization: Bearer aivo_sk_...' \
  'https://aivo.bz/api/v1/calls?limit=20&cursor=clx1abc...'