เริ่มต้นใช้งาน
REXcord API ให้ธุรกิจส่งสายเข้าระบบ ค้นหาสาย ดูบทถอดเสียงและสรุป และสั่งให้ AI ประมวลผลใหม่ได้ ทุก endpoint ทำงานกับธุรกิจที่เป็นเจ้าของ API key เท่านั้น
| ค่า | รายละเอียด |
|---|---|
| Base URL | https://phone.mcloud.co.th/api/v1 |
| Auth | Authorization: Bearer crk_... |
| Content | application/json |
| Rate limit | 600 req / min |
# ทดสอบว่า API token ใช้งานได้
curl https://phone.mcloud.co.th/api/v1/meta/whoami \
-H "Authorization: Bearer crk_..."
Quickstart
เรียก API ครั้งแรกได้ใน 5 นาที
1. สร้าง API key
ในหน้าเว็บ ไปที่ ธุรกิจ → API key แล้วสร้าง API key พร้อมเลือก scope ระบบจะแสดง API key ครั้งเดียว — คัดลอกแล้วเก็บไว้ในที่ปลอดภัย
2. ตรวจสอบ API key
เรียก /meta/whoami ก่อน — ถ้าได้ 200 พร้อมข้อมูลธุรกิจและ scope กลับมา แปลว่าตั้งค่าถูกต้องแล้ว
3. ส่งสายเข้าระบบ
ส่ง metadata มาที่ POST /recordings พร้อม audioPresignedUploadUrl: true — เซิร์ฟเวอร์จะตอบ presigned URL กลับมา ให้คุณ PUT ไฟล์เสียงขึ้นที่เก็บไฟล์ได้โดยตรง
4. สั่ง AI วิเคราะห์
เรียก POST /recordings/{id}/reextract เพื่อให้ระบบถอดเสียงและสรุปสายใหม่ ตามการตั้งค่าที่ธุรกิจเลือกไว้
# 1. ตรวจสอบ token
curl https://phone.mcloud.co.th/api/v1/meta/whoami \
-H "Authorization: Bearer crk_..."
# 2. ส่ง metadata + ขอ upload 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",
"customerPhone": "+66812345678",
"audioPresignedUploadUrl": true
}'
# 3. อัปโหลดไฟล์เสียง
curl -X PUT "<uploadUrl>" \
--data-binary "@call.wav"
# 4. สั่ง AI
curl -X POST https://phone.mcloud.co.th/api/v1/recordings/$ID/reextract \
-H "Authorization: Bearer crk_..."
const headers = { authorization: 'Bearer crk_...' };
// 1. who am I
await fetch('https://phone.mcloud.co.th/api/v1/meta/whoami', { headers });
// 2. ingest
const r = await fetch('https://phone.mcloud.co.th/api/v1/recordings', {
method: 'POST',
headers: { ...headers, 'content-type': 'application/json' },
body: JSON.stringify({
dataId: 'rec_2026_05_20_001',
callAt: '2026-05-20T08:14:00+07:00',
direction: 'in',
audioPresignedUploadUrl: true,
}),
});
const { id, uploadUrl } = await r.json();
// 3. upload
await fetch(uploadUrl, { method: 'PUT', body: audioBlob });
// 4. AI
await fetch(`https://phone.mcloud.co.th/api/v1/recordings/${id}/reextract`, {
method: 'POST',
headers,
});
import httpx
r = httpx.get(
'https://phone.mcloud.co.th/api/v1/meta/whoami',
headers={'authorization': 'Bearer crk_...'},
)
print(r.json())
Authentication
ทุก request ต้องมี header Authorization: Bearer crk_... ระบบเก็บ API key แบบ hash — เซิร์ฟเวอร์เก็บแค่ส่วนต้น (prefix) และเวลาที่ใช้ล่าสุดไว้ใช้ debug
Scopes
API key แต่ละตัวได้สิทธิ์บางส่วนของธุรกิจ ตามที่เลือกไว้ตอนสร้าง
| Scope | ความหมาย |
|---|---|
view_recording_all | อ่านทุกสายในธุรกิจ |
view_recording_self | อ่านเฉพาะสายที่ผูกกับผู้ใช้เจ้าของ key |
manage_recording_review | แก้คะแนน / แท็ก / ความเห็น |
manage_call_recording | ส่งสายเข้า / ลบ / สั่งวิเคราะห์ใหม่ |
manage_recording_link | ผูกสายกับผู้ใช้ |
ระบบแสดง API key ครั้งเดียว ตอนสร้าง ถ้าทำหาย ให้เพิกถอนแล้วสร้างใหม่
# Request — ต้องแนบ Bearer token
GET /api/v1/recordings HTTP/1.1
Host: phone.mcloud.co.th
Authorization: Bearer crk_a1b2c3d4...
# Response — 401 หากไม่มี
{
"error": { "code": "missing_token" }
}
API key ระดับบัญชี
API key มี สองระดับ — ทั้งคู่เรียก endpoint v1 ชุดเดียวกัน
| Business key | Account key | |
|---|---|---|
| สร้างที่ | ธุรกิจ → API key | เมนูรูปโปรไฟล์มุมขวาบน → API key (บัญชี) |
| ผูกกับ | ธุรกิจเดียว | ไม่ผูกกับธุรกิจ (เป็นของผู้ใช้แต่ละคน) |
| Scopes | สิทธิ์บางส่วนที่เลือก | สิทธิ์เจ้าของเต็ม (manage_all) ใน ทุก ธุรกิจที่คุณเป็นสมาชิก |
| Header เพิ่ม | — | X-Business-Id: <businessId> (จำเป็นเมื่อเรียก data endpoint) |
| การประชุมของคุณเอง | — (ธุรกิจไม่มีการประชุม) | X-Business-Id: personal อ่านอย่างเดียว (ดูข้อ 4) |
Business key ผูกกับธุรกิจที่สร้าง key นั้นโดยอัตโนมัติ ส่วน Account key ไม่ผูก — จะทำงานกับธุรกิจที่คุณระบุใน header X-Business-Id ด้วยสิทธิ์เจ้าของเต็ม
⚠️ ข้อควรระวังด้านความปลอดภัย — Account key มีอำนาจเท่ากับการล็อกอินเป็นเจ้าของธุรกิจ ทั้งหมด ของคุณ และไม่ถูกจำกัดด้วย scope ของ API key ระดับธุรกิจ เก็บไว้เหมือนรหัสผ่าน อย่าส่งไปฝั่งเบราว์เซอร์หรือ commit ลง repo และเพิกถอนทันทีถ้ารั่ว
1. สร้าง Account key
ในหน้าเว็บ กดรูปโปรไฟล์มุมขวาบน → API key (บัญชี) แล้วสร้าง key เช่นเดียวกับ API key ของธุรกิจ ระบบจะแสดง key ครั้งเดียว — คัดลอกแล้วเก็บไว้ในที่ปลอดภัย
2. ดู id ธุรกิจของคุณ
เรียก /meta/whoami โดยไม่ใส่ X-Business-Id — Account key จะตอบ level: "account" พร้อมรายการธุรกิจที่ใช้ได้
curl https://phone.mcloud.co.th/api/v1/meta/whoami \
-H "Authorization: Bearer crk_..."
{
"level": "account",
"userId": "...",
"scopes": ["manage_all"],
"businesses": [
{ "id": "b1...", "name": "Acme Sales", "slug": "acme-sales" },
{ "id": "b2...", "name": "Acme Support", "slug": "acme-support" }
]
}
(ส่วน Business key จะตอบ { "level": "business", "business": { … }, "scopes": [...] })
businesses แสดงเฉพาะธุรกิจ ส่วนพื้นที่ Meet ส่วนตัวของคุณไม่ใช่ธุรกิจ จึงไม่อยู่ในรายการนี้ วิธีเข้าถึงพื้นที่นี้อยู่ในข้อ 4
3. เรียก data endpoint พร้อม X-Business-Id
ทุกการเรียก data endpoint (recordings, collections) ต้อง แนบ X-Business-Id เพื่อเลือกธุรกิจที่จะทำงานด้วย
curl https://phone.mcloud.co.th/api/v1/recordings \
-H "Authorization: Bearer crk_..." \
-H "X-Business-Id: b1..."
ถ้าไม่ใส่ header จะได้ 400 business_required และถ้าชี้ไปที่ธุรกิจที่คุณไม่ได้เป็นสมาชิก (หรือ id ผิดรูปแบบ) จะได้ 403 forbidden_business
4. การประชุมของคุณเอง: X-Business-Id: personal
การประชุมเป็นของแต่ละคน ไม่ได้เป็นของธุรกิจ และเก็บอยู่ในพื้นที่ Meet ส่วนตัวของคุณซึ่งไม่มีธุรกิจไหนมองเห็น ดังนั้น business key หรือ account key ที่ชี้ไปที่ธุรกิจจะ ไม่ได้การประชุมเลย จาก /meetings ถ้าจะอ่านการประชุมของตัวเอง ให้ส่ง account key พร้อมค่าสงวน personal แทน id ของธุรกิจ
curl https://phone.mcloud.co.th/api/v1/meetings \
-H "Authorization: Bearer crk_<account key>" \
-H "X-Business-Id: personal"
personalหมายถึงพื้นที่ ของเจ้าของ key เอง เสมอ และไม่มี key ไหนเข้าถึงพื้นที่ของคนอื่นได้- เป็นแบบ อ่านอย่างเดียว ใช้ได้กับ
GET /meetingsและGET /meetings/{id}ส่วน endpoint อื่นทุกตัวจะตอบ403 insufficient_scope - ใช้ได้กับ account key เท่านั้น business key ที่ส่งค่านี้จะได้
403 account_key_required
ข้อผิดพลาด
ข้อผิดพลาดทุกแบบตอบเป็น JSON โครงสร้างเดียวกัน — code เป็นสตริงที่โปรแกรมอ่านได้
| Status | Code | เกิดเมื่อ |
|---|---|---|
400 | business_required | Account key เรียก data endpoint โดยไม่ส่ง X-Business-Id หรือส่งค่าว่าง |
400 | validation_failed | พารามิเตอร์ query ของการอ่าน หรือ JSON body ของการอ่านแบบ batch (POST /recordings/search, /phones/*, stats และ insights แบบ POST) อ่านไม่ได้ — issues บอกว่าผิดตรงไหน ดู Phones → Body ของคำขอแบบ batch |
401 | missing_token | ไม่มี Authorization header |
401 | invalid_token | API key ผิดหรือหมดอายุ |
401 | token_disabled | API key ถูกเพิกถอนแล้ว |
403 | insufficient_scope | API key ไม่มีสิทธิ์ที่ต้องใช้ (ถ้าส่ง X-Business-Id: personal หมายถึงเรียก endpoint อื่นที่ไม่ใช่การอ่านการประชุม) |
403 | forbidden_business | Account key ชี้ไปที่ธุรกิจที่เจ้าของ key เข้าถึงไม่ได้ หรือ id ของธุรกิจผิดรูปแบบ |
403 | account_key_required | Business key เรียก endpoint ที่ใช้ได้เฉพาะ account key หรือส่ง X-Business-Id: personal |
403 | feature_not_in_package | แพ็กเกจของธุรกิจนี้ไม่รวมการส่งผลการวิเคราะห์ออกนอก REXcord ดู Endpoint ที่ขึ้นกับแพ็กเกจ |
404 | not_found | ข้อมูลที่ขอไม่อยู่ในธุรกิจนี้ |
422 | validation_failed | Payload ไม่ถูกต้อง |
422 | invalid_payload | body ของคำขอไม่ใช่ JSON object |
429 | rate_limited | เรียกเร็วเกินไป |
500 | internal_error | เซิร์ฟเวอร์ขัดข้อง — แจ้งทีมงาน |
HTTP/1.1 403 Forbidden
content-type: application/json
{
"error": {
"code": "insufficient_scope",
"message": "Token lacks 'view_recording_all'"
}
}
Endpoint ที่ขึ้นกับแพ็กเกจ
บางแพ็กเกจไม่รวมการส่งผลการวิเคราะห์ออกนอก REXcord เช่น แพ็กเกจ Starter ที่ได้แค่บทถอดเสียง ธุรกิจที่ใช้แพ็กเกจแบบนี้ยังส่งสายเข้าระบบได้ตามปกติ (POST /recordings อัปโหลดผ่าน URL ที่ได้มา แล้ว POST /recordings/{id}/reextract) และเปิดอ่านบทถอดเสียงในแอปได้ครบ สิ่งที่ต่างคือข้อมูลที่ API ส่งกลับ
ตอบปฏิเสธ — endpoint กลุ่มนี้ตอบ 403 feature_not_in_package ก่อนอ่านหรือบันทึกอะไร
| Endpoint | หมายเหตุ |
|---|---|
GET /recordings/detail | |
POST /recordings/analyze | ปฏิเสธก่อนอ่านไฟล์เสียง ให้ส่งสายด้วย POST /recordings แทน |
GET /transcripts/search | |
GET / POST /insights/* | ทุก endpoint ของ insights |
POST /assistant/ask | ไม่นับโควตา |
PUT /callbacks (ระดับธุรกิจ) | GET และ DELETE ยังใช้ได้ ปลายทางที่ตั้งไว้ยังเก็บไว้ แต่ระบบจะไม่ส่งจนกว่าแพ็กเกจจะรวมการส่งผลออก |
POST /notifications/automations · PUT /notifications/automations/{id} | กฎแบบนี้ส่งไป Telegram / Discord เสมอ ส่วน GET PATCH (เปิด/ปิด) และ DELETE ยังใช้ได้ |
transcriptUrl · summaryUrl เมื่อเรียกด้วย API key | ลิงก์ที่อยู่ในข้อมูลของสาย |
ส่งเฉพาะข้อมูลของสาย — endpoint กลุ่มนี้ยังตอบรูปแบบเดิม แต่ช่องผลการวิเคราะห์เป็นค่าว่าง
| Endpoint | ช่องที่เป็นค่าว่าง |
|---|---|
GET /recordings · POST /recordings/search · GET /recordings/{id} · GET /collections/{id} · ข้อมูลที่ PATCH /recordings/{id} ตอบกลับ | tag score customerScore customerScoreKind customerReadinessScore customerSatisfactionScore transcriptUrl summaryUrl เป็น null และ flags เป็น [] ส่วนรหัส สถานะ ความยาว เวลา audioUrl และ cost ไม่เปลี่ยน |
GET / POST /recordings/stats | totals.avgScore topPerformers[].avgScore ทุกแถว scoreDistribution และ tagDistribution เป็น null ส่วนจำนวนสาย ความยาว รายวัน และรายชั่วโมงไม่เปลี่ยน |
POST /phones/summary | avgScore เป็น null |
กรองหรือเรียงสายตามผลการวิเคราะห์ไม่ได้ — รายการสายเลือกสายด้วยค่าที่ตัวเองส่งกลับเป็น null ไม่ได้ ใน GET /recordings และ POST /recordings/search ถ้าส่งตัวกรอง tag / tags scoreMin / scoreMax customerScoreMin / customerScoreMax customerScoreKind customerReadinessMin / customerReadinessMax customerSatisfactionMin / customerSatisfactionMax flag หรือ flagLevel หรือเรียงด้วย sortBy เป็น score customerScore customerReadinessScore หรือ customerSatisfactionScore ระบบจะตอบ 403 feature_not_in_package ก่อนอ่านสาย และบอกชื่อพารามิเตอร์ตัวแรกที่ส่งมาใน param ส่วน tags ใน POST /recordings/stats ก็ตอบแบบเดียวกัน ถ้าไม่ส่งพารามิเตอร์เหล่านี้ รายการสายจะตอบตามปกติแบบตารางด้านบน
endpoint อื่นทั้งหมดไม่เปลี่ยน เช่น ธุรกิจ สมาชิก แหล่งเสียง พนักงาน คอลเลกชัน Telegram การส่งแจ้งเตือน พาร์ทเนอร์ และการประชุม ผู้ช่วยที่เชื่อมผ่าน MCP อ่านข้อมูลผ่าน endpoint ชุดเดียวกัน เครื่องมือที่อ่านบทถอดเสียงหรือผลการวิเคราะห์จึงตอบว่าแพ็กเกจไม่รวมส่วนนี้
HTTP/1.1 403 Forbidden
content-type: application/json
{
"error": {
"code": "feature_not_in_package",
"feature": "results_api",
"message": "This business's package does not include sending call transcripts or analysis out of REXcord. …"
}
}
ถ้าต้องการใช้อีกครั้ง เลือกแพ็กเกจที่รวมการส่งผลออกได้ที่ ตั้งค่าธุรกิจ → แพ็กเกจ (/business/plan) แจ้งผลอัตโนมัติและกฎแจ้งเตือนที่เคยตั้งไว้จะกลับมาทำงานเหมือนเดิม