Loading ETA...
Loading ETA...
คู่มือสำหรับทีมเทคนิค
คู่มือสำหรับทำเว็บทัวร์แบบไวท์เลเบล: ดึงรายการทัวร์จริง เปิดหน้ารายละเอียด โหลดรอบเดินทาง สร้างรายการจอง และเตรียมเว็บฮุกสำหรับเชื่อมระบบลูกค้า
Endpoint Index
รายการทัวร์สำหรับฝังในหน้าเว็บหรือทำกล่องค้นหาเอง
Widget token
รายการทัวร์ฝั่งเซิร์ฟเวอร์ที่กรองตามสิทธิ์ลูกค้าแล้ว
catalog:read
รายละเอียดทัวร์จากรหัสหรือ slug
catalog:read
รอบเดินทาง ที่นั่ง ราคา และราคาหลังปรับตามลูกค้า
catalog:read
เช็กที่นั่งแบบเร็ว พร้อมแคชและจำกัดจำนวนเรียกใช้
catalog:read
ล็อกที่นั่งแบบไม่แคชและกันขายเกินด้วยฐานข้อมูล
booking:create
สร้างลีดรายการจองและกันที่นั่งเมื่อเลือกรอบเดินทาง
booking:create
01 / ภาพรวม
ETA API ใช้สำหรับให้เว็บไซต์ลูกค้าดึง catalog ทัวร์จากระบบ EasyTourAgent และสร้าง booking กลับเข้าระบบกลางได้ โดยแยก tenant, visibility, ราคา และสิทธิ์การใช้งานตาม key ของแต่ละเจ้า.
วิดเจ็ต
ฝัง iframe หรือเรียกข้อมูลที่ปลอดภัยสำหรับหน้าเว็บด้วย eta_widget token.
การเชื่อมต่อฝั่งเซิร์ฟเวอร์
ใช้ eta_live key จาก server ของลูกค้าเท่านั้น ห้ามฝังใน browser.
แยกข้อมูลตามลูกค้า
ทุก endpoint ถูกกรองด้วยสิทธิ์และรายการที่ลูกค้ารายนั้นมองเห็นก่อนส่งข้อมูลออก.
02 / เริ่มเชื่อมต่อ
curl "https://easytouragent.com/api/tenant/catalog?limit=5&continent=asia" \
-H "Authorization: Bearer eta_live_xxx"03 / สิทธิ์และคีย์
API key
ขึ้นต้นด้วย eta_live ใช้กับ server-to-server เท่านั้น และตรวจ scope ทุก request.
Widget token
ขึ้นต้นด้วย eta_widget ใช้กับ iframe หรือ widget API และผูก allowed origin ได้.
| Field | Type | Description |
|---|---|---|
| Authorization | header | Bearer eta_live_xxx สำหรับ server API |
| api_key | query | ใช้สำรองได้ แต่แนะนำ header เพราะไม่หลุดใน log ง่าย |
| token | query | Widget token สำหรับ /api/widget/tours และ /embed/tours |
| x-eta-widget-token | header | legacy widget header ที่ระบบยังรองรับอยู่ |
04 / วิดเจ็ตหน้าทัวร์
ถ้าลูกค้ายังไม่มีทีม dev ให้เริ่มจาก iframe ก่อน เพราะใช้งานเร็วและปลอดภัยกว่า. ถ้าต้องการ UI ของตัวเอง ให้เรียก widget API ด้วย token ที่ล็อก origin แล้ว.
<iframe
src="https://easytouragent.com/embed/tours?token=eta_widget_xxx"
width="100%"
height="720"
style="border:0"
></iframe>GET https://easytouragent.com/api/widget/tours?token=eta_widget_xxx&limit=12&continent=asia&q=japan| Field | Type | Description |
|---|---|---|
| limit | 1-30 | จำนวนรายการที่ต้องการ ค่าเริ่มต้น 12 |
| continent | string | กรองทวีป เช่น asia, europe |
| q | string | ค้นหาจากชื่อทัวร์ |
05 / รายการทัวร์
Server API เหมาะกับเว็บลูกค้าที่มี frontend/SEO ของตัวเอง และต้องการควบคุมหน้ารายละเอียดเองทั้งหมด.
curl "https://easytouragent.com/api/tenant/catalog?limit=24&continent=europe" \
-H "Authorization: Bearer eta_live_xxx"curl "https://easytouragent.com/api/tenant/tours/japan-autumn-5d" \
-H "Authorization: Bearer eta_live_xxx"
curl "https://easytouragent.com/api/tenant/tours/japan-autumn-5d/departures" \
-H "Authorization: Bearer eta_live_xxx"| Field | Type | Description |
|---|---|---|
| limit | 1-100 | จำนวน catalog ต่อหน้า ค่าเริ่มต้น 24 |
| continent | string | กรองทวีป |
| id | UUID | slug | ใช้ได้ทั้ง tour UUID และ slug |
| tenant_prices | object | ราคาที่คำนวณตาม tenant pricing layer |
06 / ช่องเช็กที่นั่ง
ใช้ gateway endpoint สำหรับเว็บลูกข่ายที่ยิงเช็กที่นั่งถี่ ๆ หลายเว็บไซต์พร้อมกัน. Availability รันบน Node.js runtime พร้อม SWR 60 วินาทีและ Redis cache; Hold เป็น no-cache และเรียก RPC ที่ล็อกแถว departure ด้วย SELECT ... FOR UPDATE.
curl "https://easytouragent.com/api/gateway/tours/japan-autumn-5d/availability?departure_date=2026-10-12" \
-H "Authorization: Bearer eta_live_xxx"curl -X POST "https://easytouragent.com/api/gateway/tours/japan-autumn-5d/hold" \
-H "Authorization: Bearer eta_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"departure_date": "2026-10-12",
"quantity": 2,
"hold_minutes": 10,
"external_ref": "WEB-ORDER-1001",
"customer": {
"name": "Somchai Demo",
"phone": "0812345678",
"email": "somchai@example.com"
}
}'| Field | Type | Description |
|---|---|---|
| UPSTASH_REDIS_REST_URL | env | เปิด distributed cache และ rate limit ข้าม instance |
| UPSTASH_REDIS_REST_TOKEN | env | token ของ Upstash Redis REST API |
| GATEWAY_AVAILABILITY_RPM | env | quota เช็กที่นั่งต่อนาทีต่อ API key ค่าเริ่มต้น 120 |
| GATEWAY_HOLD_RPM | env | quota hold ที่นั่งต่อนาทีต่อ API key ค่าเริ่มต้น 30 |
07 / สร้างรายการจอง
ระบบสร้างรายการจองจะตรวจสิทธิ์การมองเห็นทัวร์ ตรวจรอบเดินทางถ้าระบุวันที่ คำนวณราคาตามลูกค้า และสร้างลีดสถานะรอชำระเงิน
curl -X POST "https://easytouragent.com/api/tenant/bookings" \
-H "Authorization: Bearer eta_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"tour_id": "japan-autumn-5d",
"departure_date": "2026-10-12",
"name": "Somchai Demo",
"phone": "0812345678",
"email": "somchai@example.com",
"adults": 2,
"payment_method": "reserve",
"external_ref": "WEB-ORDER-1001"
}'| Field | Type | Description |
|---|---|---|
| tour_id | required | UUID หรือ slug ของทัวร์ |
| departure_date | optional | YYYY-MM-DD ถ้าระบุ ระบบจะพยายาม reserve seat |
| name | required | ชื่อลูกค้า |
| phone | required | เบอร์โทร ระบบ normalize เบื้องต้น |
| required | อีเมลลูกค้า | |
| adults | optional | ค่าเริ่มต้น 1 |
| payment_method | bank | reserve | stripe | ช่องทางชำระเงินของ tenant |
| external_ref | optional | เลขอ้างอิงจากเว็บลูกค้า |
{
"ok": true,
"booking_ref": "ETA-12345",
"lead_id": 12345,
"tenant": { "id": "uuid", "slug": "happy-tour" },
"total_price": 59800,
"deposit_total": 20000,
"status": "pending_payment"
}08 / เว็บฮุก
ระบบสร้างคิวรอส่งสำหรับเหตุการณ์ booking.created แล้ว แต่ก่อนใช้กับลูกค้า production ขนาดใหญ่ ต้องทำ worker ส่งเว็บฮุกจริง ลายเซ็นยืนยันความถูกต้อง นโยบาย retry และหน้าติดตามการส่งให้ครบก่อน
{
"event_type": "booking.created",
"booking_ref": "ETA-12345",
"lead_id": 12345,
"source": "tenant_api",
"external_ref": "WEB-ORDER-1001",
"customer": {
"name": "Somchai Demo",
"phone": "0812345678",
"email": "somchai@example.com"
},
"departure_date": "2026-10-12",
"total_price": 59800
}09 / รหัสผิดพลาด
401 Unauthorized
API key ผิด, หมดอายุ, inactive หรือไม่มี scope ที่ต้องใช้
404 Tour not found
tour ไม่อยู่ใน tenant visibility หรือ slug/id ไม่ถูกต้อง
409 Departure not available
รอบเดินทางไม่มีแล้ว ยกเลิกแล้ว หรือที่นั่งไม่พอ
500 Server error
ฐานข้อมูลหรือ upstream service มีปัญหา ควร retry แบบ exponential backoff
10 / ก่อนเปิดจริง
Tenant active
tenant status เป็น trial หรือ active
Catalog ready
มี tour visible และ quality audit ไม่มี critical
API key scoped
ออก key แยกตามเว็บและให้ scope เท่าที่จำเป็น
Widget origin locked
allowed origins เป็น domain จริง ไม่ใช้ *
ตรวจราคาขายแล้ว
สุ่มตรวจราคาและรอบเดินทางกับ supplier อย่างน้อย 5 รายการ
Booking tested
ทดสอบ create booking, reserve seat, และกรณี seat ไม่พอ
Webhook configured
ตั้ง endpoint, signature, retry และ monitor
Rate limit plan
กำหนด quota ตามแพ็กเกจและแจ้งเตือนเมื่อใช้สูงผิดปกติ
พร้อมทดสอบการเชื่อมต่อ
ห้ามส่ง eta_live key ไปใน browser หรือแอปมือถือโดยตรง. ถ้าต้องแสดง catalog ฝั่ง browser ให้ใช้ widget token หรือทำ proxy ผ่าน server ของลูกค้าเท่านั้น.
เริ่มจากวิดเจ็ตได้
เริ่มจากวิดเจ็ตก่อน แล้วค่อยย้ายเป็นการเชื่อมต่อเต็มรูปแบบเมื่อเว็บลูกค้าพร้อม.
ปลอดภัยก่อน
แยกคีย์ต่อลูกค้า แยก scope และล็อก origin เพื่อกันข้อมูลรั่ว.
คู่มือฉบับเต็ม
ไฟล์ docs/eta-api-integration-guide.md ใช้ส่งให้ทีม dev หรือแนบใน proposal ได้.