Skip to main content
Lymo delivers webhooks via Svix. Every delivery carries standard signature headers you can verify with any Svix SDK.

Before you register: hostname allowlist

Webhook destinations are gated by a per-organization hostname allowlist. This is a defense-in-depth check on top of Svix’s own URL validation — it prevents a leaked API key from being turned into an SSRF relay via Svix.
The default allowlist for a new organization is empty, which means every POST /v1/webhooks call fails with 422 invalid_webhook_url until your organization’s allowlist contains the hostname you want to deliver to. Ask your Lymo contact (CSM, admin) to add entries to organization_settings.webhook_allowed_hostnames before you start integrating.
Allowlist rules:
  • Scheme must be https://.
  • Exact match: webhook.site permits only webhook.site.
  • Wildcard subdomain: *.example.com permits a.example.com, foo.bar.example.com, but not the apex example.com.
  • Matching is case-insensitive and uses punycode form.

Register an endpoint

curl -X POST "$LYMO_BASE/v1/webhooks" \
  -H "Authorization: Bearer $LYMO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.your-app.example.com/lymo",
    "events": ["video.analysis.completed"]
  }'
The response includes a secret starting with whsec_. Save it immediately — it is returned only at creation time and is required for signature verification. There is no rotation endpoint today; if you lose or leak it, delete the endpoint and create a new one. Omit events (or pass []) to subscribe to every event type.

Event types

EventStatusFires when
video.readyDeliveredVideo finishes processing and is analyzable
video.analysis.completedDeliveredPOST /analyses job succeeds
video.analysis.failedDeliveredPOST /analyses job fails permanently
deal.scoring.completedPlanned (not yet delivered)POST /scorings job succeeds
deal.scoring.failedPlanned (not yet delivered)POST /scorings job fails permanently
The deal.scoring.* events are declared in the schema so SDK types remain stable, but the publisher isn’t wired up yet — subscribing to them today produces no deliveries. They’ll be enabled in a future release. Full payload schemas are in the API Reference tab.

Signature verification

Every delivery has three headers:
  • svix-id — unique delivery ID, stable across retries
  • svix-timestamp — Unix seconds at send time
  • svix-signature — HMAC signature(s). During secret rotation, multiple space-separated signatures are sent so subscribers have a verification window; any matching one proves authenticity.
Verify with the Svix SDK for your language:
import { Webhook } from "svix";

const wh = new Webhook(process.env.LYMO_WEBHOOK_SECRET!);
const payload = wh.verify(rawBody, {
  "svix-id": req.headers["svix-id"] as string,
  "svix-timestamp": req.headers["svix-timestamp"] as string,
  "svix-signature": req.headers["svix-signature"] as string,
});
Reject requests that fail verification. Pass the raw request body to verify — not a re-serialized JSON object.

Delivery semantics

  • Respond with any 2xx status to acknowledge; non-2xx responses or network failures trigger retries with exponential backoff.
  • The svix-id header is stable across retries — store received IDs and skip already-processed events to make your handler idempotent.
  • Retry schedule, timeout, and retention are handled by Svix. See Svix delivery documentation for specifics.

List and delete endpoints

# List registered endpoints
curl "$LYMO_BASE/v1/webhooks" -H "Authorization: Bearer $LYMO_KEY"

# Delete an endpoint
curl -X DELETE "$LYMO_BASE/v1/webhooks/ep_2abcXYZ12345" \
  -H "Authorization: Bearer $LYMO_KEY"
Endpoint IDs are Svix-issued and begin with ep_. Deleting an endpoint is immediate — in-flight deliveries still complete, but no new events are sent.