API reference

GET /v1/fraud/:id/stream · Stream audio (WebSocket)

A WebSocket for scoring a call from its audio. Send the call's raw audio as binary frames. We transcribe it as it arrives, score what's said, and send score updates back on the same socket. Use this when you have the audio but no transcript, for example from your phone system or Twilio Media Streams.

Note

This is one of a group of endpoints that work together. The setup guide walks through all of them in order. If you already have a transcript, Add what was said is simpler and costs less.

This is billed per minute of audio at the audio price shown above, which includes the transcription.

text
GET wss://api.spoofey.com/v1/fraud/:id/stream

Open it as a WebSocket, with your API key in the Authorization header of the upgrade request. Never put the key in the URL. Up to 2 sockets can stream to one conversation, for example one for each side of the call.

Before you connect

The socket streams into a conversation, so start one first, with nothing said yet, and keep its id:

bash
curl https://api.spoofey.com/v1/fraud \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"start": true, "number": "+14155550199"}'

201 with the conversation. Its id goes in the socket's URL. See Score a conversation for the other fields you can start it with.

Path

Path param Required Type Notes
id Yes string The conversation's id, from starting it with { "start": true }.

Query

Query param Required Type Notes
encoding No string mulaw (default; what phone systems and Twilio send) or linear16 (16-bit little-endian PCM).
sample_rate No number Samples per second, 8000 to 48000. Default 8000.
channels No number 1 or 2. With 2, channel 0 is the remote party and channel 1 the user, so we know who said what. Best for scoring.
speaker No string With channels=1, whose audio this is: remote, user or unknown (default).

Sending

Frame What it does
Binary Raw audio, in the encoding you asked for. Any frame size; 20 ms frames are typical. Stereo is interleaved.
{"type":"utterance","speaker":"user","text":"..."} Adds a line of text, alongside the audio.
{"type":"end"} Ends the conversation, like End a conversation.

Receiving

All server messages are JSON text frames. They are the same events Follow the score live sends, plus ready and error.

type What it means
ready The socket is open. audio says whether audio can be transcribed right now. Carries the current conversation.
utterance A line was transcribed (source: "stt") or sent as text (source: "api").
score The score changed. Carries the whole conversation.
suspended / ended Scoring paused (out of credits) or the conversation is over. The socket closes after ended.
error { "code", "message" }. For example insufficient_credits, or audio_unavailable (send text instead).

Sample client (Node.js)

javascript
import WebSocket from "ws";

const headers = { Authorization: "Bearer " + process.env.SPOOFEY_API_KEY };

// 1. start a conversation for this call, with nothing said yet
const res = await fetch("https://api.spoofey.com/v1/fraud", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ start: true, number: callerNumber }),
});
const conversationId = (await res.json()).id;

// 2. stream the call's audio into it
const ws = new WebSocket(
  "wss://api.spoofey.com/v1/fraud/" + conversationId + "/stream?encoding=mulaw&sample_rate=8000&channels=2",
  { headers }
);

ws.on("message", (raw) => {
  const msg = JSON.parse(raw);
  // 3. warn the person on the line when it's time to
  if (msg.type === "score" && ["warn_user", "end_call"].includes(msg.conversation.recommended_action)) {
    warnUser(msg.conversation.advice);
  }
});

// from your phone system: 8 kHz stereo mu-law, caller left, your user right
phoneAudio.on("data", (chunk) => ws.send(chunk));
phoneAudio.on("end", () => ws.send(JSON.stringify({ type: "end" })));

Upgrade errors

If the socket can't open, the upgrade is refused with a plain HTTP status:

Status When
401 No API key, or not a valid one.
403 The account or network is suspended.
404 No conversation of yours has that id.
409 The conversation has ended.
429 2 sockets are already streaming to this conversation.
Was this helpful?Your answer helps us improve this page.
Still stuck?Ask Spoofey AI about your exact case, or a person on our team will reply by email.
Last modified on October 23, 2026 · 4 min read
Edit