PropertyMost
ลงประกาศ

สำหรับนักพัฒนา · v1

Partner API

ส่งประกาศขาย/เช่าอสังหาฯ จากระบบของบริษัทท่านเข้า PropertyMost อัตโนมัติ สร้าง แก้ไข เปลี่ยนสถานะ และปิดประกาศได้ด้วยรหัสอ้างอิงของท่านเอง

เริ่มต้น

  1. สมัครสมาชิก PropertyMost ด้วยอีเมลบริษัท ประกาศทั้งหมดจะอยู่ในบัญชีนี้
  2. ติดต่อทีมงานทาง LINE @511gsago เพื่อขอเปิดใช้ Partner API และรับ API key
  3. Base URL: https://api.propertymost.com/api/partner/v1
  4. ทุกคำขอและคำตอบเป็น JSON (UTF-8) ผ่าน HTTPS เท่านั้น

การยืนยันตัวตน

ส่ง API key ใน header ทุกคำขอ เก็บ key ไว้ฝั่งเซิร์ฟเวอร์เท่านั้น ห้ามใส่ในแอปมือถือหรือโค้ดหน้าเว็บ

curl https://api.propertymost.com/api/partner/v1/me \
  -H "Authorization: Bearer pm_live_xxxxxxxxxxxxxxxx"

จำกัดจำนวนครั้งต่อนาทีต่อ key (ค่าเริ่มต้น 60) ดูเหลือได้จาก header X-RateLimit-Remaining ถ้าเกิน จะได้ 429 พร้อม Retry-After

Endpoint

GET/meข้อมูลบัญชีพาร์ทเนอร์ ค่าที่ตั้งไว้ และจำนวนรูปสูงสุดต่อประกาศ
GET/property-typesประเภททรัพย์ (ใช้ slug ใน propertyType)
GET/provincesรายชื่อจังหวัด
GET/districts?province={id หรือชื่อ}เขต/อำเภอ พร้อม id
GET/projects?q={คำค้น}ค้นโครงการ (อย่างน้อย 2 ตัวอักษร) สูงสุด 20 รายการ
PUT/listings/{externalId}สร้างหรืออัปเดตประกาศ
GET/listings?status=&page=&pageSize=&updatedSince=ประกาศทั้งหมดของท่าน (pageSize สูงสุด 100)
GET/listings/{externalId}ดูประกาศ สถานะ ลิงก์บนเว็บ และยอดเข้าชม
PATCH/listings/{externalId}/statusเปลี่ยนสถานะ active / paused / sold / rented
DELETE/listings/{externalId}ปิดประกาศ (ส่ง PUT อีกครั้งเพื่อเปิดใหม่)
POST/listings/bulkส่งครั้งละไม่เกิน 500 รายการ ทำงานเบื้องหลัง (upsert หรือ full_sync)
GET/jobs, /jobs/{jobId}?onlyFailed=trueความคืบหน้าและผลรายการต่อรายการของงาน bulk
GET/leads?since=&limit=ผู้สนใจประกาศ (ดูเบอร์ / เริ่มแชท) แบบไม่ระบุตัวตน
GET/webhookดูการตั้งค่า webhook
PUT/webhookตั้ง URL และเหตุการณ์ที่ต้องการรับ
POST/webhook/testส่งเหตุการณ์ทดสอบไปที่ URL
DELETE/webhookลบ webhook

สร้าง/อัปเดตประกาศ

externalId คือรหัสประกาศในระบบของท่าน (A-Z a-z 0-9 . _ - ไม่เกิน 100 ตัวอักษร) ส่ง PUT ซ้ำด้วยรหัสเดิม = อัปเดตประกาศเดิม ไม่เกิดประกาศซ้ำ จึงส่งทั้ง stock ซ้ำทุกวันได้อย่างปลอดภัย ข้อมูลที่ส่งจะแทนที่ของเดิมทั้งหมด ช่องที่ไม่ส่งจะถูกล้างเป็นค่าว่าง

curl -X PUT https://api.propertymost.com/api/partner/v1/listings/CONDO-1024 \
  -H "Authorization: Bearer pm_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "propertyType": "condo",
    "listingType": "sale",
    "price": 2890000,
    "title": "Artisan Ratchada 1 ห้องนอน ชั้น 18",
    "projectName": "Artisan Ratchada",
    "province": "กรุงเทพมหานคร",
    "district": "ห้วยขวาง",
    "bedrooms": 1,
    "bathrooms": 1,
    "sizeSqm": 28.28,
    "contactPhone": "0812345678",
    "imageUrls": ["https://cdn.example.com/1024/cover.jpg", "https://cdn.example.com/1024/2.jpg"]
  }'

คำตอบ (200):

{
  "created": true,
  "listing": {
    "externalId": "CONDO-1024",
    "id": 1532,
    "status": "pending_review",
    "url": "https://propertymost.com/properties/1532-artisan-ratchada-1-ห้องนอน-ชั้น-18-ห้วยขวาง",
    "price": 2890000,
    "images": [{ "url": "https://api.propertymost.com/uploads/....jpg", "sourceUrl": "https://cdn.example.com/1024/cover.jpg", "isCover": true }],
    "stats": { "views": 0, "phoneViews": 0 },
    ...
  },
  "warnings": [{ "field": "imageUrls[1]", "message": "ข้ามรูปนี้: ดาวน์โหลดไม่สำเร็จ (HTTP 404)" }]
}
ช่องรายละเอียด
propertyTypeจำเป็นslug จาก GET /property-types เช่น condo, house, townhome, shophouse, land
listingTypeจำเป็นsale (ขาย) หรือ rent (เช่า)
priceจำเป็นตัวเลข บาท (เช่า = บาทต่อเดือน)
contactPhoneจำเป็นเบอร์ที่ผู้สนใจโทรติดต่อ เช่น 0812345678
titleชื่อประกาศ ไม่เกิน 200 ตัวอักษร
descriptionรายละเอียด ไม่เกิน 5,000 ตัวอักษร
districtIdid จาก GET /districts (แนะนำ ชัดเจนที่สุด)
district, provinceชื่อเขต/อำเภอ และจังหวัดภาษาไทย ใช้แทน districtId ได้
projectId / projectNameid จาก GET /projects หรือชื่อโครงการ (ถ้ายังไม่มีในระบบจะสร้างให้) ถ้าไม่ส่งทำเล จะใช้ทำเลของโครงการ
addressที่อยู่ ไม่เกิน 500 ตัวอักษร
bedrooms, bathroomsจำนวนเต็ม 0–50
sizeSqmพื้นที่ ตร.ม.
contactLineIdLINE ID
imageUrlsarray ของ URL รูปแบบ https เรียงตามลำดับ รูปแรกเป็นรูปปก

รูปภาพ: PropertyMost ดาวน์โหลดและย่อรูปเก็บไว้เอง URL ต้องเป็น https เปิดได้สาธารณะ ไม่ redirect และเป็นไฟล์รูปโดยตรง รูปที่ URL เดิมจะไม่ถูกดาวน์โหลดซ้ำ ถ้ารูปใดดาวน์โหลดไม่ได้ ประกาศยังบันทึกได้ และจะแจ้งใน warnings ดูจำนวนรูปสูงสุดต่อประกาศ (maxImagesPerListing) และขนาดไฟล์รูปต้นฉบับสูงสุด (maxImageSourceMb) ได้จาก GET /me ส่งรูปเกินจำนวน = error 422 ส่วนรูปที่ใหญ่เกินจะถูกข้ามและแจ้งใน warnings

สถานะประกาศ

  • pending_review รอทีมงานตรวจ (ประกาศใหม่ของพาร์ทเนอร์ที่ยังไม่เปิดขึ้นเว็บทันที)
  • active แสดงบนเว็บ · paused พักประกาศ · sold ขายแล้ว · rented เช่าแล้ว
  • closed ปิดประกาศ ถ้ามี moderationNote แปลว่าไม่ผ่านการตรวจ ส่งข้อมูลซ้ำจะไม่เปิดประกาศเอง ให้แก้ไขตามเหตุผลแล้วติดต่อทีมงาน
curl -X PATCH https://api.propertymost.com/api/partner/v1/listings/CONDO-1024/status \
  -H "Authorization: Bearer pm_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "status": "sold" }'

ส่งทีละมาก (bulk) และ full sync

ส่งได้ครั้งละไม่เกิน 500 รายการ แต่ละรายการมีช่องเหมือน PUT และเพิ่ม externalId ระบบตอบกลับทันที (202) พร้อม jobId แล้วทำงานเบื้องหลังทีละรายการ มีงานค้างพร้อมกันได้ไม่เกิน 2 งาน

curl -X POST https://api.propertymost.com/api/partner/v1/listings/bulk \
  -H "Authorization: Bearer pm_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "upsert",
    "listings": [
      { "externalId": "CONDO-1024", "propertyType": "condo", "listingType": "sale", "price": 2890000, "districtId": 1017, "contactPhone": "0812345678" },
      { "externalId": "HOUSE-77", "propertyType": "house", "listingType": "rent", "price": 25000, "district": "บางกะปิ", "province": "กรุงเทพมหานคร", "contactPhone": "0812345678" }
    ]
  }'

# → 202 { "jobId": "job_9f...", "status": "queued", "mode": "upsert", "total": 2 }

curl https://api.propertymost.com/api/partner/v1/jobs/job_9f...?onlyFailed=true -H "Authorization: Bearer pm_live_..."
# → { "status": "completed", "total": 2, "succeeded": 1, "failed": 1,
#     "results": [{ "externalId": "HOUSE-77", "ok": false, "error": "ข้อมูลไม่ถูกต้อง", "details": [...] }] }

mode: "full_sync" = "นี่คือ stock ทั้งหมดของเรา" ประกาศที่เปิดอยู่แต่ไม่อยู่ในรอบนี้จะถูกปิดให้อัตโนมัติ (และส่ง webhook listing.closed) เพื่อความปลอดภัย ถ้ารอบนั้นส่งมาน้อยกว่าครึ่งของประกาศที่เปิดอยู่ ระบบจะไม่ปิดอะไร และแจ้งเหตุผลใน syncNote ของงาน

Webhook

ระบบส่ง POST เป็น JSON ไปที่ URL ของท่านเมื่อเกิดเหตุการณ์ URL ต้องเป็น https เปิดได้จากอินเทอร์เน็ต และตอบกลับ 2xx ภายใน 10 วินาที

  • listing.approved / listing.rejected ผลการตรวจประกาศ (มี reason)
  • listing.closed ประกาศถูกปิดเพราะไม่อยู่ใน full sync
  • lead.created มีคนกดดูเบอร์หรือเริ่มแชท
  • job.completed งาน bulk เสร็จหรือล้มเหลว
curl -X PUT https://api.propertymost.com/api/partner/v1/webhook \
  -H "Authorization: Bearer pm_live_..." -H "Content-Type: application/json" \
  -d '{ "url": "https://crm.example.com/propertymost-hook", "events": ["lead.created", "listing.rejected"] }'
# ครั้งแรกจะได้ "secret": "whsec_..." (แสดงครั้งเดียว) ส่ง "rotateSecret": true เพื่อสร้างใหม่

# สิ่งที่ส่งไป
POST https://crm.example.com/propertymost-hook
X-PropertyMost-Event: lead.created
X-PropertyMost-Event-Id: evt_3c1...
X-PropertyMost-Signature: t=1790000000,v1=5f2a...
{ "id": "evt_3c1...", "event": "lead.created", "createdAt": "2026-10-01T08:00:00.000Z",
  "data": { "id": "chat_45", "type": "chat", "externalId": "CONDO-1024", "listingId": 1532, "chatUrl": "https://propertymost.com/messages?c=45" } }

ตรวจลายเซ็นทุกครั้ง: คำนวณ HMAC-SHA256 ของ <t>.<body ดิบ> ด้วย secret แล้วเทียบกับ v1 และไม่รับข้อความที่ t เก่ากว่า 5 นาที ใช้ id กันรับซ้ำ

// Node.js
const crypto = require("crypto");
function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

ถ้าปลายทางไม่ตอบ 2xx ระบบลองใหม่อัตโนมัติหลัง 1 นาที, 5 นาที, 30 นาที, 2 ชม. และ 12 ชม. จากนั้นหยุด (ทีมงานส่งซ้ำให้ได้)

Leads (ผู้สนใจ)

รายการคนที่สนใจประกาศของท่าน: phone_view (กดดูเบอร์) และ chat (เริ่มแชท) เรียงจากเก่าไปใหม่ ใช้ nextSince จากคำตอบเป็น since ของรอบถัดไป และใช้ id กันซ้ำ

curl "https://api.propertymost.com/api/partner/v1/leads?since=2026-10-01T00:00:00Z&limit=100" -H "Authorization: Bearer pm_live_..."
# → { "items": [
#       { "id": "phone_812", "type": "phone_view", "externalId": "CONDO-1024", "listingId": 1532, "createdAt": "..." },
#       { "id": "chat_45", "type": "chat", "externalId": "CONDO-1024", "listingId": 1532, "createdAt": "...", "chatUrl": "https://propertymost.com/messages?c=45" }
#     ], "nextSince": "...", "hasMore": false }

ข้อมูลส่วนบุคคล: leads ไม่มีชื่อ อีเมล เบอร์โทร หรือข้อความของผู้สนใจ ตอบแชทได้โดยล็อกอินเว็บด้วยบัญชีพาร์ทเนอร์แล้วเปิด chatUrl

Error

ทุก error มีรูปแบบเดียวกัน กรณีข้อมูลไม่ถูกต้อง จะบอกทีละช่องใน details

{
  "error": {
    "code": "validation_failed",
    "message": "ข้อมูลไม่ถูกต้อง",
    "details": [
      { "field": "listingType", "message": "ต้องเป็น \"sale\" หรือ \"rent\"" },
      { "field": "district", "message": "ไม่พบ \"ห้วยขวัง\" ในจังหวัด \"กรุงเทพมหานคร\"" }
    ]
  }
}
400invalid_requestรูปแบบคำขอผิด เช่น externalId หรือพารามิเตอร์ไม่ถูกต้อง
401unauthorizedไม่มี API key, key ผิด หรือถูกยกเลิก
403forbiddenบัญชีพาร์ทเนอร์ถูกระงับ
404not_foundไม่พบประกาศ externalId นี้ในบัญชีของท่าน
409conflictประกาศไม่ผ่านการตรวจ เปลี่ยนสถานะไม่ได้
422validation_failedข้อมูลไม่ถูกต้อง ดูรายละเอียดทีละช่องใน details
429rate_limitedเรียกถี่เกินกำหนด รอตาม header Retry-After (วินาที)
500internal_errorข้อผิดพลาดฝั่ง PropertyMost ลองใหม่ภายหลัง

ข้อตกลงการใช้งาน

  • ส่งเฉพาะทรัพย์ที่ท่านเป็นเจ้าของ หรือได้รับมอบหมายจากเจ้าของให้ประกาศ ข้อมูลและราคาต้องเป็นความจริง
  • รูปต้องเป็นรูปทรัพย์จริง และท่านต้องมีสิทธิ์เผยแพร่ ห้ามใช้รูปสต็อกแทนรูปทรัพย์
  • เบอร์โทรและ LINE ที่ส่งมาจะแสดงบนประกาศ ท่านต้องได้รับความยินยอมจากเจ้าของข้อมูลแล้ว (PDPA)
  • อัปเดตสถานะเมื่อขาย/เช่าแล้ว และปิดประกาศที่ไม่มีอยู่จริง
  • แก้ไขประกาศผ่านหน้าเว็บได้ แต่การส่ง PUT ครั้งถัดไปจะเขียนทับข้อมูลที่แก้บนเว็บ ให้แก้ที่ระบบต้นทางเป็นหลัก
  • PropertyMost อาจระงับ key หรือบัญชีที่ละเมิด ข้อตกลงการใช้งาน