คู่มือและข้อมูลอ้างอิงสำหรับ ElefyMove Open API
ขณะนี้คู่มือเหล่านี้มีเฉพาะภาษาอังกฤษ
| เมธอด | เอนด์พอยต์ | สโคป | ใช้ทำอะไร |
|---|---|---|---|
| PUT | /api/public/v1/webhooks | webhooks:manage | ตั้งค่า URL ปลายทาง webhook ของคุณ และเลือกแทนที่รายการอีเวนต์ที่สมัครรับได้ |
| GET | /api/public/v1/webhooks | webhooks:manage | อ่านการตั้งค่า webhook ปัจจุบันของคุณ ไม่มีการส่งคืน signing secret |
| DELETE | /api/public/v1/webhooks | webhooks:manage | ล้างค่า URL ของ webhook และหยุดการส่งข้อมูล |
/api/public/v1/webhooks/test | webhooks:manage | ส่งอีเวนต์ทดสอบที่เซ็นรับรองไปยัง endpoint ที่ตั้งค่าไว้ ไม่ว่าจะสมัครรับอีเวนต์ใดอยู่ | |
| GET | /api/public/v1/webhook-deliveries | webhooks:manage | แสดงรายการความพยายามส่ง webhook ของคุณเอง พร้อมสถานะ เวลา และประวัติการลองใหม่ |
/api/public/v1/webhook-deliveries/{id}/redeliver | webhooks:manage | ลองส่งการส่งข้อมูลที่ล้มเหลวหรือถูกยกเลิกซ้ำอีกครั้งด้วยตนเอง |
Set your HTTPS endpoint URL either through the API (PUT /webhooks) or from the dashboard’s Webhooks tab; both write the same configuration. การหมุนเวียน signing secret ไม่ได้อยู่ใน API นี้โดยตั้งใจ — ต้องทำผ่านแดชบอร์ดเท่านั้น เพื่อไม่ให้พาร์ตเนอร์หมุนเวียนข้อมูลรับรองที่ใช้พิสูจน์ว่ายังควบคุมคีย์อยู่ได้เอง
events on PUT /webhooks is optional and, when sent, replaces your subscription list. Omit it entirely to leave your existing subscription untouched. Send it as an empty array — the same as never setting it — to subscribe to every event; an empty list is not "no events". A non-empty list narrows delivery to exactly those event names. POST /webhooks/test always sends a signed ping, regardless of your subscription.
The delivery log (GET /webhook-deliveries) and manual redelivery (POST /webhook-deliveries/:id/redeliver) are also available through the API, mirroring the dashboard’s delivery log.
| อีเวนต์ที่รับได้ | ใช้ทำอะไร |
|---|---|
listing.approved | A listing you submitted passed moderation and is live. |
listing.rejected | A listing you submitted was rejected by moderation. |
availability.changed | A listing’s calendar changed outside your own writes — a booking, block, or hold from another channel. |
hold.created | A temporary hold was placed on one of your listings. |
hold.released | A hold was released before it expired. |
hold.expired | A hold reached its TTL and expired. |
booking.created | An ElefyMove booking was confirmed on one of your listings (dates and references only). |
booking.cancelled | An ElefyMove booking on one of your listings was cancelled. |
ping | Manual test delivery — from the dashboard or POST /webhooks/test — same signing, no side effects. |
Every delivery is a JSON POST carrying three headers: X-Elefy-Event, X-Elefy-Timestamp, and X-Elefy-Signature. The signature is hex(HMAC-SHA256(webhookSecret, timestamp + "." + rawBody)) — recompute it over the exact bytes you received and compare in constant time:
import { createHmac, timingSafeEqual } from "node:crypto";
import express from "express";
const app = express();
// Capture the RAW request bytes — a re-serialized JSON.stringify(body)
// may not byte-match what was signed.
app.post(
"/webhooks/elefymove",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.header("X-Elefy-Signature") ?? "";
const timestamp = req.header("X-Elefy-Timestamp") ?? "";
const rawBody = req.body.toString("utf8");
const expected = createHmac("sha256", process.env.ELEFY_WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const valid =
signature.length === expected.length &&
timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.status(401).end();
// Optional hardening: reject timestamps older than a few minutes
// to close the replay window.
const event = JSON.parse(rawBody);
console.log(event.event, event.data);
// Acknowledge fast (2xx) — do heavy work asynchronously.
res.status(200).end();
},
);Use “Send test event” in the dashboard, or call POST /webhooks/test directly, to enqueue a signed ping delivery to your endpoint. Either way it goes through the exact same signing and retry pipeline as production events, with no side effects — the right way to verify your handler end to end. The response is 202 Accepted: queued for the next delivery cron run, not delivered synchronously.