1. สร้าง API key
ไปที่ การเชื่อมต่อ → API และ Webhook เฉพาะเจ้าของ workspace เท่านั้นที่สร้างคีย์ได้ ตั้งชื่อคีย์ให้รู้ว่าใช้ที่ไหน เช่น “ฟอร์มเว็บไซต์” แล้วคัดลอกทันที เพราะระบบจะแสดงคีย์เต็มเพียงครั้งเดียวและเก็บเฉพาะ hash
รูปแบบคีย์: pt_live_… · header: Authorization: Bearer …
2. การยืนยันตัวตนและข้อจำกัด
https://propthunder.com/api/v1- จำกัด 120 requests/นาทีต่อคีย์ เกินแล้วได้ 429 พร้อม Retry-After
- รับ-ส่ง JSON (UTF-8) วันที่เป็น ISO 8601 พร้อม offset ราคาเป็นจำนวนเต็มบาท
- รายการใช้ limit (สูงสุด 100) และ offset ดูต่อด้วย next_offset เมื่อ has_more = true
- เจ้าของเท่านั้นที่สร้างคีย์/เว็บฮุกได้ สมาชิกทีมใช้คีย์ที่มีอยู่เรียก API ได้
curl "https://propthunder.com/api/v1/contacts?limit=10&offset=0" \ -H "Authorization: Bearer pt_live_..." \ -H "Accept: application/json"
3. REST API
| Method | Endpoint | ใช้ทำอะไร |
|---|---|---|
| GET | /api/v1/contacts | ดูลูกค้า ค้นด้วย q กรอง stage_id |
| POST | /api/v1/contacts | สร้างลูกค้าเข้าขั้นแรกของ pipeline |
| GET | /api/v1/contacts/{id} | ดูลูกค้าหนึ่งคน |
| PATCH | /api/v1/contacts/{id} | แก้ข้อมูล ย้าย stage_id มอบหมาย assigned_to |
| GET | /api/v1/stages | ขั้น pipeline และ id |
| GET | /api/v1/listings | ดูประกาศ กรอง status |
| POST | /api/v1/tasks | สร้างงาน ผูกกับลูกค้าได้ |
ส่งลูกค้าจากเว็บไซต์ของคุณ
POST /contacts คือการเชื่อมต่อแรกที่ใช้บ่อย ชื่อบังคับ ควรมีเบอร์หรืออีเมล ลูกค้าจะเข้าขั้นแรกของ pipeline และเกิด event contact.created
curl -X POST "https://propthunder.com/api/v1/contacts" \
-H "Authorization: Bearer pt_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "สมชาย ใจดี",
"phone": "0812345678",
"email": "somchai@example.com",
"source": "website",
"interest": "buy",
"budget_max": 5000000,
"tags": ["website", "condo"],
"notes": "สนใจคอนโดใกล้ BTS"
}'ย้ายลูกค้าไปขั้นอื่น:
curl -X PATCH "https://propthunder.com/api/v1/contacts/CONTACT_ID" \
-H "Authorization: Bearer pt_live_..." \
-H "Content-Type: application/json" \
-d '{"stage_id":"STAGE_ID","deal_value":4290000}'4. สร้าง Webhook endpoint
- เตรียม HTTPS URL บนเซิร์ฟเวอร์ของคุณที่รับ POST และตอบ 2xx อย่างเร็ว (ภายใน 10 วินาที)
- ใน การเชื่อมต่อ → API และ Webhook เพิ่ม URL และเลือกเหตุการณ์ที่ต้องการ
- คัดลอก signing secret ที่แสดงครั้งเดียว เก็บเป็น environment variable ฝั่งเซิร์ฟเวอร์
- กด “ส่งทดสอบ” เพื่อตรวจการเชื่อมต่อ ผลจะอยู่ในตาราง delivery log
- เปิด endpoint ไว้ ถ้าต้อง deploy ให้ปิดชั่วคราวได้
5. เหตุการณ์และ payload
header ที่ส่งมาทุกครั้ง:
POST https://your-app.example/webhooks/propthunder
Content-Type: application/json
PropThunder-Event: contact.created
PropThunder-Timestamp: 1761411600
PropThunder-Signature: v1=<hex hmac>
{
"event": "contact.created",
"created_at": "2026-10-25T09:00:00.000Z",
"data": {
"contactId": "3f6c...",
"name": "สมชาย ใจดี",
"phone": "0812345678",
"email": "somchai@example.com",
"source": "website"
}
}| เหตุการณ์ | เกิดเมื่อ | data |
|---|---|---|
contact.created | สร้างลูกค้าใหม่จากฟอร์ม เว็บไซต์ LINE หรือ API | contactId, name, phone, email, source |
contact.updated | ข้อมูลลูกค้าถูกแก้ไข | contactId, name, fields (ชื่อฟิลด์ที่เปลี่ยน) |
contact.stage_changed | ลูกค้าถูกย้ายขั้นใน pipeline | contactId, name, from, to, stageId, kind, viaWorkflow, viaAi |
inquiry.created | มีลูกค้าส่งข้อความสอบถามจากประกาศหรือหน้าเว็บ | contactId, name, phone, email, source, message, propertyId, title |
listing.created | ประกาศใหม่ถูกสร้าง | id, slug, title, status, price |
listing.updated | ประกาศถูกแก้ไขหรือเปลี่ยนสถานะ | id, slug, title, status, price |
task.completed | งานถูกทำเครื่องหมายว่าเสร็จ | taskId, title, contactId |
ปุ่มส่งทดสอบจะส่ง event ชื่อ ping (ไม่อยู่ในรายการที่เลือกได้) เข้ามาที่ endpoint ด้วย
6. ตรวจลายเซ็น
คำนวณ HMAC-SHA256 ของ `${timestamp}.${rawBody}` ด้วย secret ของ endpoint แล้วเทียบค่าแบบ timing-safe พร้อมปฏิเสธ timestamp ที่เก่ากว่า 5 นาที สำคัญ: ต้องใช้ raw body ก่อน parse JSON
import crypto from "node:crypto";
export function verifyPropThunderWebhook(req, rawBody, secret) {
const timestamp = req.headers["propthunder-timestamp"];
const signature = String(req.headers["propthunder-signature"] ?? "").replace(/^v1=/, "");
if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(timestamp + "." + rawBody)
.digest("hex");
return signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}ตัวอย่าง Express: ใช้ express.raw({ type: 'application/json' }) แล้วส่ง req.body.toString() เป็น rawBody
7. Retry, log และการทดสอบ
- ถ้าส่งไม่สำเร็จ ระบบลองสูงสุด 6 ครั้ง โดยเว้นช่วงเพิ่มขึ้น (ประมาณ 2, 4, 8, 16 และ 32 นาที)
- หน้า API และ Webhook แสดง delivery ล่าสุดพร้อมสถานะและ error
- ตอบ 2xx ทันทีแล้วประมวลผลแบบ async อย่าทำงานช้าก่อนตอบ
- กดส่งทดสอบหลังเปลี่ยน endpoint ผลทดสอบจะอยู่ใน log เดียวกัน
- เขียน handler ให้ idempotent เพราะหลัง retry อาจได้รับ event เดิมซ้ำ
8. แก้ปัญหา
401 Unauthorized
ลืมส่ง Bearer, คีย์ถูกเพิกถอน หรือรูปแบบ header ผิด
404 Not found
ข้อมูลไม่อยู่ใน workspace ของคีย์นี้
422 Invalid input
ตรวจฟิลด์บังคับ, stage_id/assignee_id และรูปแบบวันที่
429 Rate limited
รอตาม Retry-After แล้วค่อยเรียกใหม่
Webhook ไม่มา
ตรวจว่า endpoint เปิดอยู่ เป็น HTTPS สาธารณะ เลือก event แล้ว และดู delivery log
ลายเซ็นไม่ตรง
ใช้ raw body และ secret ของ endpoint นั้น exactly; อย่า sign หลัง parse object
