Skip to main content

Webhooks

A webhook makes Lantfly send an HTTP POST to your URL when a run event happens: send results on to n8n, Zapier, Slack or your own API as soon as a run finishes. Deliveries are signed and retried with backoff. Manage them under Automation → Webhooks.

Events​

EventWhen
ACTOR.RUN.CREATEDA run was started
ACTOR.RUN.SUCCEEDEDA run finished successfully
ACTOR.RUN.FAILEDA run failed
ACTOR.RUN.TIMED_OUTA run reached its timeout
ACTOR.RUN.ABORTEDA run was aborted
ACTOR.RUN.RESURRECTEDA finished run was resurrected

A webhook can be limited to one actor or one task; otherwise it fires for every run of the account.

Create a webhook​

  1. Open Automation → Webhooks and click New webhook.
  2. Enter the URL, pick the Events, and optionally a Description, an actor under Only for this actor (optional), Headers (JSON, optional) and a Payload template (optional).
  3. Click Save webhook.
  4. Copy the Signing secret — shown once and keep it with your receiver. Click I saved it — continue.

With the API:

Create a webhook
curl -s -X POST "https://lantfly.com/api/v3/webhooks" \
-H "Authorization: Bearer $LANTFLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Send TikTok results to our API",
"event_types": ["ACTOR.RUN.SUCCEEDED", "ACTOR.RUN.FAILED"],
"condition": { "actor_id": "lantfly~tiktok-scraper" },
"request_url": "https://example.com/hooks/lantfly",
"headers": { "X-Source": "lantfly" }
}'

The answer carries secret once. Addresses on private or internal networks are refused.

What you receive​

Each delivery is a POST with a JSON body and these headers:

HeaderValue
X-Lantfly-EventThe event type, such as ACTOR.RUN.SUCCEEDED
X-Lantfly-Webhook-Dispatch-IdThe ID of this delivery (the same across retries)
X-Lantfly-Signaturesha256= and the HMAC-SHA256 of the body with your signing secret

The default body:

Default payload
{
"user_id": 1234,
"created_at": "2026-11-03T08:00:05.321Z",
"event_type": "ACTOR.RUN.SUCCEEDED",
"event_data": {
"actor_id": "…",
"task_id": null,
"run_id": "9b1f6c1e-6a4e-4b7f-9d3a-2f0c5d7e8a11"
},
"resource": {
"id": "9b1f6c1e-6a4e-4b7f-9d3a-2f0c5d7e8a11",
"status": "SUCCEEDED",
"default_dataset_id": "…",
"default_key_value_store_id": "…",
"stats": { "result_count": 120 }
}
}

resource is the full run, as GET /api/v3/runs/:run returns it.

Verify the signature​

Compute the HMAC-SHA256 of the raw request body with your signing secret and compare it, in constant time, with the hex value after sha256= in X-Lantfly-Signature. Reject requests that do not match.

Node: verify a delivery
import crypto from 'node:crypto';

function isValid(rawBody, header, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return header?.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

Full examples in several languages are in Webhook signatures.

Payload templates​

A payload template replaces the default body with your own JSON. Placeholders written as {{path}} are filled from the default body above, for example {{resource.default_dataset_id}} or {{event_data.run_id}}. Each placeholder becomes a JSON value (a string gets its quotes), so write placeholders without surrounding quotes:

Payload template
{
"text": "Lantfly run finished",
"event": {{event_type}},
"run_id": {{resource.id}},
"status": {{resource.status}},
"dataset_id": {{resource.default_dataset_id}},
"count": {{resource.stats.result_count}}
}

If the filled-in template is not valid JSON, Lantfly sends it as a string in { "payload": "…" }. Paths use the snake_case names of the body; a path that does not exist becomes null.

Delivery and retries​

  • A delivery succeeds when your URL answers with a 2xx status within 30 seconds.
  • Otherwise it is retried after 1, 5, 25, 125 and 625 seconds (6 attempts in total) before it is marked FAILED.
  • The webhook list shows each webhook's Last delivery and how many deliveries failed. The webhook page lists Recent deliveries (the last 50) with their status, response code and error.

Lantfly notifies you when a webhook keeps failing (webhook.failing, see Notifications).

Test, redeliver, rotate​

ActionConsoleAPI
Send a test nowSend testPOST /api/v3/webhooks/:webhook/test
Send a failed delivery againRedeliver on the deliveryPOST /api/v3/webhooks/:webhook/dispatches/:dispatch/redeliver
Get a new signing secretRotate secretPOST /api/v3/webhooks/:webhook/rotate-secret
Pause or resumeTurn off / Turn onPATCH /api/v3/webhooks/:webhook { "is_enabled": false }
  • Send test posts your account's latest run as a sample, with event_type TEST (or a bare TEST message if you have no run yet). It is tried once, without retries. Up to 10 tests a minute.
  • Redeliver sends a FAILED delivery again with its stored payload, signed and retried like any delivery. Only failed deliveries can be redelivered (422 otherwise).
  • Rotate secret stops the old secret at once. Update your receiver right after.

POST /api/v3/webhooks/bulk enables, disables or deletes up to 200 webhooks at once.

Webhooks for one run​

Pass webhooks when you start a run (POST /api/v3/actors/:actor/runs or POST /api/v3/tasks/:task/runs) to get calls for that run only. They do not appear in your webhook list.

Request body
{
"input": { "hashtags": ["coffee"], "resultsPerPage": 30 },
"webhooks": [
{
"event_types": ["ACTOR.RUN.SUCCEEDED", "ACTOR.RUN.FAILED"],
"request_url": "https://example.com/hooks/run-done",
"headers": { "Authorization": "Bearer your-own-secret" }
}
]
}

Up to 10 per run, each with event_types, request_url and optional payload_template, headers and description. Their signing secret is not returned, so authenticate them with your own headers. A token limited to permissions also needs webhooks.write. Saved tasks and schedules do not store webhooks.

REST hooks for integrations​

Zapier, Make and n8n subscribe to events through REST hooks (/api/v3/hooks). They work like webhooks, signed the same way, and add listening events:

EventWhen
LISTENING.MENTION.CREATEDA listening project collected a new mention
LISTENING.ALERT.FIREDA listening alert fired
RequestWhat it does
GET /api/v3/hooks/eventsEvents a hook can subscribe to
POST /api/v3/hooksSubscribe a target_url to an event (or event_types), filtered by actor_id, task_id or, for listening events, project_id (required). Needs a full-access token.
DELETE /api/v3/hooks/:hookUnsubscribe
GET /api/v3/hooks/samples?event=…Recent payloads of an event, for polling triggers and sample data

Listening events are sent about once a minute, one delivery per new mention or alert. You normally do not call these yourself; the integrations do it for you.