โทรออก
การโทรแต่ละแบบมี endpoint ของตัวเอง เลือกตามสิ่งที่ต้องการให้เกิดขึ้นเมื่อปลายสายรับ
| แบบ | Route | เมื่อปลายสายรับ | ผลตอบกลับ |
|---|---|---|---|
| Dial | POST /telephony/call/dial | ไม่มีเสียงเล่น ใช้สายนี้เพื่อพักหรือโอนต่อ | 202 queued |
| TTS | POST /telephony/call/tts | อ่านข้อความ แล้ววางสาย | 202 queued |
| Agent | POST /telephony/call/agent | AI agent คุยกับปลายสาย | 201 ringing |
| Survey | POST /telephony/call/survey | ถามคำถามและส่งคำตอบกลับมาให้คุณ | 202 หรือ 201 |
| Flow | POST /telephony/call/flow | ยังใช้ไม่ได้ — สายดัง แต่ยังไม่รัน flow | 201 ringing |
| Batch | POST /telephony/call/batch | โทรแบบ TTS หรือ dial หนึ่งสายต่อหนึ่งเบอร์ | 202 queued |
ติดตามทุกสายได้ด้วย GET /telephony/call/{call_uuid}
API key ต้องมีสิทธิ์ voice.originate ส่วนการโทรหาเบอร์ต่อภายใน (POST /telephony/call/extension) ต้องใช้ผู้ใช้ที่ลงชื่อเข้าใช้ เพราะ API key ไม่มีเครื่องโทรศัพท์ให้ดัง
แต่ละ endpoint รับเฉพาะฟิลด์ของตัวเอง
ฟิลด์ของการโทรแบบอื่นจะถูกปฏิเสธด้วย 400 พร้อมบอก endpoint ที่ถูกต้อง เช่น survey belongs to POST /telephony/call/surveyPOST /telephony/call แบบเดิมยังใช้กับ dial, TTS, agent, flow และ extension ได้ แต่เลิกแนะนำแล้ว และทำแบบสำรวจไม่ได้
โทรหาใคร และโทรจากเบอร์ไหน
การโทรหาเบอร์ทุกแบบใช้ฟิลด์ปลายทางชุดเดียวกัน
| ฟิลด์ | ชนิด | หมายเหตุ |
|---|---|---|
destination | string | จำเป็น เบอร์ที่จะโทร ในรูปแบบ E.164 (+66812345678) |
caller_id | string | ไม่บังคับ เบอร์ของคุณที่จะแสดงให้ปลายสายเห็น |
caller_identity_id | string | ไม่บังคับ ใช้ caller identity ที่บันทึกไว้แทน caller_id |
caller_extension_uuid | string | ไม่บังคับ โทรออกในนามเบอร์ของ extension นี้ |
trunk | string | ไม่บังคับ บังคับใช้ trunk ที่ระบุ |
organization_id | string | ใช้เมื่อเรียกด้วย token ของผู้ใช้เท่านั้น API key ระบุองค์กรอยู่แล้ว |
Dial, TTS และ batch รับ mode ได้ด้วย: "queue" (ค่าเริ่มต้น) รอจนมีสายว่าง ส่วน "instant" โทรทันที หรือตอบ 429 เมื่อไม่มีสายว่าง
ลองใหม่อย่างปลอดภัยด้วย Idempotency-Key
ส่ง header Idempotency-Key ทุกครั้งที่โทรออก หากส่งซ้ำด้วย key เดิม ระบบจะคืนสายแรกแทนการโทรหาปลายสายซ้ำ SDK ทางการส่ง key ให้อัตโนมัติ และใช้ key เดิมเมื่อ SDK ลองใหม่เอง
curl -X POST "$ME_BASE/telephony/call/tts" \
-H "API-Key: $ME_API_KEY" \
-H "X-TenantID: $ME_TENANT" \
-H "Idempotency-Key: order-1042-reminder" \
-H "Content-Type: application/json" \
-d '{
"destination": "+66812345678",
"tts": { "text": "คำสั่งซื้อ 1042 กำลังนำส่ง", "voice_id": "eve", "language": "th" }
}'{
"kind": "pstn",
"call": { "call_uuid": "5d2c…", "destination": "+66812345678", "status": "queued" }
}tts รับ text และ voice_id และรับ provider, language และ repeat (จำนวนครั้งที่เล่น 0 คือเล่นครั้งเดียว) ได้ด้วย
ต่อสายให้ AI agent
{
"destination": "+66812345678",
"agent": { "id": "agent_support_th" },
"gather": {
"parameters": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"]
},
"callback_url": "https://example.com/hooks/order"
}
}agent.id คือ agent ที่บันทึกไว้ (ใส่ config_mode: "draft" เพื่อใช้ฉบับร่าง) ส่วน system_prompt, voice และ language ใช้แทนค่าของ agent เฉพาะสายนี้ gather ไม่บังคับ agent จะถามข้อมูลตาม parameters แล้วส่งคำตอบกลับมา ดู รับคำตอบ
ทำแบบสำรวจ
แบบสำรวจจะโทรหาเบอร์ ถามคำถามของคุณ แล้วส่งคำตอบกลับมา ทำได้สองแบบ
กดปุ่ม ("mode": "dtmf")
ระบบอ่านคำถามทีละข้อ แล้วปลายสายตอบด้วยการกดปุ่มหนึ่งปุ่ม
{
"destination": "+66812345678",
"survey": {
"mode": "dtmf",
"survey_id": "csat_q3",
"greeting": "ขอบคุณที่ใช้บริการค่ะ",
"questions": [
{ "key": "score", "prompt": "พึงพอใจแค่ไหน กด 1 ถึง 5", "min": 1, "max": 5 },
{ "key": "would_return", "prompt": "จะกลับมาใช้บริการอีกไหม กด 1 ไม่ กด 2 ใช่", "min": 1, "max": 2, "required": false }
],
"retry_prompt": "กดได้ตั้งแต่ {min} ถึง {max} กดใหม่อีกครั้ง",
"closing": "ขอบคุณค่ะ สวัสดีค่ะ",
"tts": { "provider": "xai", "voice_id": "eve", "language": "th" },
"callback_url": "https://example.com/hooks/survey"
}
}| ฟิลด์ | หมายเหตุ |
|---|---|
questions | จำเป็น สูงสุด 20 ข้อ ถามตามลำดับ แต่ละข้อรับปุ่มเดียวระหว่าง min ถึง max (0–9) |
key | ตัวพิมพ์เล็ก ตัวเลข และ _ ขึ้นต้นด้วยตัวอักษร ใช้เป็นชื่อของคำตอบ |
required | ค่าเริ่มต้น true ถ้าข้อบังคับไม่ได้รับคำตอบ สายจะจบ ส่วนข้อไม่บังคับจะข้ามไป |
retry_prompt | พูดก่อนถามซ้ำ เมื่อกดปุ่มนอกช่วงของข้อนั้น โดยเติม {min} และ {max} ให้ ถ้าไม่ระบุจะถามคำถามซ้ำเลย ปลายสายกดได้ 3 ครั้ง |
survey_id | จัดกลุ่มคำตอบในรายงานแบบสำรวจ คำตอบแต่ละข้อบันทึกเป็น <survey_id>.<key> เช่น csat_q3.score แต่ละข้อจึงคงสเกลของตัวเอง ค่าเริ่มต้น telephony_survey |
tts | เสียงที่ใช้อ่านทุกข้อความ: provider, voice_id, language, instructions ผู้ให้บริการที่ใช้ไม่ได้จะถูกปฏิเสธด้วย 400 ก่อนเข้าคิว |
แบบสำรวจแบบกดปุ่มจะเข้าคิว ผลตอบกลับคือ 202 พร้อม status: "queued"
ให้คำตอบที่ดีกว่าอยู่บนปุ่มที่สูงกว่า
รายงานแบบสำรวจนับว่าพึงพอใจเมื่อคะแนนอยู่ในสองอันดับบนของสเกล สำหรับคำถามใช่/ไม่ ให้ ใช่ อยู่บนปุ่มที่สูงกว่า (1 ไม่ 2 ใช่) รายงานจะอ่านได้ตรงตามที่คาด
พูดตอบ ("mode": "agent" ค่าเริ่มต้น)
AI agent ถามข้อมูลตาม parameters ด้วยเสียง และวางสายเมื่อได้คำตอบที่จำเป็นครบและถูกต้อง สายจะดังทันที ผลตอบกลับคือ 201
{
"destination": "+66812345678",
"survey": {
"greeting": "สวัสดีค่ะ ขอเวลาทำแบบสำรวจสั้น ๆ",
"parameters": {
"type": "object",
"properties": {
"rating": { "type": "integer", "x-parse": "integer" },
"comment": { "type": "string" }
},
"required": ["rating"]
},
"language": "th",
"callback_url": "https://example.com/hooks/survey"
}
}x-parse กำหนดรูปแบบคำตอบที่ agent ส่งกลับของแต่ละฟิลด์: text, integer, number, boolean, date, phone หรือ email ฟิลด์ของแบบกดปุ่ม (questions, closing, retry_prompt, survey_id, tts) จะถูกปฏิเสธในโหมดนี้
รับคำตอบ
คำตอบจาก gather หรือแบบสำรวจส่งถึงคุณสองทาง ด้วย body เดียวกัน
- Webhook — event
call.ai_gather.endedใน webhook ของ workspace ส่งเมื่อสายที่มีคนรับจบลง พร้อมstatusเป็นvalidหรือincomplete callback_url— ส่งเฉพาะเมื่อคำตอบที่จำเป็นครบและvalidทั้งหมด พร้อมลายเซ็น:X-webhook-signatureคือ HMAC-SHA256 แบบ base64 ของ body ดิบ โดยใช้call.gather.callback_secretจากผลตอบกลับตอนโทร (หรือcallback_secretที่คุณส่งมา) เป็น key
{
"event": "call.ai_gather.ended",
"id": "evt_…",
"created_at": "2026-09-25T09:30:12Z",
"workspace_id": "org_…",
"gather_id": "…",
"session_uuid": "…",
"status": "valid",
"result": { "score": 4, "would_return": 2 }
}จับคู่ gather_id กับ call.gather.gather_id จากผลตอบกลับตอนโทร
โทรหลายเบอร์
{
"destinations": ["+66811111111", "+66822222222"],
"tts": { "text": "วันนี้สำนักงานปิดทำการ", "voice_id": "eve", "language": "th" }
}{ "queued": 2, "total": 2, "calls": [{ "destination": "+66811111111", "call": { "call_uuid": "…", "status": "queued" } }] }เบอร์ที่เข้าคิวไม่ได้จะมี error ในรายการของเบอร์นั้น เบอร์อื่นยังโทรออกตามปกติ
สถานะของสาย
curl "$ME_BASE/telephony/call/$CALL_UUID" \
-H "API-Key: $ME_API_KEY" -H "X-TenantID: $ME_TENANT"{ "call_uuid": "5d2c…", "room": "…", "destination": "+66812345678", "status": "completed", "handled_by_ai": false, "duration_secs": 42 }status เปลี่ยนจาก pending, ringing และ in_progress แล้วจบที่ completed, no_answer, failed หรือ canceled
SDK
res, err := c.Telephony.Survey(ctx, &sdk.SurveyCallRequest{
DialTarget: sdk.DialTarget{Destination: "+66812345678"},
Survey: &sdk.Survey{
Mode: sdk.SurveyModeDTMF,
SurveyID: "csat_q3",
Questions: []sdk.SurveyQuestion{{Key: "score", Prompt: "กด 1 ถึง 5", Min: 1, Max: 5}},
},
})const res = await me.telephony.survey({
destination: "+66812345678",
survey: { mode: "dtmf", survey_id: "csat_q3", questions: [{ key: "score", prompt: "กด 1 ถึง 5", min: 1, max: 5 }] },
});SDK ทุกภาษามีบริการ telephony เหมือนกัน: dial, tts, agent, survey, flow, extension, batch และ status
