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.
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.
GET wss://api.spoofey.com/v1/fraud/:id/streamOpen 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:
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)
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. |