เริ่มต้นใช้งาน

ภาพรวม · quickstart · auth · errors

เริ่มต้นใช้งาน

REXcord API ให้ธุรกิจส่งสายเข้าระบบ ค้นหาสาย ดูบทถอดเสียงและสรุป และสั่งให้ AI ประมวลผลใหม่ได้ ทุก endpoint ทำงานกับธุรกิจที่เป็นเจ้าของ API key เท่านั้น

ค่ารายละเอียด
Base URLhttps://phone.mcloud.co.th/api/v1
AuthAuthorization: Bearer crk_...
Contentapplication/json
Rate limit600 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 keyAccount 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 เป็นสตริงที่โปรแกรมอ่านได้

StatusCodeเกิดเมื่อ
400business_requiredAccount key เรียก data endpoint โดยไม่ส่ง X-Business-Id หรือส่งค่าว่าง
400validation_failedพารามิเตอร์ query ของการอ่าน หรือ JSON body ของการอ่านแบบ batch (POST /recordings/search, /phones/*, stats และ insights แบบ POST) อ่านไม่ได้ — issues บอกว่าผิดตรงไหน ดู Phones → Body ของคำขอแบบ batch
401missing_tokenไม่มี Authorization header
401invalid_tokenAPI key ผิดหรือหมดอายุ
401token_disabledAPI key ถูกเพิกถอนแล้ว
403insufficient_scopeAPI key ไม่มีสิทธิ์ที่ต้องใช้ (ถ้าส่ง X-Business-Id: personal หมายถึงเรียก endpoint อื่นที่ไม่ใช่การอ่านการประชุม)
403forbidden_businessAccount key ชี้ไปที่ธุรกิจที่เจ้าของ key เข้าถึงไม่ได้ หรือ id ของธุรกิจผิดรูปแบบ
403account_key_requiredBusiness key เรียก endpoint ที่ใช้ได้เฉพาะ account key หรือส่ง X-Business-Id: personal
403feature_not_in_packageแพ็กเกจของธุรกิจนี้ไม่รวมการส่งผลการวิเคราะห์ออกนอก REXcord ดู Endpoint ที่ขึ้นกับแพ็กเกจ
404not_foundข้อมูลที่ขอไม่อยู่ในธุรกิจนี้
422validation_failedPayload ไม่ถูกต้อง
422invalid_payloadbody ของคำขอไม่ใช่ JSON object
429rate_limitedเรียกเร็วเกินไป
500internal_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/statstotals.avgScore topPerformers[].avgScore ทุกแถว scoreDistribution และ tagDistribution เป็น null ส่วนจำนวนสาย ความยาว รายวัน และรายชั่วโมงไม่เปลี่ยน
POST /phones/summaryavgScore เป็น 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) แจ้งผลอัตโนมัติและกฎแจ้งเตือนที่เคยตั้งไว้จะกลับมาทำงานเหมือนเดิม