Руководства и справочник по ElefyMove Open API.
Эти руководства пока доступны только на английском языке.
| Метод | Эндпоинт | Область доступа | Назначение |
|---|---|---|---|
| PUT | /api/public/v1/webhooks | webhooks:manage | Задать URL эндпоинта webhook и при необходимости заменить список событий подписки. |
| GET | /api/public/v1/webhooks | webhooks:manage | Получить текущую конфигурацию webhook. Секрет подписи никогда не возвращается. |
| DELETE | /api/public/v1/webhooks | webhooks:manage | Очистить URL webhook и остановить доставку. |
/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.