Live calls

Create Live Call Session

Start a live voice call with a companion: returns a one-time WebSocket URL your client (a browser too) connects to, without ever seeing your API key.

spicy-live-1: the caller talks, the persona answers in a natural voice, and interruptions are handled, over one WebSocket (wss://api.spicyapi.com/v1/realtime, see Live Call WebSocket). Set the persona and voice here; the call itself follows the OpenAI Realtime event shape.

spicy-live-2 is the highest-quality live call: the role-play model spicy-companion-1 writes every reply (it stays in the scene and moves it forward), spoken by Spicy Voice 3 voices that act the emotion (Bella Bright, Roger, Sarah, Laura, Charlie, George, Callum, River, Harry, Liam, Alice, Matilda, Will, Jessica, Eric Smooth, Chris, Brian, Daniel, Lily, Adam, Bill, default Sarah), with turn-taking and interruptions handled for you. Same WebSocket events and audio formats as spicy-live-1. It takes language (en, zh, de, it, pt, es, ja, ko, fr, ru, default English) and no turn_detection. Billed at $0.08 per minute of call time (by the second) plus the reply tokens at $1.00 in, $2.80 out per 1M tokens; each charge arrives as a spicy.usage event. Opening a session needs a balance of at least $0.10.

The ticket in client_secret.value works once, within 60 seconds. Create the session on your server with your key and hand only the returned url to the browser. A call lasts up to 780 seconds per session; open a new session to continue.

Billed per turn from the tokens each reply used, per 1M tokens: text in $0.46, audio in $1.86, text out $1.40, audio out $3.74. Audio counts about 7 tokens per second in and 12.5 out, and the conversation so far is billed again as input on each turn, which comes to about 1 to 1.5 cents per minute of steady back-and-forth (measured on real calls, Oct 2026; less when the line is quiet). Opening a session needs a balance of at least $0.05; when the balance or your spend limit runs out mid-call, the call ends with a payment_required error event.

The persona in instructions is screened like a prompt before the session is created (422 when blocked). During the call both sides' transcripts are screened; a violation ends the call with a content_blocked error event. No custom or cloned voices, no camera or image input, no tools or web search. Sandbox keys get a session whose socket answers with canned events and bills nothing. Calls appear in the request log as type realtime with seconds, turns and total cost.

POST/v1/realtime/sessionsTry it
Create Live Call Session
cURL
curl --request POST \
  --url https://api.spicyapi.com/v1/realtime/sessions \
  --header 'Authorization: Bearer $SPICYAPI_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "spicy-live-1",
    "voice": "Serena",
    "instructions": "You are Mara, 29, a playful bartender on a late-night call with the user. Flirt, tease, keep replies short.",
    "turn_detection": { "type": "server_vad", "silence_duration_ms": 600 }
  }'
200
JSON
{
  "id": "rt_5c2e8a1f9d3b7e4a",
  "object": "realtime.session",
  "model": "spicy-live-1",
  "voice": "Serena",
  "turn_detection": { "type": "server_vad", "silence_duration_ms": 600 },
  "max_seconds": 780,
  "input_audio": "pcm16 mono 16 kHz, base64 in input_audio_buffer.append",
  "output_audio": "pcm16 mono 24 kHz, base64 in response.audio.delta",
  "client_secret": { "value": "rts_9f1b3d5e7a2c4e6f8a0b", "expires_at": 1758553260 },
  "url": "wss://api.spicyapi.com/v1/realtime?session=rts_9f1b3d5e7a2c4e6f8a0b"
}

Authorizations

Authorizationstringheaderrequired

Bearer authentication header of the form Bearer <token>, where <token> is your SpicyAPI key (sk-spicy-…). Create one in the dashboard under API Keys.

Body

application/json
modelstring

spicy-live-1 (the default) or spicy-live-2 (highest quality).

voicestring

The voice that answers (case-insensitive), default Tina: Tina, Cindy, Liora Mira, Serena, Maia, Mia, Katerina, Jennifer, Sonrisa, Hana, Griet, Sigga, Bea, Chloe, Kiki, Sohee, Zane, Ryan, Raymond, Theo Calm, Aiden, Andre, Dolce, Bodega, Jakub, Alek, Emilien, Evan.

instructionsstring

The persona and how to behave on the call, up to 8,000 characters. Defaults to a flirty, sexually open adult companion who leans into explicit talk when the caller wants it, takes the lead now and then, and keeps replies short.

languagestring

spicy-live-2 only: the language of the call, a two-letter code (en, zh, de, it, pt, es, ja, ko, fr, ru). Defaults to English. A 400 on spicy-live-1, which detects the language itself.

turn_detectionobject | null

spicy-live-1 only (a 400 on spicy-live-2, which takes turns by itself). When the persona replies. Default { "type": "server_vad" }: it answers when the caller stops talking. semantic_vad waits for a finished thought. Optional threshold (-1 to 1) and silence_duration_ms (200 to 6000). null is push-to-talk: send input_audio_buffer.commit and response.create yourself.

userstring

Your own id for the end user making this request (up to 128 characters; send an opaque id, not an email). Send it if your product serves many people: declined-prompt history, strikes and suspensions are then kept per end user, so one person's behaviour never affects another's requests or your account. After 10 severe violations that user gets 403 end_user_suspended; the id is echoed back as user in every screening error so you can act on it. It is stored with the requests it was sent on, so DELETE /v1/end-users/{user} can erase that person's data.

Response

200 · application/json

Session

idstringrequired

Session id, rt_....

objectstringrequired

Always realtime.session.

modelstringrequired

The model.

voicestringrequired

The voice that answers.

turn_detectionobject | nullrequired

The turn detection in effect.

max_secondsintegerrequired

Longest call on this session.

input_audiostringrequired

What to send: PCM16 mono 16 kHz, base64, in input_audio_buffer.append.

output_audiostringrequired

What comes back: PCM16 mono 24 kHz, base64, in response.audio.delta.

client_secretobjectrequired

The one-time ticket.

urlstringrequired

The WebSocket URL with the ticket, ready to open.

Was this page helpful?