Streaming AMD as a service

Detect humans vs answering machines
in under one second.

VMskip is a streaming Answering Machine Detection API. Send audio, get a verdict — HUMAN, MACHINE, or NOTSURE — in sub-second time. Three lines of code, no models to deploy, no infrastructure to maintain.

Stop wasting agent minutes on voicemail. Connect your team to real humans, the moment they answer.

Awaiting audio
Confidence
Decision
Round-trip
<1stypical decision time
99.2%accuracy vs human-labeled set
3lines of code to integrate

How it works

Stream raw audio. Get an answer before the recipient finishes speaking.

1. Stream or upload

POST a WAV/MP3 to /v1/analyze or stream PCM frames over WebSocket as the call answers.

2. Real-time inference

A proprietary voice model, state machine, and ASR keyword pipeline — tuned on millions of real dialer calls.

3. Verdict in under a second

HUMAN, MACHINE, or NOTSURE, with confidence and elapsed time. Median 480ms.

4. Skip voicemail. Talk to humans.

Stop burning agent minutes on "leave a message after the beep." Connect your team to real conversations the instant a real person answers.

The API

Standard REST. Bearer token auth. Drop into any language.

curl -X POST https://api.vmskip.com/v1/analyze \
  -H "Authorization: Bearer $VMSKIP_KEY" \
  -H "Content-Type: audio/wav" \
  --data-binary @call-answer.wav
import os, requests

with open("call-answer.wav", "rb") as f:
    r = requests.post(
        "https://api.vmskip.com/v1/analyze",
        headers={
            "Authorization": f"Bearer {os.environ['VMSKIP_KEY']}",
            "Content-Type": "audio/wav",
        },
        data=f.read(),
    )

result = r.json()
print(result["verdict"], result["confidence"])
import { readFile } from "node:fs/promises";

const audio = await readFile("call-answer.wav");

const r = await fetch("https://api.vmskip.com/v1/analyze", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.VMSKIP_KEY}`,
    "Content-Type": "audio/wav",
  },
  body: audio,
});

const result = await r.json();
console.log(result.verdict, result.confidence);
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

type Verdict struct {
    Verdict    string  `json:"verdict"`
    Confidence float64 `json:"confidence"`
    DecisionMs int     `json:"decision_ms"`
}

func main() {
    audio, _ := os.Open("call-answer.wav")
    defer audio.Close()

    req, _ := http.NewRequest("POST", "https://api.vmskip.com/v1/analyze", audio)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("VMSKIP_KEY"))
    req.Header.Set("Content-Type", "audio/wav")

    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()

    var v Verdict
    json.NewDecoder(resp.Body).Decode(&v)
    fmt.Printf("%s (%.2f) in %dms\n", v.Verdict, v.Confidence, v.DecisionMs)
}
<?php
$audio = file_get_contents("call-answer.wav");

$ch = curl_init("https://api.vmskip.com/v1/analyze");
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $audio,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer " . getenv("VMSKIP_KEY"),
        "Content-Type: audio/wav",
    ],
]);

$result = json_decode(curl_exec($ch), true);
echo $result["verdict"] . " " . $result["confidence"] . PHP_EOL;
require "net/http"
require "uri"
require "json"

audio = File.read("call-answer.wav")
uri   = URI("https://api.vmskip.com/v1/analyze")

req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['VMSKIP_KEY']}"
req["Content-Type"]  = "audio/wav"
req.body = audio

res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
result = JSON.parse(res.body)
puts "#{result['verdict']} (#{result['confidence']})"
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;

var key   = Environment.GetEnvironmentVariable("VMSKIP_KEY");
var audio = File.ReadAllBytes("call-answer.wav");

using var http    = new HttpClient();
using var content = new ByteArrayContent(audio);
content.Headers.ContentType = new MediaTypeHeaderValue("audio/wav");
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", key);

var resp   = await http.PostAsync("https://api.vmskip.com/v1/analyze", content);
var json   = await resp.Content.ReadAsStringAsync();
var result = JsonDocument.Parse(json).RootElement;

Console.WriteLine($"{result.GetProperty("verdict")} {result.GetProperty("confidence")}");

Response — same shape regardless of language:

{
  "verdict": "MACHINE",
  "confidence": 0.94,
  "decision_ms": 312,
  "chunks": 124,
  "request_id": "req_a1b2c3..."
}

For real-time streaming, open a WebSocket to wss://api.vmskip.com/v1/stream and send 20ms PCM frames. Get incremental verdicts as confidence rises.

Pricing

Pay only for what you analyze. No minimums.

Free

$0/month
  • 1,000 requests / month
  • REST API
  • Community support
Start free

Growth

$199/month
  • 500,000 requests / month
  • Priority routing
  • 99.9% uptime SLA
  • Slack support
Get Growth

Need more than 500K/month or on-prem deployment? Talk to us about Enterprise.

Get an API key

Closed beta. Drop your email and we'll send you a key within a few hours.