ElefyMove Open APIのガイドとリファレンス。
これらのガイドは現在英語のみで提供されています。
| メソッド | エンドポイント | スコープ | 内容 |
|---|---|---|---|
| PUT | /api/public/v1/webhooks | webhooks:manage | webhookのエンドポイントURLを設定し、必要に応じてイベント購読リストを置き換えます。 |
| GET | /api/public/v1/webhooks | webhooks:manage | 現在のwebhook設定を取得します。署名シークレットが返されることはありません。 |
| DELETE | /api/public/v1/webhooks | webhooks:manage | webhookのURLを削除し、配信を停止します。 |
/api/public/v1/webhooks/test | webhooks:manage | 現在の購読状況にかかわらず、設定済みのエンドポイントへ署名付きのテストイベントを送信します。 | |
| 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. 署名シークレットのローテーションはあえて本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.