POST + WSS · AI

AI Voice (Call)

Real-time AI voice astrologer over WebSocket. Audio streams in both directions — sub-second turn-taking, barge-in, multilingual, chart-grounded. Live transcripts stream alongside the audio for both the user and the astrologer, so you can render captions or build a chat log in parallel. Integration has two phases: one REST call to create the session, one WebSocket for the live conversation.

How it works

  1. Phase 1 (REST) — POST birth data to /start (or /match-start for two charts). Server computes the Vedic chart, returns a session_id.
  2. Phase 2 (WebSocket) — connect to wss://starsapi.com/voice-relay-v2, authenticate with the session_id, then exchange audio frames in real time.

The relay handles voice activity detection (VAD), turn-taking, barge-in, language detection, and billing events. Your client captures mic audio and plays back the astrologer’s audio — nothing else to manage.

Phase 1: Create session

Endpoint POST /api/v3/partner/ai/voice/start

Creates a voice session and computes the birth chart. Returns session_id to use in the WebSocket auth frame. Same birth-data fields as chat /start.

Available voice astrologers — single chart: transit_expert, love_guru, transit_expert.

Two-chart sessions

Endpoint POST /api/v3/partner/ai/voice/match-start

For compatibility voice calls. Same person1 / person2 body as chat /match-start. Returns a session_id with both charts loaded. Use person1_name and person2_name in the WebSocket greet frame instead of name.

Phase 2: WebSocket conversation

Relay wss://starsapi.com/voice-relay-v2

Connection flow

  1. Connect to the relay URL.
  2. Send an auth frame with session_id, api_key, name, and lang.
  3. Wait for ready — session is bound, astrologer loaded.
  4. Send greet to trigger the astrologer’s opening response.
  5. Stream mic audio as audio.chunk frames. Play back assistant.audio frames.

Audio format

Same format in both directions: 24 kHz, mono, signed 16-bit little-endian PCM, base64-encoded in the JSON data field.

Client requirements

The relay handles VAD, turn-taking and billing. Your client is responsible for audio capture, playback and session handling — the pieces below are what every integration needs, whatever the platform.

AreaRequirement
Mic permissionAndroid RECORD_AUDIO; iOS NSMicrophoneUsageDescription; web getUserMedia. Request it before creating the session, not mid-call.
Audio sessioniOS: AVAudioSession category playAndRecord with defaultToSpeaker. Android: capture with the VOICE_COMMUNICATION source and request audio focus. Release it on every exit path.
Echo cancellationMust be ON — the platform sources above enable it. Barge-in detection depends on it: without AEC the astrologer’s own voice re-enters the mic and interrupts itself.
Capture24 kHz mono PCM s16le, streamed in ~100–200 ms chunks, base64-encoded per audio.chunk frame. Do not resample on the server side — send 24 kHz.
PlaybackA raw-PCM streaming player that accepts scheduled 24 kHz PCM16 buffers — Web Audio AudioBuffer, Android AudioTrack, iOS AVAudioEngine, or Flutter flutter_pcm_sound. Ordinary file/URL players cannot stream raw chunks. Plan this piece first — it is the only non-trivial dependency in the integration.
Playback schedulingSchedule each chunk at an absolute timeline position (nextStart = max(now, nextStart); play(chunk, at: nextStart); nextStart += chunk.duration). Waiting for the previous chunk to finish produces audible gaps and clicks.
WebSocketA client that keeps the connection open for the whole call. Frames are single-line JSON text — no binary frames, no compression required.
Web: secure contextMicrophone access requires HTTPS (or localhost). On plain HTTP getUserMedia is unavailable and the call cannot start.
Web: capturegetUserMedia({ audio: { sampleRate: 24000, channelCount: 1, echoCancellation: true, noiseSuppression: true } }), then an AudioContext({ sampleRate: 24000 }). Use an AudioWorklet for the capture node — createScriptProcessor is deprecated and glitches under load.
Web: autoplay policyBrowsers create the AudioContext in a suspended state. Call audioContext.resume() inside the click handler that starts the call, otherwise frames arrive and nothing is heard.
During the callKeep the screen awake, default the route to speaker, and follow the OS for wired/Bluetooth headsets. Test both.

Frame reference

All frames are single-line JSON objects with a type field.

Client → Server

TypeFieldsDescription
authsession_id, api_key, name, langFirst frame. Binds the session to the WebSocket.
greetname, langTriggers the astrologer’s opening response. For couples: person1_name, person2_name, lang.
audio.chunkdataOne mic chunk. Base64 PCM (24 kHz mono s16le). Send continuously while user speaks.
interruptCancel the current assistant response. Send when user.speech_started arrives while playback is active.

Server → Client

TypeFieldsDescription
readyastrologer, languageAuth accepted, session bound.
user.speech_startedServer VAD detected the user is speaking.
user.speech_stoppedVAD detected end of user turn.
user.transcripttextTranscript of what the user said.
assistant.speech_startedAstrologer is about to speak. Show speaking indicator.
assistant.audiodataOne chunk of astrologer audio. Base64 PCM. Queue and play in order.
assistant.transcriptdeltaIncremental caption text for the current astrologer turn.
assistant.doneAstrologer finished speaking. Open mic for next turn.
assistant.cancelledBarge-in acknowledged. Previous response stopped.
billing.warningWallet running low. Show a top-up nudge.
billing.exhaustedWallet empty. Session ending — show top-up flow.
errorcode, messageRecoverable or fatal error.

Barge-in

When user.speech_started arrives while you’re still playing assistant audio, stop playback immediately and send {"type":"interrupt"}. The relay replies with assistant.cancelled and starts processing the new user turn.

Billing

Voice sessions use a per-minute meter. An initial charge is debited when the connection is established, then recurring charges every 60 seconds while the session is active. Disconnecting stops the meter. The relay sends billing.warning when balance is getting low and billing.exhausted when the wallet is empty. No webhook wiring needed — handle them inline as WebSocket frames.

Integration checklist

  1. POST to /start (or /match-start) with birth data → save session_id.
  2. Connect to wss://starsapi.com/voice-relay-v2.
  3. Send auth frame → wait for ready.
  4. Send greet → play assistant.audio chunks, render assistant.transcript deltas.
  5. Wait for assistant.done before opening mic (first turn only).
  6. Capture mic at 24 kHz mono s16le, base64-encode, send as audio.chunk frames.
  7. On user.speech_started during playback → stop audio, send interrupt.
  8. Handle billing.warning / billing.exhausted to manage wallet state.

Errors

REST errors follow the same format as chat errors. WebSocket errors arrive as {"type":"error","code":"...","message":"..."} frames.

HTTP / WSCodeCause
400VALIDATION_ERRORMissing/invalid fields or astrologer not available for voice.
400MISSING_FIELDA required field is absent.
400INVALID_SESSIONSession ID not found or expired.
401AUTH_MISSING_KEYNo API key in request or auth frame.
402INSUFFICIENT_BALANCEWallet balance too low to start.
WSbilling.exhaustedWallet empty during session — connection closing.
WSerrorFatal or recoverable error with code and message.

See also