Credufy Voice Documentation

Everything you need to integrate AI voice agents into your app. Credufy Voice handles the full pipeline — speech-to-text, LLM, text-to-speech — so you only write a few lines of code.

Quickstart

Get a voice agent running in under 5 minutes.

1. Create an account

Sign up at voice.credufy.com. You get 50 free minutes every month — no credit card required.

2. Create an API key

Go to API Keys in the dashboard. Click "New API key". Copy the key — it starts with cv_live_ and is shown exactly once.

3. Create an agent

POST https://voice.credufy.com/api/v1/agents
Authorization: Bearer cv_live_xxx
Content-Type: application/json

{
  "name":         "Amara",
  "slug":         "amara_trcn",
  "language":     "en-NG",
  "voiceProvider": "cartesia",
  "voiceId":      "your_cartesia_voice_id",
  "model":        "claude-haiku-4-5",
  "firstMessage": "Hello! I am Amara. Ready to study?",
  "systemPrompt": "You are Amara, a warm TRCN exam
    tutor. Keep responses short. Use Nigerian English."
}

4. Start a session

POST https://voice.credufy.com/api/v1/sessions/create
Authorization: Bearer cv_live_xxx
Content-Type: application/json

{
  "agentId": "your_agent_id",
  "userId":  "your_user_id"
}

// Response:
{
  "sessionId": "...",
  "transport": "livekit",
  "livekit": {
    "url":      "wss://....livekit.cloud",
    "roomName": "voice-...",
    "token":    "eyJ..."
  },
  "expiresAt": "2026-08-12T10:05:00.000Z",
  "agent": {
    "name":         "Amara",
    "firstMessage": "Hello! I am Amara..."
  }
}

5. Connect via SDK

npm install @credufy/voice-sdk
import { CredufyVoice } from '@credufy/voice-sdk'

// Your backend calls /v1/sessions/create and returns
// the WHOLE response to the browser. Pass it verbatim —
// the SDK picks the best transport it contains (WebRTC
// via LiveKit, with a WebSocket fallback).

const voice = new CredufyVoice({
  session,   // the /v1/sessions/create response, as-is
  onReady:      (s)   => console.log('Session ready', s),
  onTranscript: (t)   => setCaption(t.text),        // caller speech
  onToken:      (tok) => appendAgentText(tok),      // agent reply text
  onStatus:     (st)  => setStatus(st),             // listening|thinking|speaking
  onAudio:      (a)   => setSpeaking(a === 'playing'),
  onEnd:        (sum) => console.log('Ended', sum),
  onError:      (err) => console.error(err),
})

await voice.start()

// When done:
voice.stop()

// Interrupt the agent mid-speech:
voice.interrupt()
Note: Session credentials expire in 5 minutes. Create the session immediately before the user clicks start, and never cache them across sessions.

Authentication

All API requests require a Bearer API key in the Authorization header.

Authorization: Bearer cv_live_xxxxxxxxxxxxxxxxxxxx

Keys starting with cv_live_ are production keys. Keys starting with cv_test_ are test keys that do not consume billable minutes. Create and manage keys in your dashboard under API Keys.

Note: API keys are hashed with bcrypt and never stored in plain text. If you lose a key, revoke it and create a new one.

Your first agent

An agent is a configured voice persona. It has a name, a language, a voice (Cartesia for the lowest latency, or ElevenLabs), an LLM model, and a system prompt that defines its personality and knowledge.

Agent fields

{
  "name":          "string  — display name e.g. 'Amara'",
  "slug":          "string  — unique ID e.g. 'amara_trcn'",
  "language":      "en-NG | pcm | ha | yo | ig",
  "voiceProvider": "cartesia | elevenlabs",
  "voiceId":       "string  — provider voice ID",
  "model":         "claude-haiku-4-5 | claude-sonnet-4-6",
  "firstMessage":  "string  — what agent says first",
  "systemPrompt":  "string  — the agent's personality",
  "isPublic":      "boolean — appear in marketplace"
}

Writing a good system prompt

The system prompt is the most important field. A few rules specific to voice:

// GOOD — short, conversational, specific
"You are Amara, a TRCN exam tutor. Keep every
response to 2-3 sentences. Use Nigerian English
naturally. After explaining, ask one question."

// BAD — too long, uses markdown, lists
"You are Amara. Your responsibilities are:
1. Help students prepare for TRCN
2. Explain concepts clearly
3. Provide feedback..."

Sessions API

POST /v1/sessions/create

// Request
{
  "agentId":  "string (required)",
  "userId":   "string (required) — your user ID",
  "metadata": "object (optional) — session context, see below"
}

// Response 201
{
  "sessionId": "string",
  "transport": "livekit",
  "livekit": {
    "url":      "wss://....livekit.cloud",
    "roomName": "string",
    "token":    "JWT (expires in 5 minutes)"
  },
  "wsUrl":     "wss://... (legacy WebSocket fallback)",
  "expiresAt": "ISO datetime",
  "agent": {
    "id":           "string",
    "name":         "string",
    "firstMessage": "string"
  },
  "usage": { "minutesUsed": 0, "minutesIncluded": 120 }
}

Session metadata — context and overrides

Anything you put in metadata is injected into the agent as session context: the agent reads it as part of its instructions for that one call. Two keys are treated as per-session overrides — this is how you run fully dynamic agents (a different prompt per user, per role, per lesson) from a single agent config:

{
  "agentId": "...",
  "userId":  "user_42",
  "metadata": {
    // Overrides — replace the agent's stored config
    // for THIS session only:
    "systemPromptOverride": "You are a mock interviewer
      for a Senior PM role at TechCorp...",
    "firstMessage": "Hi Ada — ready for your interview?",

    // Enforced by the platform:
    "maxSeconds": 600,

    // Everything else becomes context the agent can use:
    "roleTitle": "Senior Product Manager",
    "questions": ["Tell me about...", "How would you..."]
  }
}
Note: Overrides make one agent serve unlimited personas — the pattern platforms call transient assistants. Voice, transcriber and language still come from the agent config.

GET /v1/sessions/:id

// Response 200
{
  "session": {
    "id":             "string",
    "agentId":        "string",
    "externalUserId": "string",
    "status":         "active | ended | error",
    "durationSec":    "number | null",
    "transcript":     "array | null",
    "costUsd":        "number | null",
    "latency":        "object | null — per-turn EOU/LLM/TTS ms, p50/p95",
    "startedAt":      "ISO datetime",
    "endedAt":        "ISO datetime | null",
    "region":         "string",
    "agent": { "name": "string", "slug": "string" }
  }
}

Agents API

GET    /v1/agents           List all agents
POST   /v1/agents           Create agent
GET    /v1/agents/:id       Get agent (includes systemPrompt)
PATCH  /v1/agents/:id       Update agent
DELETE /v1/agents/:id       Soft-delete agent

API Keys

Manage the keys your app uses to authenticate with the Credufy Voice API. Keys are created and revoked from the dashboard — there is no public API endpoint for key management, since keys authenticate the API itself.

GET    /v1/keys      List keys (prefix only — full key never returned again)
POST   /v1/keys      Create a key — { name, environment: "live" | "test" }
DELETE /v1/keys/:id  Revoke a key
Note: The full key is only ever shown once, at creation. If you lose it, revoke it and create a new one — there is no way to retrieve a lost key.

Usage API

GET /v1/usage?from=2026-08-01&to=2026-08-07

// Response 200
{
  "usage": {
    "sessions": 42,
    "minutes":  183.5,
    "costUsd":  4.96,
    "byDate":  [{ "date": "2026-08-01",
                  "sessions": 8, "minutes": 34.2, ... }],
    "byAgent": [{ "agentId": "...",
                  "sessions": 42, "minutes": 183.5, ... }]
  }
}

Webhooks

Credufy Voice fires events to your configured endpoints when sessions start and end.

Available events

session.started    — fired when WebSocket connects
session.ended      — fired when session ends (has transcript)
transcript.final   — fired on each final transcript chunk

Payload

{
  "event":       "session.ended",
  "createdAt":   "ISO datetime",
  "sessionId":   "string",
  "agentId":     "string",
  "userId":      "string",
  "durationSec": 120,
  "costUsd":     0.054,
  "region":      "jnb"
}

Verifying signatures

// Node.js
import crypto from 'crypto'

function verifyWebhook(
  rawBody:   string,
  signature: string,
  secret:    string,
): boolean {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  return `sha256=${expected}` === signature
}

// In your route handler:
const sig = req.headers['x-credufy-sig-256']
const ok  = verifyWebhook(rawBody, sig, webhookSecret)
if (!ok) return res.status(401).end()

SDK Reference

Installation

npm install @credufy/voice-sdk

Configuration

const voice = new CredufyVoice({
  // Preferred: the whole /v1/sessions/create response.
  // The SDK selects WebRTC (LiveKit) when present and
  // falls back to the WebSocket gateway otherwise.
  session:  CreateSessionResponse,

  // Legacy alternative (gateway only):
  wsUrl?:   string,

  // Callbacks (all optional)
  onReady:      (s: { sessionId: string; firstMessage: string }) => void
  onTranscript: (t: { text: string; final: boolean }) => void   // caller speech
  onToken:      (token: string) => void                          // agent reply text stream
  onStatus:     (s: 'connecting'|'listening'|'thinking'|'speaking'|'ended') => void
  onAudio:      (a: 'playing'|'idle') => void                    // agent audio state
  onEnd:        (summary: { sessionId?: string; duration?: number }) => void
  onError:      (error: Error | Event) => void
})

Methods

voice.start()      // Open mic, connect WS, start session
voice.stop()       // End session cleanly
voice.interrupt()  // Stop AI mid-speech, return to listening

Nigerian language support

Credufy Voice is the only voice AI platform with native support for Nigerian languages. Set the language field on your agent to control STT (speech recognition) and TTS (speech synthesis) behaviour.

"language": "en-NG"  // Nigerian English (default)
"language": "pcm"   // Nigerian Pidgin English
"language": "ha"    // Hausa
"language": "yo"    // Yoruba
"language": "ig"    // Igbo

Code-switching

Real Nigerian conversations mix languages naturally. Set language to en-NG and include Pidgin or local phrases in your system prompt — the STT engine handles code-switching automatically.

// System prompt for natural Nigerian English
"Speak in warm Nigerian English. Use Pidgin phrases
naturally where they fit — 'oya', 'make we', 'no worry',
'e easy'. Do not force it. Sound like a real person."

// The agent will naturally produce:
// "Oya, let us look at Chapter 3.
//  This one no hard at all — make we start."
Note: Full Hausa, Yoruba and Igbo STT models are in training. Contact hello@credufy.com to join the early access programme for your target language.