API başvurusu
Açık API v1'in tüm uçları. Örnekler curl, JavaScript (fetch) ve Python (requests) ile; seçtiğiniz dil sayfa boyunca hatırlanır.
| Taban adres | https://hubvocal.com/v1 |
|---|---|
| Kimlik | Authorization: Bearer vt_live_… |
| Hız sınırı | Anahtar başına 120 istek/dk · 429 + Retry-After |
| Kapsamlar | read · write · callsHer anahtarda read, write ve/veya calls bulunur. read GET isteklerini, write değişiklikleri, calls giden aramaları kapsar. Anahtarın kapsamı dışındaki bir istek 403 alır. |
| Hata gövdesi | {"detail": "..."} |
| OpenAPI | GET /v1/openapi.json |
Kimlik doğrulama, gömme ve hata kodları için Geliştiriciler sayfasına bakın.
Ajanlar
Görüşmeler metin modunda koşar; yani talimatı ve araç kullanımını dener, sesi ya da gecikmeyi değil. Simülasyonlar panelden koşturulur; bunlar için henüz /v1 ucu yoktur.
Ajanları listele
GET /v1/agents
Organizasyonunuzdaki tüm ajanları paneldeki sırayla döner.
İstek
curl "https://hubvocal.com/v1/agents" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/agents", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/agents",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"id": "resepsiyon",
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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
}
] Ajan oluştur
POST /v1/agents
Yeni ajan oluşturur. Her alan sunucuda doğrulanır; sınırı aşan değerler kısaltılır. Var olan bir id gönderirseniz 409 döner; güncellemek için PUT kullanın.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
id | body | string | İsteğe bağlı. Küçük harf, rakam ve tire; en fazla 48 karakter. Verilmezse addan üretilir. |
namezorunlu | body | string | Görünen ad, en fazla 60 karakter. |
langzorunlu | body | string | Görüşme dili kodu, ör. tr, en, de. Tam liste GET /v1/voices yanıtında. |
enginezorunlu | body | "live" | "gemini" | "realtime" | "classic" | live: GPT-Live 1, gemini: Gemini Live, realtime: OpenAI Realtime, classic: STT → LLM → TTS. |
instructions | body | string | Ajan talimatı, en fazla 8000 karakter. |
greeting | body | string | Ajanın ilk cümlesi, en fazla 400 karakter. |
voice | body | object | voice (/v1/voices listesinden bir ad), speed (yalnız classic ve realtime; live ve gemini'de 1.0 sabit), tone (serbest konuşma tarzı, en fazla 600 karakter). |
tools | body | object | builtins (end_call, take_message) ve webhooks (araç kimlikleri); toplam en fazla 16 araç. Boş ya da yoksa araç yoktur. mcp: [{server_id, tools}] MCP sunucularınızdaki araçları ekler; aynı sınıra dahildir. |
turn | body | object | Söz alma ayarları: sensitivity (low, balanced, high; yalnız Klasik motor), first_speaker (agent ya da caller), silence_wait_s (1–5), idle_check_s (0 ya da 10–120), agent_timeout_s (0 ya da 10–60). Boş alanlar varsayılanı kullanır. |
recording | body | object | recording: {enabled (varsayılan false), announce (varsayılan true), announce_text?}. Açıksa ajan karşılamadan önce kaydı anons eder. |
post_call | body | object | post_call.summary: görüşme bitince özet yaz (varsayılan true). post_call.fields: görüşmeden sonra doldurulacak en fazla 24 alan ({name, type, description, enum?, required?}). |
knowledge | body | object | doc_ids (en fazla 50 bilgi bankası belgesi) ve mode ("tool"). Ajan bu durumda search_knowledge aracını alır. |
calendar | body | object | Panelden integration_id ve calendar_id, duration_min (15–240), buffer_min (0–60), timezone, working_hours, min_notice_h (0–72), max_days_ahead (1–90). Randevu araçlarını açar. |
İstek
curl -X POST "https://hubvocal.com/v1/agents" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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"
}
}' const res = await fetch("https://hubvocal.com/v1/agents", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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"
}
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/agents",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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",
},
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 201
{
"id": "resepsiyon",
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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
} Hatalar
409Bu id ile bir ajan zaten var.
Ajanı getir
GET /v1/agents/{id}
Tek bir ajanı döner. published_version yayındaki sürüm numarasıdır (hiç yayımlanmadıysa null); draft_changed taslağın ondan farklı olup olmadığını söyler.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
İstek
curl "https://hubvocal.com/v1/agents/resepsiyon" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/agents/resepsiyon",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"id": "resepsiyon",
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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
} Hatalar
404Bu id ile ajan yok.
Ajanı güncelle
PUT /v1/agents/{id}
Ajanı gönderdiğiniz nesneyle değiştirir. Nesnenin tamamını gönderin; eksik bıraktığınız alanlar varsayılana döner. Yoldaki id, gövdedeki id'den önce gelir.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
namezorunlu | body | string | Görünen ad, en fazla 60 karakter. |
langzorunlu | body | string | Görüşme dili kodu, ör. tr, en, de. Tam liste GET /v1/voices yanıtında. |
enginezorunlu | body | "live" | "gemini" | "realtime" | "classic" | live: GPT-Live 1, gemini: Gemini Live, realtime: OpenAI Realtime, classic: STT → LLM → TTS. |
instructions | body | string | Ajan talimatı, en fazla 8000 karakter. |
greeting | body | string | Ajanın ilk cümlesi, en fazla 400 karakter. |
voice | body | object | voice (/v1/voices listesinden bir ad), speed (yalnız classic ve realtime; live ve gemini'de 1.0 sabit), tone (serbest konuşma tarzı, en fazla 600 karakter). |
tools | body | object | builtins (end_call, take_message) ve webhooks (araç kimlikleri); toplam en fazla 16 araç. Boş ya da yoksa araç yoktur. mcp: [{server_id, tools}] MCP sunucularınızdaki araçları ekler; aynı sınıra dahildir. |
turn | body | object | Söz alma ayarları: sensitivity (low, balanced, high; yalnız Klasik motor), first_speaker (agent ya da caller), silence_wait_s (1–5), idle_check_s (0 ya da 10–120), agent_timeout_s (0 ya da 10–60). Boş alanlar varsayılanı kullanır. |
recording | body | object | recording: {enabled (varsayılan false), announce (varsayılan true), announce_text?}. Açıksa ajan karşılamadan önce kaydı anons eder. |
post_call | body | object | post_call.summary: görüşme bitince özet yaz (varsayılan true). post_call.fields: görüşmeden sonra doldurulacak en fazla 24 alan ({name, type, description, enum?, required?}). |
knowledge | body | object | doc_ids (en fazla 50 bilgi bankası belgesi) ve mode ("tool"). Ajan bu durumda search_knowledge aracını alır. |
calendar | body | object | Panelden integration_id ve calendar_id, duration_min (15–240), buffer_min (0–60), timezone, working_hours, min_notice_h (0–72), max_days_ahead (1–90). Randevu araçlarını açar. |
İstek
curl -X PUT "https://hubvocal.com/v1/agents/resepsiyon" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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"
}
}' const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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"
}
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.put(
"https://hubvocal.com/v1/agents/resepsiyon",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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",
},
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"id": "resepsiyon",
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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
} Hatalar
404Bu id ile ajan yok. Önce POST ile oluşturun.
Ajanı sil
DELETE /v1/agents/{id}
Ajanı siler. Organizasyonda en az bir ajan kalmalı; son ajan silinemez.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
İstek
curl -X DELETE "https://hubvocal.com/v1/agents/resepsiyon" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.delete(
"https://hubvocal.com/v1/agents/resepsiyon",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"deleted": "resepsiyon"
} Hatalar
400Organizasyondaki son ajan.404Bu id ile ajan yok.
Sürümleri listele
GET /v1/agents/{id}/versions
Ajanın yayımlanmış sürümleri, yeniden eskiye. is_live, görüşmelerin şu an kullandığını işaretler.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
İstek
curl "https://hubvocal.com/v1/agents/resepsiyon/versions" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon/versions", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/agents/resepsiyon/versions",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"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
}
] Hatalar
404Bu id ile ajan yok.
Sürümü getir
GET /v1/agents/{id}/versions/{n}
Ajanın o sürümdeki tam hali.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
nzorunlu | path | integer | Sürüm numarası. |
İstek
curl "https://hubvocal.com/v1/agents/resepsiyon/versions/2" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon/versions/2", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/agents/resepsiyon/versions/2",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"id": "resepsiyon",
"name": "Resepsiyon",
"lang": "tr",
"engine": "live",
"instructions": "Bir diş kliniğinin resepsiyonistisin. Randevu almak isteyenlere yardım et, genel soruları kısa yanıtla. Bilmediğin bir şeyi uydurma; ilgili kişinin geri döneceğini söyle.",
"greeting": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"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
} Hatalar
404Böyle bir ajan ya da sürüm yok.
Taslağı yayımla
POST /v1/agents/{id}/publish
Mevcut taslağı yeni bir sürüm olarak kaydeder ve yayına alır. Süren görüşmeler kendi sürümüyle devam eder.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
note | body | string | Neyin değiştiğine dair kısa bir not. |
İstek
curl -X POST "https://hubvocal.com/v1/agents/resepsiyon/publish" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"note": "Shorter greeting"
}' const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon/publish", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"note": "Shorter greeting"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/agents/resepsiyon/publish",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"note": "Shorter greeting",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"version": 4
} Hatalar
404Bu id ile ajan yok.
Geri al
POST /v1/agents/{id}/rollback
Önceki bir sürümü taslağa kopyalar ve yeni bir sürüm olarak yayımlar.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Ajan kimliği, ör. resepsiyon. |
versionzorunlu | body | integer | Geri getirilecek sürüm. |
İstek
curl -X POST "https://hubvocal.com/v1/agents/resepsiyon/rollback" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"version": 2
}' const res = await fetch("https://hubvocal.com/v1/agents/resepsiyon/rollback", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"version": 2
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/agents/resepsiyon/rollback",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"version": 2,
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"version": 5
} Hatalar
404Böyle bir ajan ya da sürüm yok.
Bilgi bankası
Belgeleri listele
GET /v1/knowledge
Organizasyonunuzun belgeleri; işleme durumu, boyut, parça sayısı ve onları kullanan ajanlarla.
İstek
curl "https://hubvocal.com/v1/knowledge" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/knowledge", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/knowledge",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"id": "kb_7d21e4",
"title": "Fiyat listesi 2026",
"kind": "file",
"filename": "price-list-2026.pdf",
"url": null,
"size_bytes": 248113,
"chunks": 42,
"status": "ready",
"error": null,
"created_at": 1793740000,
"used_by": [
"resepsiyon"
]
}
] Belge ekle
POST /v1/knowledge
Dosyayı multipart/form-data (file alanı) olarak yükleyin, metni JSON {title, text} ya da tek bir web sayfasını JSON {url} olarak gönderin. 201 ve status processing döner; belge ready ya da failed olana kadar sorgulayın.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
file | body | file | multipart/form-data: pdf, docx, txt, md ya da html; en fazla 10 MB. |
title | body | string | Başlık; text ile birlikte. |
text | body | string | Düz metin içerik. |
url | body | string | Bunun yerine alınacak tek bir https sayfası. |
İstek
curl -X POST "https://hubvocal.com/v1/knowledge" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Çalışma saatleri",
"text": "Hafta içi 09:00–18:00, cumartesi 10:00–14:00 açığız. Pazar kapalıyız."
}' const res = await fetch("https://hubvocal.com/v1/knowledge", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"title": "Çalışma saatleri",
"text": "Hafta içi 09:00–18:00, cumartesi 10:00–14:00 açığız. Pazar kapalıyız."
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/knowledge",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"title": "Çalışma saatleri",
"text": "Hafta içi 09:00–18:00, cumartesi 10:00–14:00 açığız. Pazar kapalıyız.",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 201
{
"id": "kb_9f03b1",
"title": "Çalışma saatleri",
"kind": "text",
"filename": null,
"url": null,
"size_bytes": 96,
"chunks": 0,
"status": "processing",
"error": null,
"created_at": 1793740000,
"used_by": []
} Hatalar
400Desteklenmeyen dosya türü, 10 MB'tan büyük dosya, https olmayan ya da özel bir adrese giden URL, ya da organizasyon sınırı (200 belge, 200 MB) doldu.
Belgeyi getir
GET /v1/knowledge/{id}
Belge ve ilk 2000 karakterinin önizlemesi.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Belge kimliği. |
İstek
curl "https://hubvocal.com/v1/knowledge/kb_7d21e4" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/knowledge/kb_7d21e4", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/knowledge/kb_7d21e4",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"id": "kb_7d21e4",
"title": "Fiyat listesi 2026",
"kind": "file",
"filename": "price-list-2026.pdf",
"url": null,
"size_bytes": 248113,
"chunks": 42,
"status": "ready",
"error": null,
"created_at": 1793740000,
"used_by": [
"resepsiyon"
],
"preview": "Fiyat listesi 2026. Muayene 1.500 TL, diş taşı temizliği 2.000 TL…"
} Hatalar
404Bu kimlikle belge yok.
Belgeyi sil
DELETE /v1/knowledge/{id}
Belgeyi siler ve onu kullanan tüm ajanlardan kaldırır.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Belge kimliği. |
İstek
curl -X DELETE "https://hubvocal.com/v1/knowledge/kb_7d21e4" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/knowledge/kb_7d21e4", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.delete(
"https://hubvocal.com/v1/knowledge/kb_7d21e4",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"deleted": "kb_7d21e4"
} Hatalar
404Bu kimlikle belge yok.
Ara
POST /v1/knowledge/search
Ajanın kullandığı aramanın aynısını yapar ve en iyi eşleşen parçaları puanla döner. Yayına almadan önce belgelerinizi denemek için.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
queryzorunlu | body | string | Aranacak şey. |
doc_ids | body | string[] | Aramayı bu belgelerle sınırla. |
İstek
curl -X POST "https://hubvocal.com/v1/knowledge/search" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "diş taşı temizliği ne kadar"
}' const res = await fetch("https://hubvocal.com/v1/knowledge/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"query": "diş taşı temizliği ne kadar"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/knowledge/search",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"query": "diş taşı temizliği ne kadar",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"doc_id": "kb_7d21e4",
"title": "Fiyat listesi 2026",
"chunk_index": 3,
"text": "Diş taşı temizliği: 2.000 TL, yaklaşık 30 dakika.",
"score": 0.82
}
] Araçlar
Yerleşik araçlar
Bu araçlar tanım gerektirmez. Ajanın tools.builtins listesinde açın. knowledge ayarlanınca search_knowledge eklenir. calendar ayarlanınca randevu araçları eklenir.
| Ad | Ne yapar |
|---|---|
end_call | Ajan vedalaşır, konuşması bittikten 0,75 sn sonra kapatır. Arayan bu arada konuşursa kapatma iptal olur. Görüşme kaydında ended_by: "agent" görünür. |
take_message | name, phone, message ve callback_requested alır ve görüşme kaydında outcomes[] içine yazar. Onay istemez. |
search_knowledge | Ajanın knowledge alanında belge varsa kendiliğinden eklenir. Belgelerde arar ve kaynakları görüşme kaydına yazar. |
check_availability | Okuma. Ajanın çalışma saatleri içinde date_from ile date_to arasındaki boş zamanları döner. calendar ayarlıysa eklenir. |
book_appointment | Yazma; onay kapısından geçer. name ve phone için start zamanına randevu alır; isteğe bağlı note. Randevu outcomes[] içine yazılır. |
cancel_appointment | Yazma; onay kapısından geçer. booking_ref ile randevuyu iptal eder. |
Takvim entegrasyonları (Google Calendar) yalnız panelden bağlanır; bunlar için /v1 ucu yoktur. Ajanın calendar alanında panelden aldığınız entegrasyon ve takvim kimliklerini kullanın.
Araçları listele
GET /v1/tools
Organizasyonunuzun webhook araçları. Gizli anahtar hiç dönmez; has_secret tanımlı olup olmadığını gösterir.
İstek
curl "https://hubvocal.com/v1/tools" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/tools", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/tools",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"id": "tl_8f3a2c",
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 8,
"enabled": true,
"has_secret": true,
"created_at": 1793830000,
"updated_at": 1793830000
}
] Aracı getir
GET /v1/tools/{id}
Tek bir webhook aracı. Gizli anahtar hiç dönmez.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Araç kimliği. |
İstek
curl "https://hubvocal.com/v1/tools/tl_8f3a2c" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/tools/tl_8f3a2c", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/tools/tl_8f3a2c",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"id": "tl_8f3a2c",
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 8,
"enabled": true,
"has_secret": true,
"created_at": 1793830000,
"updated_at": 1793830000
} Hatalar
404Bu kimlikle araç yok.
Araç oluştur
POST /v1/tools
Organizasyon için bir webhook aracı tanımlar. Kullanmak için kimliğini ajanın tools.webhooks listesine ekleyin. Adres https olmalı, yerel ya da özel bir adrese gidemez.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
namezorunlu | body | string | Küçük harf, rakam ve alt çizgi; harfle başlar (3–41 karakter). Organizasyonda benzersiz; end_call ve take_message ayrılmıştır. |
descriptionzorunlu | body | string | Modele aracı ne zaman ve nasıl kullanacağını anlatır. |
kindzorunlu | body | "read" | "write" | read hemen çalışır; write önce arayandan onay ister. |
urlzorunlu | body | string | Sizin ucunuz. Yalnız https; yerel ve özel adresler reddedilir. |
parameters | body | object | JSON Schema nesnesi: string, number, integer ya da boolean türünde en fazla 20 alan (enum olur). |
timeout_s | body | integer | 2–15 saniye. |
enabled | body | boolean | Kapalı araçlar modele sunulmaz. |
secret | body | string | İstekleri imzalamak için. Yalnız yazılır; güncellemede boş değer mevcut anahtarı korur, "-" siler. |
İstek
curl -X POST "https://hubvocal.com/v1/tools" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 8,
"enabled": true,
"secret": "whsec_2b7f…"
}' const res = await fetch("https://hubvocal.com/v1/tools", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 8,
"enabled": true,
"secret": "whsec_2b7f…"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/tools",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası",
},
},
"required": [
"order_id",
],
},
"timeout_s": 8,
"enabled": True,
"secret": "whsec_2b7f…",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 201
{
"id": "tl_8f3a2c",
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 8,
"enabled": true,
"has_secret": true,
"created_at": 1793830000,
"updated_at": 1793830000
} Hatalar
400Bir alan kurala uymuyor: ad biçimi, https adres, özel adres, 20'den fazla parametre ya da aralık dışı zaman aşımı.409Bu adla bir araç zaten var ya da ad ayrılmış.
Aracı güncelle
PUT /v1/tools/{id}
Aracı gönderdiğiniz nesneyle değiştirir. Mevcut gizli anahtarı korumak için secret alanını boş bırakın ya da göndermeyin; silmek için "-" gönderin.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Araç kimliği. |
namezorunlu | body | string | Küçük harf, rakam ve alt çizgi; harfle başlar (3–41 karakter). Organizasyonda benzersiz; end_call ve take_message ayrılmıştır. |
descriptionzorunlu | body | string | Modele aracı ne zaman ve nasıl kullanacağını anlatır. |
kindzorunlu | body | "read" | "write" | read hemen çalışır; write önce arayandan onay ister. |
urlzorunlu | body | string | Sizin ucunuz. Yalnız https; yerel ve özel adresler reddedilir. |
parameters | body | object | JSON Schema nesnesi: string, number, integer ya da boolean türünde en fazla 20 alan (enum olur). |
timeout_s | body | integer | 2–15 saniye. |
enabled | body | boolean | Kapalı araçlar modele sunulmaz. |
secret | body | string | İstekleri imzalamak için. Yalnız yazılır; güncellemede boş değer mevcut anahtarı korur, "-" siler. |
İstek
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": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 10,
"enabled": true,
"secret": ""
}' const res = await fetch("https://hubvocal.com/v1/tools/tl_8f3a2c", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 10,
"enabled": true,
"secret": ""
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.put(
"https://hubvocal.com/v1/tools/tl_8f3a2c",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası",
},
},
"required": [
"order_id",
],
},
"timeout_s": 10,
"enabled": True,
"secret": "",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"id": "tl_8f3a2c",
"name": "check_order",
"description": "Sipariş numarasıyla kargo durumunu getirir.",
"kind": "read",
"url": "https://crm.example.com/hooks/order",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Sipariş numarası"
}
},
"required": [
"order_id"
]
},
"timeout_s": 10,
"enabled": true,
"has_secret": true,
"created_at": 1793830000,
"updated_at": 1793833600
} Hatalar
400Bir alan kurala uymuyor: ad biçimi, https adres, özel adres, 20'den fazla parametre ya da aralık dışı zaman aşımı.404Bu kimlikle araç yok.
Aracı sil
DELETE /v1/tools/{id}
Aracı siler ve onu kullanan tüm ajanlardan kaldırır.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Araç kimliği. |
İstek
curl -X DELETE "https://hubvocal.com/v1/tools/tl_8f3a2c" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/tools/tl_8f3a2c", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.delete(
"https://hubvocal.com/v1/tools/tl_8f3a2c",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"deleted": "tl_8f3a2c"
} Hatalar
404Bu kimlikle araç yok.
Aracı dene
POST /v1/tools/{id}/test
Verdiğiniz argümanlarla aracın adresine gerçek bir istek atar; durum kodunu, süreyi ve yanıt gövdesinin en fazla 4 KB'ını döner.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Araç kimliği. |
arguments | body | object | parameters ile uyumlu örnek argümanlar. |
İstek
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"
}
}' const res = await fetch("https://hubvocal.com/v1/tools/tl_8f3a2c/test", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"arguments": {
"order_id": "A-10234"
}
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/tools/tl_8f3a2c/test",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"arguments": {
"order_id": "A-10234",
},
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"ok": true,
"status": 200,
"ms": 412,
"body": "{\"order_id\":\"A-10234\",\"status\":\"shipped\",\"eta\":\"2026-11-07\"}"
} Hatalar
404Bu kimlikle araç yok.
MCP sunucuları
MCP sunucularını listele
GET /v1/mcp-servers
Organizasyonunuzun MCP sunucuları; durumları ve eşitlenmiş araçlarıyla. auth_set bir gizli anahtarın kayıtlı olup olmadığını gösterir; anahtar hiç dönmez.
İstek
curl "https://hubvocal.com/v1/mcp-servers" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/mcp-servers", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/mcp-servers",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"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 sunucusu ekle
POST /v1/mcp-servers
Sunucuyu kaydeder ve araç listesini çeker. Yeni araçlar kapalı gelir. Organizasyon başına en fazla 10 sunucu.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
namezorunlu | body | string | Kısa ad; araç adlarında önek olarak kullanılır (<ad>.<araç>). |
urlzorunlu | body | string | Sunucunun MCP ucu. Yalnız https; yerel ve özel adresler reddedilir. |
transport | body | string | streamable_http (varsayılan) ya da sse. |
auth | body | string | none, bearer ya da header. |
secret | body | string | Token ya da başlık değeri. Şifreli saklanır, hiç dönmez; "-" siler. |
header_name | body | string | auth header ise başlığın adı. |
İstek
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_…"
}' const res = await fetch("https://hubvocal.com/v1/mcp-servers", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"name": "crm",
"url": "https://mcp.example.com/mcp",
"auth": "bearer",
"secret": "sk_live_…"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/mcp-servers",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"name": "crm",
"url": "https://mcp.example.com/mcp",
"auth": "bearer",
"secret": "sk_live_…",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 201
{
"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"
}
]
} Hatalar
400Adres https değil ya da özel bir adrese gidiyor, ya da sunucunun araç listesi alınamadı.409Organizasyonda zaten 10 MCP sunucusu var.
MCP sunucusunu güncelle
PUT /v1/mcp-servers/{id}
Adı, adresi, kimlik doğrulamayı ya da açık/kapalı durumunu; hangi araçların açık olduğunu ve okuma mı yazma mı olduğunu değiştirir. Gizli anahtarı silmek için secret: "-" gönderin.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | MCP sunucusu kimliği. |
name | body | string | Kısa ad; araç adlarında önek olarak kullanılır (<ad>.<araç>). |
url | body | string | Sunucunun MCP ucu. Yalnız https; yerel ve özel adresler reddedilir. |
enabled | body | boolean | Kapalı bir sunucu ajanlara sunulmaz. |
auth | body | string | none, bearer ya da header. |
secret | body | string | Token ya da başlık değeri. Şifreli saklanır, hiç dönmez; "-" siler. |
tools | body | object[] | Araç başına [{name, enabled, access}]; access read ya da write. |
İstek
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"
}
]
}' const res = await fetch("https://hubvocal.com/v1/mcp-servers/mcp_2b8e41", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"tools": [
{
"name": "find_customer",
"enabled": true,
"access": "read"
},
{
"name": "create_ticket",
"enabled": true,
"access": "write"
}
]
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.put(
"https://hubvocal.com/v1/mcp-servers/mcp_2b8e41",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"tools": [
{
"name": "find_customer",
"enabled": True,
"access": "read",
},
{
"name": "create_ticket",
"enabled": True,
"access": "write",
},
],
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"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"
}
]
} Hatalar
400Adres https değil ya da özel bir adrese gidiyor, ya da sunucunun araç listesi alınamadı.404Bu kimlikle MCP sunucusu yok.
MCP sunucusunu sil
DELETE /v1/mcp-servers/{id}
Sunucuyu siler ve araçlarını tüm ajanlardan kaldırır.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | MCP sunucusu kimliği. |
İstek
curl -X DELETE "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/mcp-servers/mcp_2b8e41", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.delete(
"https://hubvocal.com/v1/mcp-servers/mcp_2b8e41",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"deleted": "mcp_2b8e41"
} Hatalar
404Bu kimlikle MCP sunucusu yok.
Araçları eşitle
POST /v1/mcp-servers/{id}/sync
Araç listesini yeniden çeker. Yeni araçlar kapalı ve access write olarak gelir.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | MCP sunucusu kimliği. |
İstek
curl -X POST "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/sync" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/sync", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/sync",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"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"
}
]
} Hatalar
400Adres https değil ya da özel bir adrese gidiyor, ya da sunucunun araç listesi alınamadı.404Bu kimlikle MCP sunucusu yok.
Aracı dene
POST /v1/mcp-servers/{id}/test
Sunucudaki bir aracı verdiğiniz argümanlarla çağırır; süreyi, içeriğin en fazla 4 KB'ını ve aracın hata bildirip bildirmediğini döner.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | MCP sunucusu kimliği. |
toolzorunlu | body | string | Çağrılacak aracın adı. |
arguments | body | object | Aracın input_schema'sına uyan argümanlar. |
İstek
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"
}
}' const res = await fetch("https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/test", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"tool": "find_customer",
"arguments": {
"phone": "+905321234567"
}
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/test",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"tool": "find_customer",
"arguments": {
"phone": "+905321234567",
},
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"ok": true,
"ms": 236,
"content": "{\"customer_id\":\"C-1042\",\"name\":\"Ayşe Yılmaz\",\"open_tickets\":0}",
"is_error": false
} Hatalar
404Bu kimlikle MCP sunucusu yok.
Webhook'lar
Webhook'ları listele
GET /v1/webhooks
Organizasyonunuzun webhook'ları ve son teslimlerinin sonucu. Gizli anahtar burada dönmez; secret_set tanımlı olup olmadığını gösterir.
İstek
curl "https://hubvocal.com/v1/webhooks" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/webhooks", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/webhooks",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"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 oluştur
POST /v1/webhooks
Bir adresi olaylara abone eder. Şimdilik tek olay call.ended. Organizasyon başına en fazla 5 webhook. secret vermezseniz biri üretilir ve yalnız bu yanıtta döner.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
urlzorunlu | body | string | Sizin ucunuz. Yalnız https; yerel ve özel adresler reddedilir. |
eventszorunlu | body | string[] | Alınacak olaylar. Şimdilik ["call.ended"]. |
enabled | body | boolean | Kapalı webhook'lara hiçbir şey gönderilmez. |
secret | body | string | İmza anahtarı. Verilmezse üretilir; yalnız bir kez döner. |
İstek
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"
]
}' const res = await fetch("https://hubvocal.com/v1/webhooks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"url": "https://crm.example.com/hooks/voice",
"events": [
"call.ended"
]
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/webhooks",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"url": "https://crm.example.com/hooks/voice",
"events": [
"call.ended",
],
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 201
{
"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…"
} Hatalar
400Adres https değil, özel bir adrese gidiyor ya da olay bilinmiyor.409Organizasyonda zaten 5 webhook var.
Webhook'u güncelle
PUT /v1/webhooks/{id}
Adresi, olayları ya da açık/kapalı durumunu değiştirir. Yeni bir gizli anahtar üretmek için secret: "-" gönderin; yanıtta döner.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Webhook kimliği. |
url | body | string | Sizin ucunuz. Yalnız https; yerel ve özel adresler reddedilir. |
events | body | string[] | Alınacak olaylar. Şimdilik ["call.ended"]. |
enabled | body | boolean | Kapalı webhook'lara hiçbir şey gönderilmez. |
secret | body | string | "-" yeni bir anahtar üretir. Mevcut anahtarı korumak için göndermeyin. |
İstek
curl -X PUT "https://hubvocal.com/v1/webhooks/wh_3c9d1e" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": false
}' const res = await fetch("https://hubvocal.com/v1/webhooks/wh_3c9d1e", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"enabled": false
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.put(
"https://hubvocal.com/v1/webhooks/wh_3c9d1e",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"enabled": False,
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"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
}
} Hatalar
400Adres https değil, özel bir adrese gidiyor ya da olay bilinmiyor.404Bu kimlikle webhook yok.
Webhook'u sil
DELETE /v1/webhooks/{id}
Webhook'u siler. Bekleyen teslimler düşer.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Webhook kimliği. |
İstek
curl -X DELETE "https://hubvocal.com/v1/webhooks/wh_3c9d1e" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/webhooks/wh_3c9d1e", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.delete(
"https://hubvocal.com/v1/webhooks/wh_3c9d1e",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"deleted": "wh_3c9d1e"
} Hatalar
404Bu kimlikle webhook yok.
Webhook'u dene
POST /v1/webhooks/{id}/test
Adrese örnek bir call.ended olayı gönderir; durum kodunu, süreyi ve yanıt gövdesini döner.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Webhook kimliği. |
İstek
curl -X POST "https://hubvocal.com/v1/webhooks/wh_3c9d1e/test" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/webhooks/wh_3c9d1e/test", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/webhooks/wh_3c9d1e/test",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"ok": true,
"http_status": 200,
"ms": 184,
"body": "{\"received\":true}"
} Hatalar
404Bu kimlikle webhook yok.
Teslimleri listele
GET /v1/webhooks/{id}/deliveries
Bir webhook'un son 50 teslimi, yeniden eskiye: durum (pending, ok, failed), deneme sayısı, HTTP durumu, hata ve sonraki denemenin zamanı.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Webhook kimliği. |
İstek
curl "https://hubvocal.com/v1/webhooks/wh_3c9d1e/deliveries" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/webhooks/wh_3c9d1e/deliveries", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/webhooks/wh_3c9d1e/deliveries",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"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
}
] Hatalar
404Bu kimlikle webhook yok.
Teslimi yeniden dene
POST /v1/webhooks/deliveries/{id}/retry
Başarısız bir teslimi yeniden kuyruğa alır.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
idzorunlu | path | string | Teslim listesinden teslim kimliği. |
İstek
curl -X POST "https://hubvocal.com/v1/webhooks/deliveries/dl_51a3c4/retry" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/webhooks/deliveries/dl_51a3c4/retry", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/webhooks/deliveries/dl_51a3c4/retry",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"ok": true
} Hatalar
404Bu kimlikle teslim yok ya da başarısız değil.
Sesler ve motorlar
Motorları, sesleri ve sınırları listele
GET /v1/voices
Ajan formu kurmak için gereken her şey: motor adları, motor başına geçerli sesler, hız aralıkları, diller, hazır ton seçenekleri, her motorun arkasındaki model ve alan uzunluğu sınırları. Aşağıdaki örnek kısaltıldı.
İstek
curl "https://hubvocal.com/v1/voices" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/voices", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/voices",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"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
}
} Görüşmeler
Saklama süresi organizasyon başına panelden ayarlanır: recordings_days (varsayılan 30), transcripts_days (varsayılan 365) ve pii_redaction. Günlük bir iş süresi dolan kayıtları ve dökümleri siler; görüşme satırı ve maliyeti kalır.
Web widget'ı: herkese açık anahtarlar (pk_…) panelde ajan başına oluşturulur. Widget betiği POST /api/public/web-calls çağırır; ayrıntı Geliştiriciler sayfasındaki rehberde.
Web görüşmesi başlat
POST /v1/web-calls
Tarayıcı görüşmesi için bir oda açar ve kısa ömürlü bir erişim token'ı döner. server_url ve token'ı tarayıcıda livekit-client'a verin; ajan odaya kendisi katılır. Bu ucu kendi sunucunuzdan çağırın, API anahtarı tarayıcıya hiç gitmesin. agent_id yerine tam bir agent nesnesi göndererek taslağı kaydetmeden deneyebilirsiniz.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
agent_id | body | string | Kayıtlı ajanın kimliği. agent göndermiyorsanız zorunlu. |
agent | body | object | Yalnız bu görüşmede kullanılacak tam ajan nesnesi (POST /v1/agents ile aynı alanlar). |
version | body | string | integer | Kullanılacak sürüm: "live" (varsayılan), "draft" ya da bir sürüm numarası. |
İstek
curl -X POST "https://hubvocal.com/v1/web-calls" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "resepsiyon"
}' const res = await fetch("https://hubvocal.com/v1/web-calls", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"agent_id": "resepsiyon"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/web-calls",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"agent_id": "resepsiyon",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"server_url": "wss://hubvocal.com",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
"room": "demo-3f9a1c2e",
"max_seconds": 300
} Hatalar
400agent_id ya da agent gönderilmedi.402Organizasyonun aylık harcama limiti doldu.403Organizasyon askıda.404Bu id ile ajan yok.
Giden telefon araması başlat
POST /v1/calls
Organizasyonunuzun numaralarından biriyle bir numarayı arar; arama cevaplanınca ajan bağlanır. Sağlayıcı (DIDWW, Twilio ya da kendi SIP hattınız) arayan numaraya göre seçilir.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
fromzorunlu | body | string | Organizasyonunuzun numaralarından biri, E.164 biçiminde (+90…). |
tozorunlu | body | string | Aranacak numara, E.164 biçiminde. |
agent_id | body | string | Kullanılacak ajan. Verilmezse arayan numaraya atanmış ajan konuşur. |
version | body | string | integer | Kullanılacak sürüm: "live" (varsayılan), "draft" ya da bir sürüm numarası. |
İstek
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": "resepsiyon"
}' const res = await fetch("https://hubvocal.com/v1/calls", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"from": "+908501234567",
"to": "+905321234567",
"agent_id": "resepsiyon"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.post(
"https://hubvocal.com/v1/calls",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"from": "+908501234567",
"to": "+905321234567",
"agent_id": "resepsiyon",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"room": "tel-out-9c41e0b7",
"provider": "didww",
"sip_call_id": "SCL_7mVt2kQb9xRa"
} Hatalar
400Numara uluslararası biçimde değil ya da arayan numara organizasyonunuzun değil.402Organizasyonun aylık harcama limiti doldu.502Telefon sağlayıcısı aramayı reddetti.
Görüşmeleri listele
GET /v1/calls
Görüşmeler, yeniden eskiye; web ve telefon birlikte. quality tarayıcı ölçümünün özetidir, telefon görüşmelerinde null. ended_by: caller, agent, max_call_seconds, caller_unresponsive, agent_unresponsive, no_answer ya da unknown. channel: web, phone_in ya da phone_out. Her satırda ayrıca outcome ve summary_text (özetin ilk 160 karakteri) bulunur. Görüşmeyi canlı konsoldan bir yönetici bitirdiyse ended_by supervisor olur.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
limit | query | integer | Varsayılan 50, en fazla 500. |
agent | query | string | Yalnız bu ajanın görüşmeleri (ajan adı). |
outcome | query | string | Yalnız bu sonuçtaki görüşmeler. |
İstek
curl "https://hubvocal.com/v1/calls?limit=20" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/calls?limit=20", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/calls",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
params={
"limit": 20,
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
[
{
"room": "demo-8585522d",
"org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
"org_name": "Örnek Klinik",
"channel": "web",
"profile": "Resepsiyon",
"engine": "live",
"lang": "tr",
"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": "Arayan perşembe öğleden sonra için randevu istedi; geri arama için mesaj alındı.",
"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": "Temiz: kayıp ve boşluk yok.",
"protocol": "UDP",
"loss_pct": 0,
"conceal_pct": 0,
"jitter_ms": 4,
"rtt_ms": 38
}
}
] Görüşme detayı
GET /v1/calls/{room}
Görüşmenin tam kaydı: sağlayıcı başına maliyet kırılımı, döküm, karşılama zamanlaması, ajan tarafı kaynak boşlukları ve 2 saniyelik pencerelerle tarayıcı kalite zaman çizelgesi. Maliyet alanları motora göre değişir (live, llm, stt, tts, realtime…); her biri usd içerir. source_gaps.events [saniye, ms] çiftleridir. summary; text, outcome (resolved, message_taken, transferred, unresolved, no_conversation, spam), sentiment, topics ve action_items içerir. supervisors canlı konsoldan görüşmeye kimin, hangi kiplerde katıldığını listeler. recording; available, duration_s ve size_bytes içerir. extracted ajanın post_call.fields alanlarının değerlerini tutar (konuşulmadıysa null).
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
roomzorunlu | path | string | Görüşme listesinden ya da POST /v1/web-calls yanıtından oda adı. |
İstek
curl "https://hubvocal.com/v1/calls/demo-8585522d" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/calls/demo-8585522d", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/calls/demo-8585522d",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"call": {
"room": "demo-8585522d",
"org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
"org_name": "Örnek Klinik",
"channel": "web",
"profile": "Resepsiyon",
"engine": "live",
"lang": "tr",
"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": "Arayan perşembe öğleden sonra için randevu istedi; geri arama için mesaj alındı.",
"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": "Temiz: kayıp ve boşluk yok.",
"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": "Arayan perşembe öğleden sonra için randevu istedi; geri arama için mesaj alındı.",
"language": "tr",
"outcome": "message_taken",
"sentiment": "neutral",
"topics": [
"randevu"
],
"action_items": [
"Arayanı perşembe sabahı geri ara"
]
},
"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": "Merhaba, kliniğimizi aradığınız için teşekkürler. Size nasıl yardımcı olabilirim?",
"t": 2.4,
"interrupted": false
},
{
"role": "user",
"text": "Perşembe öğleden sonra randevu almak istiyorum.",
"t": 9.8
}
]
},
"quality": {
"summary": {
"verdict": "Temiz: kayıp ve boşluk yok.",
"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"
}
]
}
} Hatalar
404Görüşme bulunamadı.
Kaydı indir
GET /v1/calls/{room}/recording
Görüşmenin sesi, OGG/Opus olarak. Range isteklerini destekler. Görüşme kaydedilmediyse ya da kaydın süresi dolduysa 404.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
roomzorunlu | path | string | Görüşme listesinden ya da POST /v1/web-calls yanıtından oda adı. |
İstek
curl "https://hubvocal.com/v1/calls/demo-8585522d/recording" \
-H "Authorization: Bearer $VT_API_KEY" \
-o call.ogg import fs from "node:fs";
const res = await fetch("https://hubvocal.com/v1/calls/demo-8585522d/recording", {
headers: { Authorization: `Bearer ${process.env.VT_API_KEY}` },
});
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).detail}`);
fs.writeFileSync("call.ogg", Buffer.from(await res.arrayBuffer())); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/calls/demo-8585522d/recording",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=60,
)
resp.raise_for_status()
with open("call.ogg", "wb") as f:
f.write(resp.content) Yanıt · 200
HTTP/1.1 200 OK
Content-Type: audio/ogg
Accept-Ranges: bytes
Content-Length: 201344
<OGG/Opus> Hatalar
404Görüşme kaydedilmedi ya da kaydın süresi doldu.
Görüşmeyi sil
DELETE /v1/calls/{room}
Görüşmenin kaydını, dökümünü ve özetini hemen siler; örneğin bir KVKK ya da GDPR talebi için. Görüşme satırı ve maliyeti kalır.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
roomzorunlu | path | string | Görüşme listesinden ya da POST /v1/web-calls yanıtından oda adı. |
İstek
curl -X DELETE "https://hubvocal.com/v1/calls/demo-8585522d" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/calls/demo-8585522d", {
method: "DELETE",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.delete(
"https://hubvocal.com/v1/calls/demo-8585522d",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"deleted": "demo-8585522d"
} Hatalar
404Görüşme bulunamadı.
Görüşmeleri dışa aktar (CSV)
GET /v1/calls/export
Bir tarih aralığındaki görüşmeler CSV olarak, görüşme başına bir satır; yapılandırılmış alanlar ek sütunlar olarak.
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
formatzorunlu | query | string | Yalnız csv. |
from | query | date | YYYY-AA-GG, dahil. |
to | query | date | YYYY-AA-GG, dahil. |
agent_id | query | string | Yalnız bu ajanın görüşmeleri. |
İstek
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 import fs from "node:fs";
const res = await fetch("https://hubvocal.com/v1/calls/export?format=csv&from=2026-11-01&to=2026-11-05", {
headers: { Authorization: `Bearer ${process.env.VT_API_KEY}` },
});
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).detail}`);
fs.writeFileSync("calls.csv", Buffer.from(await res.arrayBuffer())); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/calls/export",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
params={
"format": "csv",
"from": "2026-11-01",
"to": "2026-11-05",
},
timeout=60,
)
resp.raise_for_status()
with open("calls.csv", "wb") as f:
f.write(resp.content) Yanıt · 200
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 Telefon numaraları
Numaraları listele
GET /v1/numbers
Organizasyonunuzun numaraları ve her birine cevap veren ajan (profile_id); ayrıca her telefon sağlayıcısının hazır olup olmadığı. Numaraları platform ekibi ekler; ajanı siz atarsınız.
İstek
curl "https://hubvocal.com/v1/numbers" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/numbers", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/numbers",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"numbers": [
{
"number": "+908501234567",
"provider": "didww",
"org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
"org_name": "Örnek Klinik",
"profile_id": "resepsiyon",
"label": "Ana hat"
}
],
"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
}
}
}
} Numaraya ajan ata
PUT /v1/numbers/{number}
Bu numaraya gelen aramalara cevap verecek ajanı seçer. Atamayı kaldırmak için agent_id: null gönderin. Yoldaki numaranın + işaretini %2B olarak yazın (00 öneki de olur).
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
numberzorunlu | path | string | E.164 biçiminde, URL kodlanmış numara. |
agent_id | body | string | null | Gelen aramalara cevap verecek ajan. |
label | body | string | Ekibiniz için kısa not, en fazla 60 karakter. |
İstek
curl -X PUT "https://hubvocal.com/v1/numbers/%2B908501234567" \
-H "Authorization: Bearer $VT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "resepsiyon",
"label": "Ana hat"
}' const res = await fetch("https://hubvocal.com/v1/numbers/%2B908501234567", {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"agent_id": "resepsiyon",
"label": "Ana hat"
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.put(
"https://hubvocal.com/v1/numbers/%2B908501234567",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
json={
"agent_id": "resepsiyon",
"label": "Ana hat",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"ok": true
} Hatalar
400Seçilen ajan yok.404Numara organizasyonunuza ait değil.
Tüketim
Tüketim
GET /v1/usage
Organizasyonunuzun görüşme, dakika ve sağlayıcı maliyeti; sağlayıcıya ve güne göre (Europe/Istanbul). Varsayılan aralık bu ay. kind: llm, tts, stt ya da voice (ses-sese motorlar).
| Ad | Yer | Tür | Açıklama |
|---|---|---|---|
from | query | date | YYYY-AA-GG, dahil. |
to | query | date | YYYY-AA-GG, dahil. |
İstek
curl "https://hubvocal.com/v1/usage?from=2026-11-01&to=2026-11-05" \
-H "Authorization: Bearer $VT_API_KEY" const res = await fetch("https://hubvocal.com/v1/usage?from=2026-11-01&to=2026-11-05", {
headers: {
Authorization: `Bearer ${process.env.VT_API_KEY}`,
},
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import os
import requests
resp = requests.get(
"https://hubvocal.com/v1/usage",
headers={"Authorization": f"Bearer {os.environ['VT_API_KEY']}"},
params={
"from": "2026-11-01",
"to": "2026-11-05",
},
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"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": "Örnek Klinik",
"usd": 3.94,
"minutes": 81.2,
"calls": 42
}
]
} Tanım
OpenAPI tanımı
GET /v1/openapi.json Anahtar gerekmez
Bu API'nin OpenAPI 3.1 belgesi. Anahtar gerekmez. Postman, Insomnia ya da bir istemci üreticisine aktarabilirsiniz.
İstek
curl "https://hubvocal.com/v1/openapi.json" const res = await fetch("https://hubvocal.com/v1/openapi.json");
const data = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${data.detail}`);
console.log(data); import requests
resp = requests.get(
"https://hubvocal.com/v1/openapi.json",
timeout=30,
)
if not resp.ok:
raise RuntimeError(f"{resp.status_code}: {resp.json()['detail']}")
print(resp.json()) Yanıt · 200
{
"openapi": "3.1.0",
"info": {
"title": "HubVocal API",
"version": "1.0.0"
},
"servers": [
{
"url": "https://hubvocal.com/v1"
}
],
"paths": {}
}