API-Referenz

Alle Endpunkte der API v1. Beispiele in curl, JavaScript (fetch) und Python (requests); die gewählte Sprache gilt für die ganze Seite.

Basis-URLhttps://hubvocal.com/v1
AuthAuthorization: Bearer vt_live_…
Rate-Limit120 Anfragen/Min. pro Schlüssel · 429 + Retry-After
Scopesread · write · calls
Jeder Schlüssel hat read, write und/oder calls. read deckt GET-Anfragen ab, write Änderungen, calls ausgehende Anrufe. Eine Anfrage außerhalb der Scopes des Schlüssels erhält 403.
Fehler-Body{"detail": "..."}
OpenAPIGET /v1/openapi.json

Zu Authentifizierung, Einbettung und Fehlercodes siehe Entwickler.

Agenten

Die Gespräche laufen im Textmodus. Getestet werden also Anweisungen und Tool-Nutzung, nicht Stimme oder Latenz. Simulationen starten Sie im Dashboard; einen /v1-Endpunkt dafür gibt es noch nicht.

Agenten auflisten

GET /v1/agents

Gibt alle Agenten Ihrer Organisation in der Reihenfolge des Dashboards zurück.

Anfrage

curl
curl "https://hubvocal.com/v1/agents" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "id": "front-desk",
    "name": "Front desk",
    "lang": "en",
    "engine": "live",
    "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
    "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
    "voice": {
      "voice": "marin",
      "speed": 1
    },
    "tools": {
      "builtins": [
        "end_call",
        "take_message"
      ],
      "webhooks": [
        "tl_8f3a2c"
      ]
    },
    "turn": {
      "first_speaker": "agent",
      "idle_check_s": 30
    },
    "recording": {
      "enabled": false,
      "announce": true
    },
    "post_call": {
      "summary": true,
      "fields": [
        {
          "name": "appointment_date",
          "type": "date",
          "description": "Requested appointment date, if any"
        },
        {
          "name": "callback",
          "type": "boolean",
          "description": "Does the caller want a callback?"
        }
      ]
    },
    "knowledge": {
      "doc_ids": [
        "kb_7d21e4"
      ],
      "mode": "tool"
    },
    "published_version": 3,
    "draft_changed": false
  }
]

Agenten erstellen

POST /v1/agents

Erstellt einen Agenten. Jedes Feld wird auf dem Server validiert; Werte über den Limits werden gekürzt. Übergeben Sie eine bereits vorhandene id, schlägt die Anfrage mit 409 fehl. Zum Aktualisieren verwenden Sie PUT.

NameOrtTypBeschreibung
id body string Optional. Kleinbuchstaben, Ziffern und Bindestriche, bis zu 48 Zeichen. Wird ohne Angabe aus dem Namen erzeugt.
name
Pflicht
body string Anzeigename, bis zu 60 Zeichen.
lang
Pflicht
body string Code der Gesprächssprache, z. B. tr, en, de. Die vollständige Liste liefert GET /v1/voices.
engine
Pflicht
body "live" | "gemini" | "realtime" | "classic" live: GPT-Live 1, gemini: Gemini Live, realtime: OpenAI Realtime, classic: STT → LLM → TTS.
instructions body string Systemanweisungen, bis zu 8000 Zeichen.
greeting body string Was der Agent zuerst sagt, bis zu 400 Zeichen.
voice body object voice (ein Name aus /v1/voices), speed (nur classic und realtime; bei live und gemini fest auf 1.0), tone (Sprechstil als Freitext, bis zu 600 Zeichen).
tools body object builtins (end_call, take_message) und webhooks (Tool-ids); insgesamt bis zu 16 Tools. Leer oder nicht angegeben heißt: keine Tools. mcp: [{server_id, tools}] fügt Tools aus Ihren MCP-Servern hinzu; sie zählen zum selben Limit.
turn body object Einstellungen zum Sprecherwechsel: sensitivity (low, balanced, high; nur classic-Engine), first_speaker (agent oder caller), silence_wait_s (1–5), idle_check_s (0 oder 10–120), agent_timeout_s (0 oder 10–60). Leere Felder verwenden die Standardwerte.
recording body object recording: {enabled (Standard false), announce (Standard true), announce_text?}. Ist sie eingeschaltet, kündigt der Agent die Aufzeichnung vor der Begrüßung an.
post_call body object post_call.summary: beim Anrufende eine Zusammenfassung schreiben (Standard true). post_call.fields: bis zu 24 Felder, die nach dem Anruf ausgefüllt werden ({name, type, description, enum?, required?}).
knowledge body object doc_ids (bis zu 50 Dokumente aus der Wissensdatenbank) und mode ("tool"). Der Agent erhält dann das Tool search_knowledge.
calendar body object integration_id und calendar_id aus dem Dashboard, duration_min (15–240), buffer_min (0–60), timezone, working_hours, min_notice_h (0–72), max_days_ahead (1–90). Aktiviert die Termin-Tools.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/agents" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  }
}'

Antwort · 201

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "published_version": null,
  "draft_changed": true
}

Fehler

  • 409 Ein Agent mit dieser id existiert bereits.

Agenten abrufen

GET /v1/agents/{id}

Gibt einen einzelnen Agenten zurück. published_version ist die Nummer der Live-Version (null, wenn er noch nie veröffentlicht wurde), und draft_changed zeigt, ob der Entwurf davon abweicht.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.

Anfrage

curl
curl "https://hubvocal.com/v1/agents/front-desk" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "published_version": 3,
  "draft_changed": false
}

Fehler

  • 404 Kein Agent mit dieser id.

Agenten aktualisieren

PUT /v1/agents/{id}

Ersetzt den Agenten durch das gesendete Objekt. Senden Sie das vollständige Objekt: Ausgelassene Felder erhalten ihre Standardwerte. Die id im Pfad hat Vorrang vor einer id im Body.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.
name
Pflicht
body string Anzeigename, bis zu 60 Zeichen.
lang
Pflicht
body string Code der Gesprächssprache, z. B. tr, en, de. Die vollständige Liste liefert GET /v1/voices.
engine
Pflicht
body "live" | "gemini" | "realtime" | "classic" live: GPT-Live 1, gemini: Gemini Live, realtime: OpenAI Realtime, classic: STT → LLM → TTS.
instructions body string Systemanweisungen, bis zu 8000 Zeichen.
greeting body string Was der Agent zuerst sagt, bis zu 400 Zeichen.
voice body object voice (ein Name aus /v1/voices), speed (nur classic und realtime; bei live und gemini fest auf 1.0), tone (Sprechstil als Freitext, bis zu 600 Zeichen).
tools body object builtins (end_call, take_message) und webhooks (Tool-ids); insgesamt bis zu 16 Tools. Leer oder nicht angegeben heißt: keine Tools. mcp: [{server_id, tools}] fügt Tools aus Ihren MCP-Servern hinzu; sie zählen zum selben Limit.
turn body object Einstellungen zum Sprecherwechsel: sensitivity (low, balanced, high; nur classic-Engine), first_speaker (agent oder caller), silence_wait_s (1–5), idle_check_s (0 oder 10–120), agent_timeout_s (0 oder 10–60). Leere Felder verwenden die Standardwerte.
recording body object recording: {enabled (Standard false), announce (Standard true), announce_text?}. Ist sie eingeschaltet, kündigt der Agent die Aufzeichnung vor der Begrüßung an.
post_call body object post_call.summary: beim Anrufende eine Zusammenfassung schreiben (Standard true). post_call.fields: bis zu 24 Felder, die nach dem Anruf ausgefüllt werden ({name, type, description, enum?, required?}).
knowledge body object doc_ids (bis zu 50 Dokumente aus der Wissensdatenbank) und mode ("tool"). Der Agent erhält dann das Tool search_knowledge.
calendar body object integration_id und calendar_id aus dem Dashboard, duration_min (15–240), buffer_min (0–60), timezone, working_hours, min_notice_h (0–72), max_days_ahead (1–90). Aktiviert die Termin-Tools.

Anfrage

curl
curl -X PUT "https://hubvocal.com/v1/agents/front-desk" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "cedar",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  }
}'

Antwort · 200

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "cedar",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "published_version": 3,
  "draft_changed": true
}

Fehler

  • 404 Kein Agent mit dieser id. Erstellen Sie ihn zuerst mit POST.

Agenten löschen

DELETE /v1/agents/{id}

Löscht den Agenten. Eine Organisation behält immer mindestens einen Agenten, daher schlägt das Löschen des letzten fehl.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.

Anfrage

curl
curl -X DELETE "https://hubvocal.com/v1/agents/front-desk" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "deleted": "front-desk"
}

Fehler

  • 400 Dies ist der letzte Agent der Organisation.
  • 404 Kein Agent mit dieser id.

Versionen auflisten

GET /v1/agents/{id}/versions

Die veröffentlichten Versionen des Agenten, neueste zuerst. is_live markiert die Version, die Anrufe derzeit verwenden.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.

Anfrage

curl
curl "https://hubvocal.com/v1/agents/front-desk/versions" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "version": 3,
    "note": "Shorter greeting",
    "published_at": 1793829000,
    "published_by": "ayse@example.com",
    "is_live": true
  },
  {
    "version": 2,
    "note": "Added price list",
    "published_at": 1793740000,
    "published_by": "ayse@example.com",
    "is_live": false
  }
]

Fehler

  • 404 Kein Agent mit dieser id.

Version abrufen

GET /v1/agents/{id}/versions/{n}

Der vollständige Agent im Stand dieser Version.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.
n
Pflicht
path integer Versionsnummer.

Anfrage

curl
curl "https://hubvocal.com/v1/agents/front-desk/versions/2" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "version": 2
}

Fehler

  • 404 Agent oder Version existiert nicht.

Entwurf veröffentlichen

POST /v1/agents/{id}/publish

Speichert den aktuellen Entwurf als neue Version und schaltet sie live. Bereits laufende Anrufe behalten ihre Version.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.
note body string Eine kurze Notiz, was sich geändert hat.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/agents/front-desk/publish" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "note": "Shorter greeting"
}'

Antwort · 200

JSON
{
  "version": 4
}

Fehler

  • 404 Kein Agent mit dieser id.

Zurücksetzen

POST /v1/agents/{id}/rollback

Kopiert eine frühere Version in den Entwurf und veröffentlicht sie als neue Version.

NameOrtTypBeschreibung
id
Pflicht
path string Agent-id, z. B. front-desk.
version
Pflicht
body integer Die Version, die wiederhergestellt werden soll.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/agents/front-desk/rollback" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "version": 2
}'

Antwort · 200

JSON
{
  "version": 5
}

Fehler

  • 404 Agent oder Version existiert nicht.

Wissensdatenbank

Dokumente auflisten

GET /v1/knowledge

Die Dokumente Ihrer Organisation mit Verarbeitungsstatus, Größe, Anzahl der Abschnitte und den Agenten, die sie verwenden.

Anfrage

curl
curl "https://hubvocal.com/v1/knowledge" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "id": "kb_7d21e4",
    "title": "Price list 2026",
    "kind": "file",
    "filename": "price-list-2026.pdf",
    "url": null,
    "size_bytes": 248113,
    "chunks": 42,
    "status": "ready",
    "error": null,
    "created_at": 1793740000,
    "used_by": [
      "front-desk"
    ]
  }
]

Dokument hinzufügen

POST /v1/knowledge

Laden Sie eine Datei als multipart/form-data hoch (Feld file), senden Sie Text als JSON {title, text} oder eine einzelne Webseite als JSON {url}. Gibt 201 mit Status processing zurück; fragen Sie das Dokument ab, bis es ready oder failed ist.

NameOrtTypBeschreibung
file body file multipart/form-data: pdf, docx, txt, md oder html, bis zu 10 MB.
title body string Titel, zusammen mit text.
text body string Inhalt als reiner Text.
url body string Alternativ eine einzelne https-Seite, die abgerufen wird.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/knowledge" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Opening hours",
  "text": "We are open 09:00–18:00 on weekdays and 10:00–14:00 on Saturdays. Closed on Sundays."
}'

Antwort · 201

JSON
{
  "id": "kb_9f03b1",
  "title": "Opening hours",
  "kind": "text",
  "filename": null,
  "url": null,
  "size_bytes": 96,
  "chunks": 0,
  "status": "processing",
  "error": null,
  "created_at": 1793740000,
  "used_by": []
}

Fehler

  • 400 Nicht unterstützter Dateityp, Datei größer als 10 MB, URL ohne https oder mit privater Adresse, oder das Limit der Organisation (200 Dokumente, 200 MB) ist erreicht.

Dokument abrufen

GET /v1/knowledge/{id}

Das Dokument mit einer Vorschau seiner ersten 2000 Zeichen.

NameOrtTypBeschreibung
id
Pflicht
path string Dokument-id.

Anfrage

curl
curl "https://hubvocal.com/v1/knowledge/kb_7d21e4" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "id": "kb_7d21e4",
  "title": "Price list 2026",
  "kind": "file",
  "filename": "price-list-2026.pdf",
  "url": null,
  "size_bytes": 248113,
  "chunks": 42,
  "status": "ready",
  "error": null,
  "created_at": 1793740000,
  "used_by": [
    "front-desk"
  ],
  "preview": "Price list 2026. Check-up 1,500 TRY, scale and polish 2,000 TRY…"
}

Fehler

  • 404 Kein Dokument mit dieser id.

Dokument löschen

DELETE /v1/knowledge/{id}

Löscht das Dokument und entfernt es aus allen Agenten, die es verwendet haben.

NameOrtTypBeschreibung
id
Pflicht
path string Dokument-id.

Anfrage

curl
curl -X DELETE "https://hubvocal.com/v1/knowledge/kb_7d21e4" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "deleted": "kb_7d21e4"
}

Fehler

  • 404 Kein Dokument mit dieser id.

Suchen

POST /v1/knowledge/search

Führt dieselbe Suche aus wie der Agent und gibt die am besten passenden Abschnitte mit einem Score zurück. Hilfreich, um Ihre Dokumente vor dem Livegang zu prüfen.

NameOrtTypBeschreibung
query
Pflicht
body string Wonach gesucht werden soll.
doc_ids body string[] Die Suche auf diese Dokumente beschränken.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/knowledge/search" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "query": "how much is a scale and polish"
}'

Antwort · 200

JSON
[
  {
    "doc_id": "kb_7d21e4",
    "title": "Price list 2026",
    "chunk_index": 3,
    "text": "Scale and polish: 2,000 TRY, about 30 minutes.",
    "score": 0.82
  }
]

Tools

Integrierte Tools

Diese Tools brauchen keine Definition. Schalten Sie sie in tools.builtins des Agenten ein. search_knowledge kommt hinzu, sobald knowledge gesetzt ist. Die Termin-Tools kommen hinzu, sobald calendar gesetzt ist.

NameFunktion
end_callDer Agent verabschiedet sich und legt 0,75 s nach dem Ende seiner Äußerung auf. Spricht der Anrufer in der Zwischenzeit, wird das Auflegen abgebrochen. Im Anrufprotokoll steht ended_by: "agent".
take_messageNimmt name, phone, message und callback_requested auf und schreibt sie in outcomes[] des Anrufprotokolls. Eine Bestätigung wird nicht abgefragt.
search_knowledgeWird automatisch hinzugefügt, wenn dem Agenten in knowledge Dokumente zugeordnet sind. Durchsucht sie und hält die Quellen im Anrufprotokoll fest.
check_availabilityLesend. Liefert freie Zeitfenster zwischen date_from und date_to innerhalb der Arbeitszeiten des Agenten. Wird hinzugefügt, wenn calendar gesetzt ist.
book_appointmentSchreibend, mit Bestätigungsschritt. Bucht start für name und phone, optional mit einer note. Die Buchung landet in outcomes[].
cancel_appointmentSchreibend, mit Bestätigungsschritt. Storniert eine Buchung anhand ihrer booking_ref.

Kalender-Integrationen (Google Calendar) werden ausschließlich im Dashboard verbunden; dafür gibt es keinen /v1-Endpunkt. Tragen Sie die Integrations- und Kalender-ids aus dem Dashboard im Feld calendar des Agenten ein.

Tools auflisten

GET /v1/tools

Die Webhook-Tools Ihrer Organisation. Das Secret wird nie zurückgegeben; has_secret zeigt, ob eines gesetzt ist.

Anfrage

curl
curl "https://hubvocal.com/v1/tools" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "id": "tl_8f3a2c",
    "name": "check_order",
    "description": "Looks up the shipping status of an order by its number.",
    "kind": "read",
    "url": "https://crm.example.com/hooks/order",
    "parameters": {
      "type": "object",
      "properties": {
        "order_id": {
          "type": "string",
          "description": "Order number"
        }
      },
      "required": [
        "order_id"
      ]
    },
    "timeout_s": 8,
    "enabled": true,
    "has_secret": true,
    "created_at": 1793830000,
    "updated_at": 1793830000
  }
]

Tool abrufen

GET /v1/tools/{id}

Ein einzelnes Webhook-Tool. Das Secret wird nie zurückgegeben.

NameOrtTypBeschreibung
id
Pflicht
path string Tool-id.

Anfrage

curl
curl "https://hubvocal.com/v1/tools/tl_8f3a2c" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "id": "tl_8f3a2c",
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 8,
  "enabled": true,
  "has_secret": true,
  "created_at": 1793830000,
  "updated_at": 1793830000
}

Fehler

  • 404 Kein Tool mit dieser id.

Tool erstellen

POST /v1/tools

Legt ein Webhook-Tool für die Organisation an. Um es zu nutzen, tragen Sie seine id in tools.webhooks eines Agenten ein. Die URL muss https verwenden und darf nicht auf eine lokale oder private Adresse zeigen.

NameOrtTypBeschreibung
name
Pflicht
body string Kleinbuchstaben, Ziffern und Unterstriche, beginnend mit einem Buchstaben (3–41 Zeichen). Eindeutig in der Organisation; end_call und take_message sind reserviert.
description
Pflicht
body string Sagt dem Modell, wann und wie es das Tool verwenden soll.
kind
Pflicht
body "read" | "write" read läuft sofort; write lässt den Anrufer zuerst bestätigen.
url
Pflicht
body string Ihr Endpunkt. Nur https; lokale und private Adressen werden abgelehnt.
parameters body object JSON-Schema-Objekt: bis zu 20 Felder vom Typ string, number, integer oder boolean (enum erlaubt).
timeout_s body integer 2 bis 15 Sekunden.
enabled body boolean Deaktivierte Tools werden dem Modell nicht angeboten.
secret body string Dient zum Signieren der Anfragen. Nur schreibbar; beim Aktualisieren behält ein leerer Wert das aktuelle Secret, "-" entfernt es.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/tools" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 8,
  "enabled": true,
  "secret": "whsec_2b7f…"
}'

Antwort · 201

JSON
{
  "id": "tl_8f3a2c",
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 8,
  "enabled": true,
  "has_secret": true,
  "created_at": 1793830000,
  "updated_at": 1793830000
}

Fehler

  • 400 Ein Feld verstößt gegen die Regeln: Namensformat, https-URL, private Adresse, mehr als 20 Parameter oder Timeout außerhalb des zulässigen Bereichs.
  • 409 Ein Tool mit diesem Namen existiert bereits, oder der Name ist reserviert.

Tool aktualisieren

PUT /v1/tools/{id}

Ersetzt das Tool durch das gesendete Objekt. Lassen Sie secret leer oder weg, um das aktuelle zu behalten; senden Sie "-", um es zu entfernen.

NameOrtTypBeschreibung
id
Pflicht
path string Tool-id.
name
Pflicht
body string Kleinbuchstaben, Ziffern und Unterstriche, beginnend mit einem Buchstaben (3–41 Zeichen). Eindeutig in der Organisation; end_call und take_message sind reserviert.
description
Pflicht
body string Sagt dem Modell, wann und wie es das Tool verwenden soll.
kind
Pflicht
body "read" | "write" read läuft sofort; write lässt den Anrufer zuerst bestätigen.
url
Pflicht
body string Ihr Endpunkt. Nur https; lokale und private Adressen werden abgelehnt.
parameters body object JSON-Schema-Objekt: bis zu 20 Felder vom Typ string, number, integer oder boolean (enum erlaubt).
timeout_s body integer 2 bis 15 Sekunden.
enabled body boolean Deaktivierte Tools werden dem Modell nicht angeboten.
secret body string Dient zum Signieren der Anfragen. Nur schreibbar; beim Aktualisieren behält ein leerer Wert das aktuelle Secret, "-" entfernt es.

Anfrage

curl
curl -X PUT "https://hubvocal.com/v1/tools/tl_8f3a2c" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 10,
  "enabled": true,
  "secret": ""
}'

Antwort · 200

JSON
{
  "id": "tl_8f3a2c",
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 10,
  "enabled": true,
  "has_secret": true,
  "created_at": 1793830000,
  "updated_at": 1793833600
}

Fehler

  • 400 Ein Feld verstößt gegen die Regeln: Namensformat, https-URL, private Adresse, mehr als 20 Parameter oder Timeout außerhalb des zulässigen Bereichs.
  • 404 Kein Tool mit dieser id.

Tool löschen

DELETE /v1/tools/{id}

Löscht das Tool und entfernt es aus allen Agenten, die es verwendet haben.

NameOrtTypBeschreibung
id
Pflicht
path string Tool-id.

Anfrage

curl
curl -X DELETE "https://hubvocal.com/v1/tools/tl_8f3a2c" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "deleted": "tl_8f3a2c"
}

Fehler

  • 404 Kein Tool mit dieser id.

Tool testen

POST /v1/tools/{id}/test

Sendet eine echte Anfrage mit den angegebenen Argumenten an die URL des Tools und gibt Status, benötigte Zeit und bis zu 4 KB des Antwort-Bodys zurück.

NameOrtTypBeschreibung
id
Pflicht
path string Tool-id.
arguments body object Beispielargumente passend zu parameters.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/tools/tl_8f3a2c/test" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "arguments": {
    "order_id": "A-10234"
  }
}'

Antwort · 200

JSON
{
  "ok": true,
  "status": 200,
  "ms": 412,
  "body": "{\"order_id\":\"A-10234\",\"status\":\"shipped\",\"eta\":\"2026-11-07\"}"
}

Fehler

  • 404 Kein Tool mit dieser id.

MCP-Server

MCP-Server auflisten

GET /v1/mcp-servers

Die MCP-Server Ihrer Organisation mit Status und synchronisierten Tools. auth_set zeigt, ob ein Secret gespeichert ist; das Secret selbst wird nie zurückgegeben.

Anfrage

curl
curl "https://hubvocal.com/v1/mcp-servers" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "id": "mcp_2b8e41",
    "name": "crm",
    "url": "https://mcp.example.com/mcp",
    "transport": "streamable_http",
    "auth": "bearer",
    "auth_set": true,
    "enabled": true,
    "status": "ok",
    "error": null,
    "tools_synced_at": 1793831000,
    "tools": [
      {
        "name": "find_customer",
        "description": "Find a customer by phone number.",
        "input_schema": {
          "type": "object",
          "properties": {
            "phone": {
              "type": "string"
            }
          },
          "required": [
            "phone"
          ]
        },
        "enabled": true,
        "access": "read"
      },
      {
        "name": "create_ticket",
        "description": "Open a support ticket.",
        "input_schema": {
          "type": "object",
          "properties": {
            "subject": {
              "type": "string"
            },
            "body": {
              "type": "string"
            }
          },
          "required": [
            "subject"
          ]
        },
        "enabled": false,
        "access": "write"
      }
    ]
  }
]

MCP-Server hinzufügen

POST /v1/mcp-servers

Speichert den Server und ruft seine Tool-Liste ab. Neue Tools sind ausgeschaltet. Bis zu 10 Server pro Organisation.

NameOrtTypBeschreibung
name
Pflicht
body string Kurzname; wird als Präfix in Tool-Namen verwendet (<name>.<tool>).
url
Pflicht
body string Der MCP-Endpunkt des Servers. Nur https; lokale und private Adressen werden abgelehnt.
transport body string streamable_http (Standard) oder sse.
auth body string none, bearer oder header.
secret body string Token oder Header-Wert. Wird verschlüsselt gespeichert und nie zurückgegeben; "-" entfernt ihn.
header_name body string Name des Headers, wenn auth header ist.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/mcp-servers" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "auth": "bearer",
  "secret": "sk_live_…"
}'

Antwort · 201

JSON
{
  "id": "mcp_2b8e41",
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable_http",
  "auth": "bearer",
  "auth_set": true,
  "enabled": true,
  "status": "ok",
  "error": null,
  "tools_synced_at": 1793831000,
  "tools": [
    {
      "name": "find_customer",
      "description": "Find a customer by phone number.",
      "input_schema": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string"
          }
        },
        "required": [
          "phone"
        ]
      },
      "enabled": false,
      "access": "write"
    },
    {
      "name": "create_ticket",
      "description": "Open a support ticket.",
      "input_schema": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "enabled": false,
      "access": "write"
    }
  ]
}

Fehler

  • 400 Die URL ist nicht https oder zeigt auf eine private Adresse, oder die Tool-Liste des Servers konnte nicht abgerufen werden.
  • 409 Die Organisation hat bereits 10 MCP-Server.

MCP-Server aktualisieren

PUT /v1/mcp-servers/{id}

Ändert Name, URL, Authentifizierung oder Aktivierung sowie, welche Tools eingeschaltet sind und ob sie read oder write sind. Senden Sie secret: "-", um das Secret zu entfernen.

NameOrtTypBeschreibung
id
Pflicht
path string id des MCP-Servers.
name body string Kurzname; wird als Präfix in Tool-Namen verwendet (<name>.<tool>).
url body string Der MCP-Endpunkt des Servers. Nur https; lokale und private Adressen werden abgelehnt.
enabled body boolean Ein deaktivierter Server wird Agenten nicht angeboten.
auth body string none, bearer oder header.
secret body string Token oder Header-Wert. Wird verschlüsselt gespeichert und nie zurückgegeben; "-" entfernt ihn.
tools body object[] [{name, enabled, access}] pro Tool; access ist read oder write.

Anfrage

curl
curl -X PUT "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "tools": [
    {
      "name": "find_customer",
      "enabled": true,
      "access": "read"
    },
    {
      "name": "create_ticket",
      "enabled": true,
      "access": "write"
    }
  ]
}'

Antwort · 200

JSON
{
  "id": "mcp_2b8e41",
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable_http",
  "auth": "bearer",
  "auth_set": true,
  "enabled": true,
  "status": "ok",
  "error": null,
  "tools_synced_at": 1793831000,
  "tools": [
    {
      "name": "find_customer",
      "description": "Find a customer by phone number.",
      "input_schema": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string"
          }
        },
        "required": [
          "phone"
        ]
      },
      "enabled": true,
      "access": "read"
    },
    {
      "name": "create_ticket",
      "description": "Open a support ticket.",
      "input_schema": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "enabled": true,
      "access": "write"
    }
  ]
}

Fehler

  • 400 Die URL ist nicht https oder zeigt auf eine private Adresse, oder die Tool-Liste des Servers konnte nicht abgerufen werden.
  • 404 Kein MCP-Server mit dieser id.

MCP-Server löschen

DELETE /v1/mcp-servers/{id}

Löscht den Server und entfernt seine Tools aus allen Agenten.

NameOrtTypBeschreibung
id
Pflicht
path string id des MCP-Servers.

Anfrage

curl
curl -X DELETE "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "deleted": "mcp_2b8e41"
}

Fehler

  • 404 Kein MCP-Server mit dieser id.

Tools synchronisieren

POST /v1/mcp-servers/{id}/sync

Ruft die Tool-Liste erneut ab. Neu hinzugekommene Tools sind ausgeschaltet, access steht auf write.

NameOrtTypBeschreibung
id
Pflicht
path string id des MCP-Servers.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/sync" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "id": "mcp_2b8e41",
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable_http",
  "auth": "bearer",
  "auth_set": true,
  "enabled": true,
  "status": "ok",
  "error": null,
  "tools_synced_at": 1793831000,
  "tools": [
    {
      "name": "find_customer",
      "description": "Find a customer by phone number.",
      "input_schema": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string"
          }
        },
        "required": [
          "phone"
        ]
      },
      "enabled": true,
      "access": "read"
    },
    {
      "name": "create_ticket",
      "description": "Open a support ticket.",
      "input_schema": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "enabled": false,
      "access": "write"
    }
  ]
}

Fehler

  • 400 Die URL ist nicht https oder zeigt auf eine private Adresse, oder die Tool-Liste des Servers konnte nicht abgerufen werden.
  • 404 Kein MCP-Server mit dieser id.

Tool testen

POST /v1/mcp-servers/{id}/test

Ruft ein Tool des Servers mit den angegebenen Argumenten auf und gibt die Dauer, bis zu 4 KB Inhalt und die Angabe zurück, ob das Tool einen Fehler gemeldet hat.

NameOrtTypBeschreibung
id
Pflicht
path string id des MCP-Servers.
tool
Pflicht
body string Name des aufzurufenden Tools.
arguments body object Argumente für das Tool, passend zu seinem input_schema.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/test" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "tool": "find_customer",
  "arguments": {
    "phone": "+905321234567"
  }
}'

Antwort · 200

JSON
{
  "ok": true,
  "ms": 236,
  "content": "{\"customer_id\":\"C-1042\",\"name\":\"Ayşe Yılmaz\",\"open_tickets\":0}",
  "is_error": false
}

Fehler

  • 404 Kein MCP-Server mit dieser id.

Webhooks

Webhooks auflisten

GET /v1/webhooks

Die Webhooks Ihrer Organisation mit dem Ergebnis ihrer letzten Zustellung. Das Secret wird hier nie zurückgegeben; secret_set zeigt, ob eines gesetzt ist.

Anfrage

curl
curl "https://hubvocal.com/v1/webhooks" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "id": "wh_3c9d1e",
    "url": "https://crm.example.com/hooks/voice",
    "events": [
      "call.ended"
    ],
    "enabled": true,
    "secret_set": true,
    "created_at": 1793830000,
    "last_delivery": {
      "status": "ok",
      "at": 1793832440.2,
      "http_status": 200
    }
  }
]

Webhook erstellen

POST /v1/webhooks

Abonniert Ereignisse für eine URL. Derzeit gibt es nur das Ereignis call.ended. Bis zu 5 Webhooks pro Organisation. Lassen Sie secret weg, wird eines erzeugt und nur in dieser Antwort zurückgegeben.

NameOrtTypBeschreibung
url
Pflicht
body string Ihr Endpunkt. Nur https; lokale und private Adressen werden abgelehnt.
events
Pflicht
body string[] Zu empfangende Ereignisse. Derzeit ["call.ended"].
enabled body boolean Deaktivierte Webhooks erhalten nichts.
secret body string Secret zum Signieren. Wird ohne Angabe erzeugt und nur einmal zurückgegeben.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/webhooks" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://crm.example.com/hooks/voice",
  "events": [
    "call.ended"
  ]
}'

Antwort · 201

JSON
{
  "id": "wh_3c9d1e",
  "url": "https://crm.example.com/hooks/voice",
  "events": [
    "call.ended"
  ],
  "enabled": true,
  "secret_set": true,
  "created_at": 1793830000,
  "last_delivery": null,
  "secret": "whsec_9QmZ…"
}

Fehler

  • 400 Die URL verwendet kein https, zeigt auf eine private Adresse, oder ein Ereignis ist unbekannt.
  • 409 Die Organisation hat bereits 5 Webhooks.

Webhook aktualisieren

PUT /v1/webhooks/{id}

Ändert URL, Ereignisse oder Aktivierungsstatus. Senden Sie secret: "-", um ein neues Secret zu erzeugen; es wird in der Antwort zurückgegeben.

NameOrtTypBeschreibung
id
Pflicht
path string Webhook-id.
url body string Ihr Endpunkt. Nur https; lokale und private Adressen werden abgelehnt.
events body string[] Zu empfangende Ereignisse. Derzeit ["call.ended"].
enabled body boolean Deaktivierte Webhooks erhalten nichts.
secret body string "-" erzeugt ein neues Secret. Weglassen, um das aktuelle zu behalten.

Anfrage

curl
curl -X PUT "https://hubvocal.com/v1/webhooks/wh_3c9d1e" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": false
}'

Antwort · 200

JSON
{
  "id": "wh_3c9d1e",
  "url": "https://crm.example.com/hooks/voice",
  "events": [
    "call.ended"
  ],
  "enabled": false,
  "secret_set": true,
  "created_at": 1793830000,
  "last_delivery": {
    "status": "ok",
    "at": 1793832440.2,
    "http_status": 200
  }
}

Fehler

  • 400 Die URL verwendet kein https, zeigt auf eine private Adresse, oder ein Ereignis ist unbekannt.
  • 404 Kein Webhook mit dieser id.

Webhook löschen

DELETE /v1/webhooks/{id}

Löscht den Webhook. Ausstehende Zustellungen werden verworfen.

NameOrtTypBeschreibung
id
Pflicht
path string Webhook-id.

Anfrage

curl
curl -X DELETE "https://hubvocal.com/v1/webhooks/wh_3c9d1e" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "deleted": "wh_3c9d1e"
}

Fehler

  • 404 Kein Webhook mit dieser id.

Webhook testen

POST /v1/webhooks/{id}/test

Sendet ein Beispielereignis call.ended an die URL und gibt Status, benötigte Zeit und Antwort-Body zurück.

NameOrtTypBeschreibung
id
Pflicht
path string Webhook-id.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/webhooks/wh_3c9d1e/test" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "ok": true,
  "http_status": 200,
  "ms": 184,
  "body": "{\"received\":true}"
}

Fehler

  • 404 Kein Webhook mit dieser id.

Zustellungen auflisten

GET /v1/webhooks/{id}/deliveries

Die letzten 50 Zustellungen eines Webhooks, neueste zuerst, mit Status (pending, ok, failed), Anzahl der Versuche, HTTP-Status, Fehler und Zeitpunkt des nächsten Versuchs.

NameOrtTypBeschreibung
id
Pflicht
path string Webhook-id.

Anfrage

curl
curl "https://hubvocal.com/v1/webhooks/wh_3c9d1e/deliveries" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "id": "dl_51b7a9",
    "event": "call.ended",
    "call_id": "demo-8585522d",
    "status": "ok",
    "attempts": 1,
    "http_status": 200,
    "error": null,
    "created_at": 1793832440.2,
    "next_attempt_at": null
  },
  {
    "id": "dl_51a3c4",
    "event": "call.ended",
    "call_id": "tel-6b1f04d2",
    "status": "pending",
    "attempts": 2,
    "http_status": 503,
    "error": "HTTP 503",
    "created_at": 1793832101.7,
    "next_attempt_at": 1793833901.7
  }
]

Fehler

  • 404 Kein Webhook mit dieser id.

Zustellung wiederholen

POST /v1/webhooks/deliveries/{id}/retry

Stellt eine fehlgeschlagene Zustellung erneut in die Warteschlange.

NameOrtTypBeschreibung
id
Pflicht
path string id der Zustellung aus der Zustellungsliste.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/webhooks/deliveries/dl_51a3c4/retry" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "ok": true
}

Fehler

  • 404 Keine Zustellung mit dieser id, oder sie ist nicht fehlgeschlagen.

Stimmen und Engines

Engines, Stimmen und Limits auflisten

GET /v1/voices

Alles für ein Agentenformular: Engine-Namen, gültige Stimmen pro Engine, Geschwindigkeitsbereiche, Sprachen, Tonfall-Vorlagen, das Modell hinter jeder Engine und Feldlängen-Limits. Das Beispiel unten ist gekürzt.

Anfrage

curl
curl "https://hubvocal.com/v1/voices" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "engines": {
    "live": "GPT-Live 1 (OpenAI full-duplex ses modeli)",
    "gemini": "Gemini Live (Google ses-sese model)",
    "realtime": "Realtime (OpenAI ses-sese model)",
    "classic": "Klasik (Deepgram + OpenAI LLM + OpenAI TTS)"
  },
  "voices": {
    "live": [
      "marin",
      "cedar",
      "gleam",
      "meridian"
    ],
    "gemini": [
      "Kore",
      "Aoede",
      "Charon",
      "Puck"
    ],
    "realtime": [
      "marin",
      "cedar",
      "alloy"
    ],
    "classic": [
      "alloy",
      "coral",
      "sage"
    ]
  },
  "speed": {
    "live": {
      "min": 1,
      "max": 1
    },
    "gemini": {
      "min": 1,
      "max": 1
    },
    "realtime": {
      "min": 0.25,
      "max": 1.5
    },
    "classic": {
      "min": 0.25,
      "max": 4
    }
  },
  "langs": {
    "tr": "Türkçe",
    "en": "English"
  },
  "presets": [
    {
      "id": "calm",
      "label": "Sakin ve güven veren",
      "text": "Sakin, yumuşak ve güven veren bir tonla konuş."
    }
  ],
  "models": {
    "live": {
      "model": "gpt-live-1",
      "backend": "gpt-5.6-luna"
    },
    "gemini": {
      "model": "gemini-3.8-live",
      "ready": true
    },
    "realtime": {
      "model": "gpt-realtime-2.1-mini"
    },
    "classic": {
      "stt": "nova-3",
      "llm": "gpt-4.1-mini",
      "tts": "gpt-4o-mini-tts"
    }
  },
  "limits": {
    "tone": 600,
    "instructions": 8000,
    "greeting": 400
  }
}

Anrufe

Die Aufbewahrung wird pro Organisation im Dashboard festgelegt: recordings_days (Standard 30), transcripts_days (Standard 365) und pii_redaction. Ein täglicher Job löscht abgelaufene Aufzeichnungen und Transkripte; die Anrufzeile und ihre Kosten bleiben erhalten.

Web-Widget: Öffentliche Schlüssel (pk_…) werden pro Agent im Dashboard angelegt. Das Widget-Script ruft POST /api/public/web-calls auf; siehe die Anleitung auf der Entwicklerseite.

Web-Anruf starten

POST /v1/web-calls

Öffnet einen Raum für einen Browser-Anruf und gibt ein kurzlebiges Zugriffstoken zurück. Übergeben Sie server_url und token im Browser an livekit-client; der Agent tritt dem Raum selbstständig bei. Rufen Sie diesen Endpunkt von Ihrem Server auf, damit der API-Schlüssel nie den Browser erreicht. Statt agent_id können Sie ein vollständiges agent-Objekt senden, um einen Entwurf ohne Speichern zu testen.

NameOrtTypBeschreibung
agent_id body string id eines gespeicherten Agenten. Pflicht, sofern Sie nicht agent senden.
agent body object Ein vollständiges agent-Objekt (dieselben Felder wie bei POST /v1/agents), nur für diesen Anruf.
version body string | integer Welche Version verwendet wird: "live" (Standard), "draft" oder eine Versionsnummer.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/web-calls" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "agent_id": "front-desk"
}'

Antwort · 200

JSON
{
  "server_url": "wss://hubvocal.com",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
  "room": "demo-3f9a1c2e",
  "max_seconds": 300
}

Fehler

  • 400 Weder agent_id noch agent wurde gesendet.
  • 402 Die Organisation hat ihr monatliches Ausgabenlimit erreicht.
  • 403 Die Organisation ist gesperrt.
  • 404 Kein Agent mit dieser id.

Ausgehenden Anruf starten

POST /v1/calls

Wählt eine Telefonnummer von einer Rufnummer Ihrer Organisation und verbindet den Agenten, sobald abgenommen wird. Der Anbieter (DIDWW, Twilio oder Ihr eigener SIP-Trunk) ergibt sich aus der from-Nummer.

NameOrtTypBeschreibung
from
Pflicht
body string Eine Rufnummer Ihrer Organisation im E.164-Format (+90…).
to
Pflicht
body string Die anzurufende Nummer im E.164-Format.
agent_id body string Zu verwendender Agent. Ohne Angabe nimmt der Agent der from-Nummer ab.
version body string | integer Welche Version verwendet wird: "live" (Standard), "draft" oder eine Versionsnummer.

Anfrage

curl
curl -X POST "https://hubvocal.com/v1/calls" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "+908501234567",
  "to": "+905321234567",
  "agent_id": "front-desk"
}'

Antwort · 200

JSON
{
  "room": "tel-out-9c41e0b7",
  "provider": "didww",
  "sip_call_id": "SCL_7mVt2kQb9xRa"
}

Fehler

  • 400 Eine Nummer ist nicht im internationalen Format, oder from gehört nicht zu Ihren Rufnummern.
  • 402 Die Organisation hat ihr monatliches Ausgabenlimit erreicht.
  • 502 Der Telefonieanbieter hat den Anruf abgelehnt.

Anrufe auflisten

GET /v1/calls

Anrufe von neu nach alt, Web und Telefon. quality ist die Kurzauswertung der Messung im Browser und bei Telefonanrufen null. ended_by ist caller, agent, max_call_seconds, caller_unresponsive, agent_unresponsive, no_answer oder unknown. channel ist web, phone_in oder phone_out. Jede Zeile enthält außerdem outcome und summary_text (die ersten 160 Zeichen der Zusammenfassung). ended_by ist supervisor, wenn ein Supervisor den Anruf über die Live-Konsole beendet hat.

NameOrtTypBeschreibung
limit query integer Standard 50, maximal 500.
agent query string Nur Anrufe dieses Agenten (Agentenname).
outcome query string Nur Anrufe mit diesem Ergebnis.

Anfrage

curl
curl "https://hubvocal.com/v1/calls?limit=20" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
[
  {
    "room": "demo-8585522d",
    "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
    "org_name": "Example Clinic",
    "channel": "web",
    "profile": "Front desk",
    "engine": "live",
    "lang": "en",
    "voice": "marin",
    "started_at": 1793832409.1,
    "ended_at": 1793832434.2,
    "duration_s": 25.1,
    "total_usd": 0.021215,
    "ended_by": "caller",
    "outcome": "message_taken",
    "summary_text": "The caller asked for an appointment on Thursday afternoon; a message was taken for a callback.",
    "extracted": {
      "appointment_date": "2026-11-12",
      "callback": true
    },
    "first_audio_s": 2.43,
    "turns": 4,
    "source_gaps": {
      "count": 0,
      "total_ms": 0,
      "max_ms": 0
    },
    "quality": {
      "verdict": "Clean: no loss, no gaps.",
      "protocol": "UDP",
      "loss_pct": 0,
      "conceal_pct": 0,
      "jitter_ms": 4,
      "rtt_ms": 38
    }
  }
]

Anruf abrufen

GET /v1/calls/{room}

Das vollständige Anrufprotokoll: Kostenaufschlüsselung nach Anbieter, Transkript, Zeit bis zur Begrüßung, Quelllücken auf Agentenseite und die Qualitäts-Zeitachse des Browsers in 2-Sekunden-Fenstern. Die Kostenfelder hängen von der Engine ab (live, llm, stt, tts, realtime…); jedes enthält usd. source_gaps.events listet Paare aus [second, ms]. summary enthält text, outcome (resolved, message_taken, transferred, unresolved, no_conversation, spam), sentiment, topics und action_items. supervisors zeigt, wer sich über die Live-Konsole in den Anruf eingeschaltet hat und in welchen Modi. recording enthält available, duration_s und size_bytes. extracted enthält die Werte der post_call.fields des Agenten (null, wenn nicht erwähnt).

NameOrtTypBeschreibung
room
Pflicht
path string Raumname aus der Anrufliste oder aus POST /v1/web-calls.

Anfrage

curl
curl "https://hubvocal.com/v1/calls/demo-8585522d" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "call": {
    "room": "demo-8585522d",
    "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
    "org_name": "Example Clinic",
    "channel": "web",
    "profile": "Front desk",
    "engine": "live",
    "lang": "en",
    "voice": "marin",
    "started_at": 1793832409.1,
    "ended_at": 1793832434.2,
    "duration_s": 25.1,
    "total_usd": 0.021215,
    "ended_by": "caller",
    "outcome": "message_taken",
    "summary_text": "The caller asked for an appointment on Thursday afternoon; a message was taken for a callback.",
    "extracted": {
      "appointment_date": "2026-11-12",
      "callback": true
    },
    "first_audio_s": 2.43,
    "turns": 4,
    "source_gaps": {
      "count": 2,
      "total_ms": 230,
      "max_ms": 141,
      "agent_audio_s": 31.2,
      "events": [
        [
          16.4,
          141
        ],
        [
          40.1,
          89
        ]
      ]
    },
    "quality": {
      "verdict": "Clean: no loss, no gaps.",
      "protocol": "UDP",
      "loss_pct": 0,
      "conceal_pct": 0,
      "jitter_ms": 4,
      "rtt_ms": 38
    },
    "cost": {
      "live": {
        "billed_s": 25.1,
        "reported": true,
        "voice_usd": 0.020917,
        "backend": {
          "in": 1840,
          "cached": 1024,
          "out": 96
        },
        "backend_usd": 0.000298
      },
      "llm": {
        "input_tokens": 1840,
        "cached_tokens": 1024,
        "output_tokens": 96,
        "usd": 0.000298
      },
      "tts": {
        "input_tokens": 0,
        "audio_tokens": 0,
        "audio_s": 25.1,
        "usd": 0.020917
      },
      "stt": {
        "audio_s": 0,
        "usd": 0
      }
    },
    "tools": [
      {
        "t": 14.2,
        "name": "check_order",
        "kind": "read",
        "ok": true,
        "ms": 412,
        "status": 200
      }
    ],
    "outcomes": [],
    "summary": {
      "text": "The caller asked for an appointment on Thursday afternoon; a message was taken for a callback.",
      "language": "en",
      "outcome": "message_taken",
      "sentiment": "neutral",
      "topics": [
        "appointment"
      ],
      "action_items": [
        "Call the caller back on Thursday morning"
      ]
    },
    "recording": {
      "available": true,
      "duration_s": 25.1,
      "size_bytes": 201344
    },
    "supervisors": [
      {
        "user": "ayse@example.com",
        "joined_at": 1793832420.4,
        "left_at": 1793832431,
        "modes": [
          "listen",
          "whisper"
        ]
      }
    ],
    "greeting": {
      "connect_s": 0.15,
      "session_started_s": 0.05,
      "reply_requested_s": 0.05,
      "first_audio_s": 2.4,
      "reply_done_s": 7.1
    },
    "transcript": [
      {
        "role": "assistant",
        "text": "Hello, thanks for calling the clinic. How can I help you today?",
        "t": 2.4,
        "interrupted": false
      },
      {
        "role": "user",
        "text": "I would like an appointment on Thursday afternoon.",
        "t": 9.8
      }
    ]
  },
  "quality": {
    "summary": {
      "verdict": "Clean: no loss, no gaps.",
      "protocol": "UDP",
      "rtt_ms": 38,
      "protocols_seen": [
        "UDP"
      ],
      "loss_pct": 0,
      "conceal_pct": 0,
      "jitter_ms": 4,
      "buffer_ms": 62
    },
    "timeline": [
      {
        "t": 2,
        "loss": 0,
        "conceal": 0,
        "jitter": 3,
        "buffer": 60,
        "proto": "UDP"
      },
      {
        "t": 4,
        "loss": 0,
        "conceal": 0,
        "jitter": 4,
        "buffer": 62,
        "proto": "UDP"
      }
    ]
  }
}

Fehler

  • 404 Anruf nicht gefunden.

Aufzeichnung herunterladen

GET /v1/calls/{room}/recording

Die Audiodaten des Anrufs als OGG/Opus. Unterstützt Range-Anfragen. 404, wenn der Anruf nicht aufgezeichnet wurde oder die Aufzeichnung abgelaufen ist.

NameOrtTypBeschreibung
room
Pflicht
path string Raumname aus der Anrufliste oder aus POST /v1/web-calls.

Anfrage

curl
curl "https://hubvocal.com/v1/calls/demo-8585522d/recording" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -o call.ogg

Antwort · 200

audio/ogg
HTTP/1.1 200 OK
Content-Type: audio/ogg
Accept-Ranges: bytes
Content-Length: 201344

<OGG/Opus>

Fehler

  • 404 Der Anruf wurde nicht aufgezeichnet, oder die Aufzeichnung ist abgelaufen.

Anruf löschen

DELETE /v1/calls/{room}

Löscht Aufzeichnung, Transkript und Zusammenfassung des Anrufs sofort, etwa bei einem Antrag nach KVKK oder GDPR. Die Anrufzeile und ihre Kosten bleiben erhalten.

NameOrtTypBeschreibung
room
Pflicht
path string Raumname aus der Anrufliste oder aus POST /v1/web-calls.

Anfrage

curl
curl -X DELETE "https://hubvocal.com/v1/calls/demo-8585522d" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "deleted": "demo-8585522d"
}

Fehler

  • 404 Anruf nicht gefunden.

Anrufe exportieren (CSV)

GET /v1/calls/export

Anrufe eines Zeitraums als CSV, eine Zeile pro Anruf, mit den strukturierten Feldern als zusätzliche Spalten.

NameOrtTypBeschreibung
format
Pflicht
query string Nur csv.
from query date YYYY-MM-DD, einschließlich.
to query date YYYY-MM-DD, einschließlich.
agent_id query string Nur Anrufe dieses Agenten.

Anfrage

curl
curl "https://hubvocal.com/v1/calls/export?format=csv&from=2026-11-01&to=2026-11-05" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -o calls.csv

Antwort · 200

text/csv
room,started_at,agent,channel,duration_s,total_usd,outcome,appointment_date,callback
demo-8585522d,2026-11-05T09:46:49Z,front-desk,web,25.1,0.021215,message_taken,2026-11-12,true

Rufnummern

Rufnummern auflisten

GET /v1/numbers

Die Rufnummern Ihrer Organisation und der Agent, der jeweils abnimmt (profile_id), dazu die Bereitschaft jedes Telefonieanbieters. Rufnummern fügt das Plattform-Team hinzu; Sie weisen die Agenten zu.

Anfrage

curl
curl "https://hubvocal.com/v1/numbers" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "numbers": [
    {
      "number": "+908501234567",
      "provider": "didww",
      "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
      "org_name": "Example Clinic",
      "profile_id": "front-desk",
      "label": "Main line"
    }
  ],
  "sip": {
    "enabled": true,
    "room_prefix": "tel-",
    "providers": {
      "didww": {
        "inbound_ips": "46.19.209.14,46.19.210.14",
        "inbound_auth": false,
        "outbound_host": "trunk.example.com",
        "outbound_auth": true,
        "outbound_ready": true,
        "inbound_ready": true
      }
    }
  }
}

Agenten einer Rufnummer zuweisen

PUT /v1/numbers/{number}

Legt fest, welcher Agent eingehende Anrufe auf dieser Rufnummer annimmt. Mit agent_id: null heben Sie die Zuweisung auf. Kodieren Sie das + der Nummer im Pfad als %2B (das Präfix 00 funktioniert ebenfalls).

NameOrtTypBeschreibung
number
Pflicht
path string Die Nummer in E.164, URL-kodiert.
agent_id body string | null Agent, der eingehende Anrufe annimmt.
label body string Eine Notiz für Ihr Team, bis zu 60 Zeichen.

Anfrage

curl
curl -X PUT "https://hubvocal.com/v1/numbers/%2B908501234567" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "agent_id": "front-desk",
  "label": "Main line"
}'

Antwort · 200

JSON
{
  "ok": true
}

Fehler

  • 400 Der Agent existiert nicht.
  • 404 Die Rufnummer gehört nicht zu Ihrer Organisation.

Nutzung

Nutzung

GET /v1/usage

Anrufe, Minuten und Anbieterkosten Ihrer Organisation, nach Anbieter und Tag (Europe/Istanbul). Standard ist der laufende Monat. kind ist llm, tts, stt oder voice (Speech-to-Speech-Engines).

NameOrtTypBeschreibung
from query date YYYY-MM-DD, einschließlich.
to query date YYYY-MM-DD, einschließlich.

Anfrage

curl
curl "https://hubvocal.com/v1/usage?from=2026-11-01&to=2026-11-05" \
  -H "Authorization: Bearer $VT_API_KEY"

Antwort · 200

JSON
{
  "from": "2026-11-01",
  "to": "2026-11-05",
  "totals": {
    "calls": 42,
    "minutes": 81.2,
    "usd": 3.94
  },
  "by_provider": [
    {
      "provider": "openai",
      "model": "gpt-live-1",
      "kind": "voice",
      "calls": 30,
      "input_tokens": 0,
      "cached_tokens": 0,
      "output_tokens": 0,
      "audio_s": 2900.1,
      "usd": 2.41
    }
  ],
  "by_day": [
    {
      "date": "2026-11-05",
      "usd": 1.2,
      "minutes": 20.5,
      "calls": 9
    }
  ],
  "by_org": [
    {
      "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
      "org_name": "Example Clinic",
      "usd": 3.94,
      "minutes": 81.2,
      "calls": 42
    }
  ]
}

Spezifikation

OpenAPI-Spezifikation

GET /v1/openapi.json Kein Schlüssel nötig

Das OpenAPI-3.1-Dokument dieser API. Kein Schlüssel nötig. Importieren Sie es in Postman, Insomnia oder einen Client-Generator.

Anfrage

curl
curl "https://hubvocal.com/v1/openapi.json"

Antwort · 200

JSON
{
  "openapi": "3.1.0",
  "info": {
    "title": "HubVocal API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://hubvocal.com/v1"
    }
  ],
  "paths": {}
}