Complete API reference

Everything needed to build with Rabbitt Voice API v1.0.0: create credentials, configure agents, run phone calls or interviews, collect reports, handle failures, and take the integration to production. The endpoint catalog below contains all 26 currently supported operations.

Start here

All public operations use JSON over HTTPS and are relative to this base URL:

Base URL
https://api.rabbitt.ai/api/v1
  1. An organization administrator creates a key in the API keys workspace. Key management is a dashboard operation; API keys cannot mint more API keys.
  2. Store the one-time plaintext value in a server-side secret manager.
  3. Choose only the scopes required by the workflow.
  4. Call GET /usage to confirm credits, agent capacity, and concurrent-call limits before accepting production work.
  5. Create one reusable agent, then create calls or interview sessions from it.
  6. Poll resource and report endpoints until asynchronous work is complete.
Verify the key and organization
export RABBITT_API_KEY="rb_live_xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export RABBITT_API_BASE="https://api.rabbitt.ai/api/v1"

curl "$RABBITT_API_BASE/usage" \
  -H "Authorization: Bearer $RABBITT_API_KEY" \
  -H "Accept: application/json"

Authentication and scopes

Send the API key in the Authorization header on every request. A key belongs to exactly one organization, and access is the intersection of its scopes and the current permissions of its owner.

Required header
Authorization: Bearer rb_live_xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Scopes used by public v1

ScopeCapabilityOperations
agents:readList and retrieve agentsGET /agents, GET /agents/{id}
agents:manageCreate, update, and delete agentsPOST /agents, PATCH/DELETE /agents/{id}
executions:readRead calls, interviews, transcripts, reports, and create interview sessionsCall read routes and every interview route
campaigns:managePlace or end calls and manage campaign statePOST /calls, POST /calls/{id}/hangup, every campaign route
organization:readRead credits and quotasGET /usage

Use separate least-privilege keys per service and environment. Keys beginning withrb_test_ and rb_live_ are visibly distinguishable, but the prefix alone is not a simulation guarantee: a test key can still mutate data or place a call when accepted by a configured environment. Use a dedicated test organization, credits, and destination numbers for staging.

Embed origins

If a key will mint interview embed tokens, register every exact browser origin on the key, such as https://app.example.com. Paths are ignored. HTTPS is required except for localhost development, and an empty allowlist denies token creation.

Request conventions

  • Send and accept application/json.
  • Resource IDs are 24-character hexadecimal strings.
  • Phone numbers use E.164, for example +919876543210.
  • Timestamps are ISO 8601 UTC strings.
  • Unknown JSON fields are rejected on strict create operations.
  • List routes use page and limit; defaults are 1 and 25, and the maximum limit is 100.
  • Persist the returned id. Use externalRef for your own candidate, order, ticket, or job identifier where supported.

Pagination envelope

List response
{
  "object": "list",
  "dataType": "call",
  "data": [],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 0,
    "totalPages": 0,
    "hasMore": false
  }
}

Available filters are type for agents; agentId andstatus for calls; externalRef and status for interviews; and agentId and status for campaigns.

A minimal server client

rabbitt.js
const baseUrl = process.env.RABBITT_API_BASE ?? "https://api.rabbitt.ai/api/v1";

export async function rabbitt(path, init = {}) {
  const response = await fetch(baseUrl + path, {
    ...init,
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${process.env.RABBITT_API_KEY}`,
      ...(init.body ? { "Content-Type": "application/json" } : {}),
      ...init.headers,
    },
  });

  const body = await response.json().catch(() => ({}));
  if (!response.ok) {
    const error = new Error(body.error?.message ?? `Rabbitt HTTP ${response.status}`);
    error.status = response.status;
    error.code = body.error?.code;
    error.param = body.error?.param;
    error.requestId = body.request_id;
    throw error;
  }
  return body;
}

End-to-end phone-call workflow

1. Create a reusable phone agent

Create an outbound agent
const agent = await rabbitt("/agents", {
  method: "POST",
  body: JSON.stringify({
    type: "phone",
    name: "Appointment reminder",
    instructions:
      "Call {{customerName}} to confirm the appointment. Be concise and polite.",
    language: "english",
    phone: {
      direction: "outbound",
      greeting: "Hello, this is Bright Dental calling about your appointment.",
      voicemailBehavior: "mark_no_answer",
      maxAttempts: 2,
      retryDelayMinutes: 60
    }
  })
});

console.log(agent.id);

Provider overrides are optional. When omitted, the server uses the configured LLM, STT, and TTS defaults. Keep an agent reusable and pass recipient-specific values as call variables.

2. Check credit and concurrency

Preflight
const usage = await rabbitt("/usage");

if (usage.credits.remainingMinutes <= 0) {
  throw new Error("Rabbitt organization has no remaining credit minutes");
}

3. Place the call

Dial one recipient
const call = await rabbitt("/calls", {
  method: "POST",
  body: JSON.stringify({
    agentId: agent.id,
    phoneNumber: "+919876543210",
    contactName: "Asha Menon",
    externalRef: "booking-8842",
    variables: { customerName: "Asha Menon" }
  })
});

console.log(call.id, call.status);

The request returns after the carrier accepts dialing, not after the conversation. A call moves through created, active, andcompleted. To stop an active call, sendPOST /calls/{id}/hangup.

4. Wait for the report

Poll asynchronous analysis
export async function waitForCallReport(callId, timeoutMs = 15 * 60_000) {
  const deadline = Date.now() + timeoutMs;
  const baseUrl = process.env.RABBITT_API_BASE ?? "https://api.rabbitt.ai/api/v1";

  while (Date.now() < deadline) {
    const response = await fetch(`${baseUrl}/calls/${callId}/report`, {
      headers: { Authorization: `Bearer ${process.env.RABBITT_API_KEY}` }
    });

    if (response.status === 200) return response.json();
    if (response.status !== 202) {
      const body = await response.json().catch(() => ({}));
      throw new Error(body.error?.code ?? `Rabbitt HTTP ${response.status}`);
    }
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }

  throw new Error(`Timed out waiting for call ${callId}`);
}

End-to-end interview workflow

1. Create a voice interview agent

Create an interview agent
const interviewAgent = await rabbitt("/agents", {
  method: "POST",
  body: JSON.stringify({
    type: "voice",
    mode: "interview",
    name: "Customer support interview",
    instructions:
      "Interview the candidate about customer support experience. Ask one question at a time.",
    language: "english",
    maxDurationMinutes: 20,
    voice: {
      goal: "Assess communication and problem-solving",
      evaluationCriteria: ["clarity", "empathy", "problem solving"]
    }
  })
});

2. Create one interview per candidate

Create a pre-authorized interview
const interview = await rabbitt("/interviews", {
  method: "POST",
  body: JSON.stringify({
    agentId: interviewAgent.id,
    candidateName: "Asha Menon",
    candidateEmail: "asha@example.com",
    mode: "voice",
    expiresInHours: 72,
    externalRef: "candidate-2188"
  })
});

// Hosted flow: send interview.interviewUrl to the candidate.
console.log(interview.interviewUrl);

3A. Use the hosted interview

Send the returned interviewUrl to the candidate. The URL contains only a candidate-scoped capability, never your API key. Poll GET /interviews/{id}for created, active, or completed.

3B. Or embed it in your application

Register your browser origins on the API key, then mint a token server-side shortly before rendering the interview:

Server: mint a short-lived embed token
const embed = await rabbitt(`/interviews/${interview.id}/embed-token`, {
  method: "POST",
  body: JSON.stringify({ expiresInSeconds: 900 })
});

// Return only embed.token (or embed.embedUrl) to your authenticated page.
// Never return RABBITT_API_KEY.
return { token: embed.token, interviewId: interview.id };
Browser: mount the interview
<div id="rabbitt-interview" style="min-height: 680px"></div>
<script src="https://voice.rabbitt.ai/embed.js"></script>
<script>
  const session = RabbittInterview.mount(
    document.getElementById("rabbitt-interview"),
    {
      token: EMBED_TOKEN_FROM_YOUR_SERVER,
      interviewId: INTERVIEW_ID_FROM_YOUR_SERVER,
      onEvent(event) {
        if (event.type === "session.ended") {
          console.log("Report id", event.payload.reportId);
        }
      }
    }
  );

  // Optional controls: session.start(), end(), mute(), unmute(), setTheme("dark")
</script>

The loader validates both message origin and iframe identity and handles resizing. See the embed protocol guide for every event payload and a framework-free iframe implementation.

4. Read the interview report

Poll GET /interviews/{id}/report. It returns 202 while analysis is pending and 200 when ready. Add ?includeTranscript=true when the same response should include the turn-by-turn transcript.

Campaign workflow

Campaigns provide paced bulk calling with retry and concurrency settings. The public API can create, inspect, update, launch, pause, resume, cancel, and archive campaigns.

Create a draft campaign
const campaign = await rabbitt("/campaigns", {
  method: "POST",
  body: JSON.stringify({
    name: "January overdue invoices",
    agentId: agent.id,
    timezone: "Asia/Kolkata",
    settings: {
      retryLimit: 3,
      retryDelayMinutes: 60,
      concurrency: 5
    }
  })
});

Valid actions are launch, pause, resume,cancel, and archive. Invalid state transitions return 409. Read stats.total, pending, completed, andfailed from GET /campaigns/{id}.

Polling, transcripts, and reports

Public API v1 is polling-based; it does not currently define partner webhooks. Poll every few seconds with bounded timeouts and stop when the resource is completed or a report request returns 200.

NeedOperationReady signal
Call stateGET /calls/{id}status: completed
Call transcriptGET /calls/{id}/transcriptTurns appear as the call progresses
Call reportGET /calls/{id}/reportHTTP 200; HTTP 202 means pending
Interview stateGET /interviews/{id}status: completed
Interview reportGET /interviews/{id}/reportHTTP 200; use includeTranscript=true

A report can include an outcome, summary, captured fields, sentiment, evaluation scores, or phone dispositions depending on agent type and configuration. Treat fields not relevant to that report family as absent. Do not assume a report exists merely because the call or interview has ended.

Errors and retries

Every public failure uses this envelope:

Error response
{
  "error": {
    "type": "invalid_request_error",
    "code": "VALIDATION_ERROR",
    "message": "phoneNumber is required",
    "param": "body.phoneNumber"
  },
  "request_id": "req_01..."
}

Branch first on HTTP status or error.type, then on the stableerror.code. Show message to developers, not end users, and include request_id when contacting support. Never log authorization headers, embed tokens, transcripts, or sensitive request bodies.

StatusRetry policyAction
400Do not retry unchangedFix the field named by error.param, when present.
401Do not retryReplace a missing, malformed, expired, or revoked API key.
402Do not retryAdd organization credit before placing another call.
403Do not retryGrant the required scope or correct organization access.
404Do not retry blindlyVerify the resource ID and organization.
409Reconcile firstResolve a duplicate name or invalid campaign transition.
429Retry with backoffHonor Retry-After when present and add jitter.
5xx/networkRetry safe readsReconcile mutations before retrying; v1 has no idempotency-key contract.

Rate limits, credits, and quotas

  • Rate limits are per API key in one-minute windows.
  • The default is 120 requests per minute; administrators can configure a key.
  • HTTP 429 uses rate_limit_error and code RATE_LIMITED.
  • Credits are shared organization minutes. Call creation can return HTTP 402.
  • GET /usage returns remaining credits plus maxAgents,maxUsers, and maxConcurrentCalls.

Cache usage briefly for display, but treat the call-creation response as authoritative because concurrent workloads can consume credit or capacity between preflight and execution.

Complete endpoint catalog

This catalog is generated from the committed OpenAPI contract. Select an operation for exact path/query/body fields, response statuses, and cURL, Node.js, and Python samples.

Agents

Voice and phone agents — the reusable definition of who the AI is and what it should accomplish.

Calls

Outbound and inbound telephony calls placed by a phone agent.

Interviews

Candidate interview sessions, including embeddable ones.

Campaigns

Bulk outbound calling over a list of recipients.

Usage

Credit balance and organization quotas.

Production checklist

  • Create separate least-privilege keys per application and environment.
  • Store keys in a secret manager and exercise zero-downtime rotation.
  • Use a dedicated safe organization, credits, and phone numbers for staging.
  • Keep API calls on your server; send only short-lived embed tokens to browsers.
  • Register exact embed origins and verify microphone permissions on HTTPS.
  • Validate E.164 numbers and every declared agent variable before dialing.
  • Bound polling, apply jittered backoff, and respect per-key rate limits.
  • Reconcile timed-out mutations before retrying to prevent duplicate calls.
  • Monitor credit and concurrent-call capacity with GET /usage.
  • Log status, error code, and request ID only; redact credentials and conversation data.
  • Test 401, 402, 403, 404, 409, 429, timeout, revocation, and partial-provider failure paths.
  • Confirm legal consent, calling windows, recording, retention, and data-handling requirements for every destination.

OpenAPI document

The machine-readable OpenAPI 3.1 document is public and served by the API. Use it for client generation and contract checks, but keep the workflow and retry rules from this guide in your application design.

OpenAPI 3.1
https://api.rabbitt.ai/api/v1/openapi.json

For focused background, see Authentication, Errors, Rate limits, and the interview embed guide.

Dashboard Welcome