elefymove

Документация для разработчиков

Руководства и справочник по ElefyMove Open API.

Эти руководства пока доступны только на английском языке.

Endpoints

МетодЭндпоинтОбласть доступаНазначение
PUT/api/public/v1/webhookswebhooks:manageЗадать URL эндпоинта webhook и при необходимости заменить список событий подписки.
GET/api/public/v1/webhookswebhooks:manageПолучить текущую конфигурацию webhook. Секрет подписи никогда не возвращается.
DELETE/api/public/v1/webhookswebhooks:manageОчистить URL webhook и остановить доставку.
POST/api/public/v1/webhooks/testwebhooks:manageОтправить подписанное тестовое событие на настроенный эндпоинт независимо от текущей подписки.
GET/api/public/v1/webhook-deliverieswebhooks:manageПолучить список собственных попыток доставки webhook со статусом, временными метками и историей повторов.
POST/api/public/v1/webhook-deliveries/{id}/redeliverwebhooks:manageВручную повторить неудачную или помеченную как недоставленную доставку.

Configuration

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.

Events

Какие события можно получатьНазначение
listing.approvedA listing you submitted passed moderation and is live.
listing.rejectedA listing you submitted was rejected by moderation.
availability.changedA listing’s calendar changed outside your own writes — a booking, block, or hold from another channel.
hold.createdA temporary hold was placed on one of your listings.
hold.releasedA hold was released before it expired.
hold.expiredA hold reached its TTL and expired.
booking.createdAn ElefyMove booking was confirmed on one of your listings (dates and references only).
booking.cancelledAn ElefyMove booking on one of your listings was cancelled.
pingManual test delivery — from the dashboard or POST /webhooks/test — same signing, no side effects.

Verifying signatures

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();
  },
);

Retries & redelivery

  • Respond with a 2xx quickly — anything else counts as a failed attempt.
  • Failed deliveries retry on a backoff of 1m, 5m, 30m, 2h, 12h, then dead-letter.
  • Failed and dead-lettered deliveries can be redelivered manually from the dashboard’s delivery log.
  • Deliveries can arrive more than once — key your processing on the delivery id or your own idempotency check.

Test deliveries

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.