Recordings

บันทึกการสนทนา + transcript + summary

Recordings

หน่วยข้อมูลหลักของระบบ — บันทึกการสนทนาหนึ่งสาย พร้อม transcript + summary

Account key: ทุก request ด้านล่างต้องส่ง X-Business-Id: <business id> เพื่อเลือก business ที่จะทำงานด้วย (ถ้าไม่ส่งจะได้ 400 business_required) ส่วน business key ไม่สนใจ header นี้เพราะผูกกับ business เดียวอยู่แล้ว ดูเพิ่มที่ Getting started → API Key ระดับบัญชี

GET /recordings

List recording แบบ paginated

Scopes: view_recording_all · view_recording_self

ParamTypeNote
limitint 1-200default 20
offsetintdefault 0
direction"in" | "out"optional
sourceProviderthreecx | dtac | uploadoptional
callDateFromISO 8601 datetimeoptional
callDateToISO 8601 datetimeoptional
customerPhonestring (exact match)optional
customerPhoneNormalizedstring (exact match)optional
tagnormal | short | wrong_or_spam | no_answer | other | nonenone = ยังไม่ติด tag
scoreMinint 0-100เฉพาะ row ที่มี score
scoreMaxint 0-100เฉพาะ row ที่มี score
searchstringilike ครอบ dataId, customerPhone, customerPhoneNormalized, callcenterNumber, callcenterName
sortBycallAt | duration | scoredefault callAt
sortDirasc | descdefault desc; null อยู่ท้ายสุด, tiebreak callAt desc
agentKeystring, ส่งซ้ำได้ (สูงสุด 500)เอาเฉพาะสายของ agent เหล่านี้ — เทียบกับ COALESCE(callcenterNumber, callcenterName) (key เดียวกับที่ /recordings/agents คืน) เช่น ?agentKey=%2B66804972699&agentKey=Somchai
curl "https://phone.mcloud.co.th/api/v1/recordings?limit=10&direction=in&sortBy=score&sortDir=desc" \
  -H "Authorization: Bearer crk_..."
{
  "items": [
    {
      "id": "0192b9...",
      "dataId": "rec_2026_05_20_001",
      "callAt": "2026-05-20T08:14:00+07:00",
      "direction": "in",
      "customerPhone": "+66812345678",
      "customerPhoneNormalized": "0812345678",
      "tag": "normal",
      "score": 86,
      "processingStatus": "completed",
      "audioUrl": "/api/recording/audio/0192b9...",
      "transcriptUrl": "/api/recording/transcript/0192b9...",
      "summaryUrl": "/api/recording/summary/0192b9..."
    }
  ],
  "total": 1284,
  "limit": 10,
  "offset": 0
}

GET /recordings/stats

รวมสถิติ call recording ตามช่วงเวลา — ยอดรวม, จำนวนสายต่อวัน, การกระจาย score, ชั่วโมงที่สายเข้าหนาแน่น, และ top performer

Scopes: view_recording_all · view_recording_self

ParamTypeNote
dateFromISO 8601 datetimeoptional
dateToISO 8601 datetimeoptional
customerPhoneNormalizedstring (exact match)optional
tzIANA timezonedefault Asia/Bangkok — ใช้แบ่ง bucket วัน/ชั่วโมง
agentKeystring, ส่งซ้ำได้ (สูงสุด 500)เอาเฉพาะสายของ agent เหล่านี้ (ความหมายเดียวกับ endpoint list)
curl "https://phone.mcloud.co.th/api/v1/recordings/stats?dateFrom=2026-05-01T00:00:00%2B07:00&tz=Asia/Bangkok" \
  -H "Authorization: Bearer crk_..."
{
  "totals": {
    "total": 1284,
    "inbound": 902,
    "outbound": 382,
    "avgDurationMs": 184320.5,
    "longestMs": 1432000,
    "avgScore": 78.4,
    "firstCallAt": "2026-05-01T08:12:00+07:00",
    "lastCallAt": "2026-05-31T19:45:00+07:00"
  },
  "daily": [{ "day": "2026-05-01", "count": 41 }],
  "scoreDistribution": { "good": 612, "mid": 388, "low": 96 },
  "peakHours": [{ "hour": 0, "count": 3 }],
  "topPerformers": [
    { "name": "Somchai", "calls": 214, "avgDurationMs": 176000, "avgScore": 81.2 }
  ]
}
  • scoreDistribution: good ≥ 70, mid 40–69.99, low < 40 (เฉพาะ row ที่มี score)
  • peakHours: มีครบ 24 ชั่วโมง (0–23, เติม 0 ให้ชั่วโมงที่ไม่มีสาย)
  • topPerformers: top 10 callcenter name เรียงตามจำนวนสาย

POST /recordings

Ingest metadata + presigned upload (optional) — idempotent ด้วย dataId

Scopes: manage_call_recording

ParamTypeNote
dataIdstring uniquerequired
callAtISO 8601required
direction"in" | "out"required
customerPhonestringoptional
callcenterNumberstringoptional
callcenterNamestringoptional
tagenumoptional
scorenumber 0-100optional
notestringoptional
contentTypestring (MIME)default audio/wav
audioPresignedUploadUrlbooleanขอ presigned URL?
curl -X POST https://phone.mcloud.co.th/api/v1/recordings \
  -H "Authorization: Bearer crk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "dataId": "rec_2026_05_20_001",
    "callAt": "2026-05-20T08:14:00+07:00",
    "direction": "in",
    "audioPresignedUploadUrl": true
  }'

GET /recordings/{id}

ดึง recording เดียว

Scopes: view_recording_all · view_recording_self

PATCH /recordings/{id}

Review — score / tag / comment / note / link

Scopes: manage_recording_review · manage_recording_link

ParamTypeNote
scorenumber 0-100optional
tagnormal | short | wrong_or_spam | no_answer | otheroptional
reviewCommentstringoptional
notestringoptional
linkedUserIduuid | nullrequires manage_recording_link

DELETE /recordings/{id}

Soft-delete (ย้ายไป trash, เก็บ 30 วัน)

Scopes: manage_call_recording

POST /recordings/{id}/reextract

สั่ง AI ทำงานใหม่ (ถอดเสียง + สรุป)

Scopes: manage_call_recording

curl -X POST https://phone.mcloud.co.th/api/v1/recordings/$ID/reextract \
  -H "Authorization: Bearer crk_..."

POST /recordings/analyze

วิเคราะห์ไฟล์เสียงแบบ synchronous — อัปโหลดเสียง รัน AI แล้วคืนผลลัพธ์ทั้งหมดพร้อมค่าใช้จ่ายที่คิดเงินแล้วในครั้งเดียว (รอจนเสร็จ) ไฟล์จะถูกบันทึกและแสดงใน dashboard ใช้เวลาประมาณ 1–4 นาที ให้ตั้ง client timeout ยาวๆ

Scopes: manage_call_recording

body เป็น multipart/form-data (ไม่ใช่ JSON)

ParamTypeNote
filefile (multipart)required — ไฟล์เสียง wav/mp3/m4a/mp4/aac/ogg/opus/webm/flac, ≤50MB
direction"in" | "out"optional, default "in"
customerPhonestringoptional
callcenterNamestringoptional
callcenterNumberstringoptional
notestringoptional
callAtISO 8601optional, default = เวลาปัจจุบัน
curl -X POST https://phone.mcloud.co.th/api/v1/recordings/analyze \
  -H "Authorization: Bearer crk_..." \
  -H "X-Business-Id: <business uuid, account keys only>" \
  -F "file=@call.wav" \
  -F "direction=in" \
  -F "customerPhone=+66812345678"
{
  "recordingId": "0190f7b2-...",
  "dataId": "api-2f1c...",
  "status": "completed",
  "result": {
    "transcript": "แอดมิน: สวัสดีค่ะ...\nลูกค้า: ...",
    "segments": [
      { "index": 0, "start_ms": 0, "end_ms": 2400, "speaker": "admin", "text": "สวัสดีค่ะ", "emotion": "neutral", "tone": "polite", "coaching": "" }
    ],
    "summary": "ลูกค้าสอบถามโปรโมชั่น...",
    "recommendations": "ควรเสนอ...",
    "score": 86,
    "tag": "normal",
    "overallEmotion": "positive",
    "overallTone": "friendly"
  },
  "cost": { "chargedThb": 0.1234, "currency": "THB" },
  "durationMs": 73210
}

cost.chargedThb คือยอดที่คิดเงินกับธุรกิจ (ราคาสุทธิ) ระบบจะไม่เปิดเผยต้นทุนดิบ อัตรา หรือรุ่น AI

Error ที่เป็นไปได้: 402 insufficient_credit, 413 audio_file_too_large, 415 audio_unsupported_format, 422 audio_file_required, 503 worker_unavailable, 504 extraction_timeout

GET /recordings/agents

รายชื่อ callcenter agent ทั้งหมดที่พบใน recording ของ business นี้ พร้อมจำนวนสาย — นำ key ที่ได้ไปใช้เป็น filter agentKey กับ endpoint list และ stats ได้เลย (key คือ COALESCE(callcenterNumber, callcenterName))

Scopes: view_recording_all · view_recording_self

curl https://phone.mcloud.co.th/api/v1/recordings/agents \
  -H "Authorization: Bearer crk_..."
{
  "items": [
    {
      "key": "+66804972699",
      "name": "66804972699 FIN4YOU 07",
      "number": "+66804972699",
      "calls": 412,
      "lastCallAt": "2026-06-09T14:13:53.000Z"
    }
  ],
  "total": 7
}

PATCH /recordings/agents/{extension}

ตั้งหรือล้างป้ายชื่อ (label) ของ callcenter agent — เหมือนการแก้ label บนการ์ดในหน้าทีม โดย {extension} คือ number ของ agent ที่ได้จาก endpoint list (ต้อง URL-encode เช่น +66804972699%2B66804972699) ป้ายชื่อใหม่จะ cascade ไปยังทุก recording ที่มี callcenter_number เดียวกัน ทำให้ leaderboard, รายการสาย และหัว player แสดงชื่อใหม่ทันที

ส่ง customName: null เพื่อล้าง override แล้วกลับไปใช้ชื่อที่ provider ตั้งให้

Scope: manage_recording_link

fieldtypenotes
customNamestring (1–128) | null, requiredป้ายชื่อใหม่ — ส่ง null เพื่อล้าง override
curl -X PATCH "https://phone.mcloud.co.th/api/v1/recordings/agents/%2B66804972699" \
  -H "Authorization: Bearer crk_..." \
  -H "Content-Type: application/json" \
  -d '{"customName":"ทีมขาย A"}'
{
  "ok": true,
  "extension": "+66804972699",
  "customName": "ทีมขาย A",
  "effectiveName": "ทีมขาย A"
}

จะคืน 404 extension_not_found เมื่อไม่พบ extension นี้ใน business

GET /recordings/prompt-config

อ่าน config การวิเคราะห์สายด้วย AI ของ business — บริบทธุรกิจที่ AI ใช้เป็น persona, คำอธิบาย tag ทั้ง 4 ประเภท และเกณฑ์การให้คะแนนแบบถ่วงน้ำหนัก (เป็น config เดียวกับที่หน้า /app/prompt ในแอปใช้จัดการ) AI จะนำไปประกอบเป็น persona ทุกครั้งที่ถอดเสียง/วิเคราะห์สาย · business ที่ยังไม่เคยตั้งค่าจะได้ค่าเริ่มต้น (คำอธิบาย tag + เกณฑ์รวม 100 คะแนน) โดย businessName จะ fallback เป็นชื่อ business

Scopes: manage_recording_prompt · view_recording_all

curl "https://phone.mcloud.co.th/api/v1/recordings/prompt-config" \
  -H "Authorization: Bearer crk_..."
{
  "businessName": "Acme Co.",
  "businessAbout": "ขายอสังหาริมทรัพย์ ลูกค้าเป็นกลุ่มครอบครัว",
  "businessProducts": "บ้านเดี่ยว, ทาวน์โฮม, คอนโด",
  "tagDescriptions": {
    "normal": "บทสนทนาปกติ มีเนื้อหา/ติดต่อธุรกิจจริง",
    "short": "สายสั้นมาก ไม่มีเนื้อหา หรือวางสายก่อนพูดจบ",
    "wrong_or_spam": "โทรผิด สายขายของ spam สแกม หรือไม่เกี่ยวกับธุรกิจ",
    "no_answer": "สายที่ไม่มีคนรับ ไม่มีบทสนทนา (missed call)",
    "other": "อื่นๆ ที่ไม่เข้ากลุ่มข้างบน"
  },
  "scoreCategories": [
    { "label": "การทักทายและมารยาท", "maxPoints": 20 },
    { "label": "การสอบถามข้อมูลครบถ้วน", "maxPoints": 30 },
    { "label": "การจัดการข้อโต้แย้ง", "maxPoints": 20 },
    { "label": "การปิดการสนทนา/นัดหมาย", "maxPoints": 30 }
  ],
  "updatedAt": "2026-06-10T04:54:12.745Z",
  "updatedBy": null
}

PUT /recordings/prompt-config

บันทึก/อัปเดต config การวิเคราะห์ด้วย AI (1 แถวต่อ 1 business) · ช่องบริบทธุรกิจที่เว้นว่างจะถูกเก็บเป็น null แล้ว businessName จะ fallback เป็นชื่อ business · scoreCategories มีได้ 1–20 หมวด · endpoint ตรวจรูปแบบข้อมูลแต่ไม่บังคับให้ผลรวมน้ำหนักเท่ากับ 100 (ตัว editor ในแอปบังคับให้เอง)

Scope: manage_recording_prompt

fieldtypenotes
businessNamestring (≤200)ชื่อที่ AI ใช้ — เว้นว่าง → fallback เป็นชื่อ business
businessAboutstring (≤4000)ธุรกิจทำเกี่ยวกับอะไร (บริบทให้ AI)
businessProductsstring (≤4000)สินค้า/บริการที่พูดถึงในสาย
tagDescriptionsobject, requiredต้องครบ 5 คีย์: normal, short, wrong_or_spam, no_answer, other (แต่ละค่า ≤1000)
scoreCategoriesarray 1–20, requiredแต่ละหมวด { label (1–200), maxPoints (1–100 จำนวนเต็ม) }
curl -X PUT "https://phone.mcloud.co.th/api/v1/recordings/prompt-config" \
  -H "Authorization: Bearer crk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "Acme Co.",
    "businessAbout": "ขายอสังหาริมทรัพย์ ลูกค้าเป็นกลุ่มครอบครัว",
    "businessProducts": "บ้านเดี่ยว, ทาวน์โฮม, คอนโด",
    "tagDescriptions": {
      "normal": "บทสนทนาปกติ",
      "short": "สายสั้นมาก",
      "wrong_or_spam": "โทรผิด/สแปม",
      "no_answer": "ไม่รับสาย",
      "other": "อื่นๆ"
    },
    "scoreCategories": [
      { "label": "การทักทายและมารยาท", "maxPoints": 50 },
      { "label": "การปิดการสนทนา/นัดหมาย", "maxPoints": 50 }
    ]
  }'
{ "ok": true }

จะคืน 422 validation_failed เมื่อข้อมูลไม่ถูกต้อง — เช่น ขาด tag key, scoreCategories ว่าง, หรือ maxPoints อยู่นอกช่วง 1–100

เอกสาร API