Developers

Build on
what we ship on.

Calls, messages, faxes, recordings, transcripts and contacts through one REST API. Eleven signed webhook events. Keys you make yourself in the portal. Included in every seat.

Quick start

Your first API call.

one request
curl "https://api.vocatech.com/v1/calls?limit=10" \
     -H "Authorization: Bearer YOUR_API_KEY"
the response, trimmed
{
  "calls": [{
    "call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
    "direction": "incoming",
    "status": "answered",
    "extension": "104",
    "extension_name": "Maya Chen",
    "remote_name": "Jordan Reyes",
    "remote_number": "7185550142",
    "group_number": "7185550100",
    "start_time": "2026-09-14T18:02:11.000Z",
    "end_time": "2026-09-14T18:07:28.000Z",
    "duration": 317,
    "journey": [
      { "order": 1, "type": "auto_attendant",
        "extension_name": "Main Menu", "extension": "900",
        "duration": 6, "recording_url": null },
      { "order": 2, "type": "call_center",
        "extension_name": "Billing", "extension": "300",
        "duration": 22, "recording_url": null },
      { "order": 3, "type": "user",
        "extension_name": "Maya Chen", "extension": "104",
        "start_time": "2026-09-14T18:02:39.000Z",
        "end_time": "2026-09-14T18:07:28.000Z",
        "duration": 289,
        "summary": "Jordan asked about the March invoice. Maya sent a corrected copy.",
        "transcription": "Hi Maya, this is Jordan ...",
        "recording_url":
          "https://api.vocatech.com/v1/media/rec_48213907" }
    ]
  }],
  "meta": { "page": 1, "limit": 10,
            "total_pages": 4, "total_calls": 38 }
}

One key in the Authorization header, JSON back. Every call carries the caller, the duration and the routing journey, and each recorded leg its summary, transcript and recording link. Times are UTC. Call the API from your server: it sends no CORS headers, and a key never belongs in a browser or an app.

What you can reach

Twelve surfaces.

Twenty-eight operations, every one Bearer-authenticated and scoped to your company. Lists page with page and limit, up to 500 records a page. Dates default to today in New York time, a timezone parameter overrides, and one request covers up to 366 days.

Calls

GET /v1/calls

Every call with its journey: the menu, the queue, who answered and for how long. A recorded leg adds its summary and transcript.

Messages

GET, POST /v1/messages

Text and WhatsApp history, and texts sent from your own numbers with a dry-run flag. WhatsApp sending is not in the API.

Send queue

GET, DELETE /v1/messages/queue

What an API Messaging key has waiting to go out, in order. Cancel one message, or the whole queue, before it sends.

Faxes

GET, POST /v1/faxes

Fax history on your fax lines, and a PDF of up to 25 pages sent from your own software, with the same dry-run flag so nothing goes out by accident.

Media

GET /v1/media/{id}

Message attachments, call recordings and fax documents, each handed back as a signed link that works for 30 minutes.

Contacts

GET, POST, DELETE /v1/contacts

The names behind Callpop and Reports. Create or update in batches of up to 500, delete, and look up any number in one read.

Callers

GET /v1/callers/{number}

One number’s contacts, its recent calls with who handled them and the AI summary, and its recent texts and WhatsApp messages.

AI agents

GET /v1/agents

Your AI agents, and one outgoing call placed by an agent: a reminder, a confirmation, a callback. One call per request.

Webhooks

/v1/webhooks

Create, update, test and delete endpoints, filter by event, extension or number, and list the deliveries that failed.

Support

POST /v1/support/tickets

Open a ticket with us from your own system. A help desk sync or an automation step posts here, and it lands in our inbox.

Knowledge

GET, POST /v1/knowledge/answer

A question about our service, answered the way our front desk would say it, in one to three sentences. For help desks.

Identity

GET /v1/whoami

The address the API sees you as, and whether this key is locked to a list. Check it before you lock a key to your servers.

The API reads and sends. It does not change call settings such as forwarding or voicemail. Those live in the portal.

Webhooks

Eleven events.
Every one signed.

Create an endpoint in the portal’s Webhooks panel or through the API, pick the events, and filter by extension or number. Answer with a 2xx within five seconds and do the work after. A failed delivery is retried four more times over roughly the next three hours, and failures stay listed at GET /v1/webhooks/failures for seven days. There is no replay, so fill a gap from the call, message and fax lists. A delivery can arrive twice: dedupe on the event id.

verify.mjs
// Verify X-Vocatech-Signature: t=<unix>,v1=<hex>
// rawBody: the body exactly as it arrived, unparsed.
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(
    String(header).split(',').map((p) => p.split('='))
  );
  const t = Number(parts.t);
  if (!t || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - t) > 300) return false;

  const expected = Buffer.from(
    createHmac('sha256', secret)
      .update(`t=${parts.t}.${rawBody}`)
      .digest('hex')
  );
  const given = Buffer.from(parts.v1);
  // timingSafeEqual throws on unequal lengths: check first.
  return given.length === expected.length
    && timingSafeEqual(given, expected);
}
call.startedA call leg starts Within seconds
call.answeredA call leg is answered Within seconds
call.endedA call leg ends Within seconds
call.transcriptionA recorded leg’s summary and transcript are ready Minutes after the call, sometimes hours
message.sentA text sent from the API or the portal goes out Within seconds
message.receivedA text or WhatsApp message arrives Within seconds
message.status_updatedA carrier or WhatsApp reports a delivery status Within seconds
fax.sentAn outgoing fax is logged Within a minute
fax.receivedAn inbound fax is logged Within a minute
fax.deliveredA fax is logged as delivered Within a minute
fax.failedA fax is logged as failed Within a minute

call.transcription is skipped when a transcript is still not ready after six hours or cannot be matched to its call, so do not count on one for every recorded leg. fax.delivered and fax.failed fire only when the result is known as the fax is logged. A result that comes in later does not fire them, so read a fax’s final status from GET /v1/faxes.

Keys, limits and errors

Keys you control.
Limits you can read.

Keys you make yourself
The main key comes from your company’s Integrations page and reaches everything. API Messaging keys, one per integrator, only text.
Locked to your servers
List the exact IPv4 or IPv6 addresses a key may use, no ranges. It is optional on the main key and required on API Messaging keys.
Signed webhooks
HMAC-SHA256 over the timestamp and the raw body, in the X-Vocatech-Signature header. Reject anything older than five minutes.
A counter per kind
Reports, texts, faxes, AI agent calls, tickets and questions each count on their own, per key, and faxes per account. A 429 says which counter filled, and when it resets.
Counter, per keyMinuteHourDay
DefaultEvery other request6003,600100,000
ReportsGET /v1/calls, GET /v1/messages3003,000100,000
Texts, on the main keyPOST /v1/messages20200
Faxes, per accountPOST /v1/faxes350 sent
AI agent callsPOST /v1/agents/{id}/calls10500
Support ticketsPOST /v1/support/tickets10200
Knowledge/v1/knowledge/answer302,000

Each counter runs in fixed windows in UTC, and a refused request counts too. A 429 names the counter and the window, with a Retry-After header in seconds. An API Messaging key is not held to the 20 and 200: its batch is accepted and sent in order at a pace we set per key. A request without a live key is counted per address, 60 a minute and 600 an hour. Faxes count per account: 3 a minute and 50 sent a day, midnight to midnight Eastern, each a PDF of at most 25 pages, and they also stop at the account’s monthly limit, 1,000 by default. The fax API is for sending your own documents, not for marketing or bulk faxing. What metered texting costs is on the pricing page.

When a request fails

StatusWhat it means
400, 422The request is malformed or fails a check, like a window over 366 days, or a fax that is not a PDF or runs over 25 pages. The message names what to fix.
401No key, or a key that is wrong or turned off.
403Outside the key’s scope or its IP list, or an action we refuse, like texting from a number that is not yours.
404, 410Not found, or not yours. A 410 is a file that is no longer available.
409Already done or busy: a queued text already sent or canceled, or a support ticket still being worked. Honor Retry-After.
413A fax document over 20 MB.
429A counter is full. Wait the seconds in the Retry-After header.
502, 503A service behind the API could not do it just now. Try again shortly. A text answered 503 was not sent and is safe to retry.
504A text was not confirmed and may have gone out. Check GET /v1/messages before you retry.

Every error body carries a plain message. The reference shows each one route by route.

Also on the same key

For your AI,
and your help desk.

Caller context for your own AI

GET /v1/callers/{number} hands your assistant the caller’s contacts, recent calls with who handled them and the AI summary, and recent texts, before it says hello. Every read is written to your account’s HIPAA access log.

See it in the reference

Support tickets from your own system

POST /v1/support/tickets opens a ticket with us from a help desk sync, an automation step, or the AI answering agent’s after-message action. Your own reference keeps follow-ups on the same ticket for seven days, and the reply reaches whoever you name.

Read the guide

Start building.

The interactive reference on api.vocatech.com sends real requests to your own account, so use the dry-run flag when you send. The guide walks through concepts, payloads and curl examples. Generate a key on your Integrations page and go.