agentsclimarketplace

Apify webhooks events

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/apify-pack/skills/apify-webhooks-events

'Implement Apify webhooks for Actor run notifications and event-driven pipelines.From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill apify-webhooks-events

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.1 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it

Apify Webhooks & Events

Overview

Configure webhooks to receive notifications when Actor runs complete, fail, or time out. Apify supports both persistent webhooks (for all runs of an Actor) and ad-hoc webhooks (for a single run). Event-driven architecture is the recommended pattern for production Apify integrations.

Prerequisites

  • npm install apify-client in your project (and express if you build an HTTP handler)
  • An API token in APIFY_TOKEN — read it from the environment (process.env.APIFY_TOKEN) or pass Authorization: Bearer $APIFY_TOKEN on REST calls, never hard-code it
  • A public HTTPS endpoint for Apify to POST to (use ngrok while developing)
  • Familiarity with apify-sdk-patterns

Event Types

EventFired When
ACTOR.RUN.CREATEDA new Actor run starts
ACTOR.RUN.SUCCEEDEDRun finishes with SUCCEEDED status
ACTOR.RUN.FAILEDRun finishes with FAILED status
ACTOR.RUN.ABORTEDRun is manually or programmatically aborted
ACTOR.RUN.TIMED_OUTRun exceeds its timeout
ACTOR.RUN.RESURRECTEDA finished run is resurrected

Instructions

Step 1: Create a Persistent Webhook

Persistent webhooks fire for every run of an Actor. Set condition.actorId, list the eventTypes you care about, and shape the delivered body with payloadTemplate:

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const webhook = await client.webhooks().create({
  eventTypes: ['ACTOR.RUN.SUCCEEDED', 'ACTOR.RUN.FAILED', 'ACTOR.RUN.TIMED_OUT'],
  condition: { actorId: 'YOUR_ACTOR_ID' },
  requestUrl: 'https://your-app.com/api/webhooks/apify',
  payloadTemplate: JSON.stringify({
    eventType: '{{eventType}}',
    actorRunId: '{{actorRunId}}',
    defaultDatasetId: '{{resource.defaultDatasetId}}',
    status: '{{resource.status}}',
    statusMessage: '{{resource.statusMessage}}',
  }),
  isAdHoc: false,
});

console.log(`Webhook created: ${webhook.id}`);

The full payload template (all run fields) and the complete variable table are in payload templates & local testing.

Step 2: Use Ad-Hoc Webhooks for Single Runs

Ad-hoc webhooks are created at run time and fire only for that specific run — pass a webhooks array when starting the Actor:

const run = await client.actor('username/my-actor').start(
  { startUrls: [{ url: 'https://example.com' }] },
  {
    webhooks: [{
      eventTypes: ['ACTOR.RUN.SUCCEEDED', 'ACTOR.RUN.FAILED'],
      requestUrl: 'https://your-app.com/api/webhooks/apify',
    }],
  },
);

The equivalent REST/curl form is in payload templates & local testing.

Step 3: Handle the Webhook

Your endpoint must return a 2xx within 30 seconds, so acknowledge immediately and process asynchronously. On SUCCEEDED, fetch the dataset via defaultDatasetId; on FAILED/TIMED_OUT, pull the run log and alert:

app.post('/api/webhooks/apify', async (req, res) => {
  res.status(200).json({ received: true }); // ack first
  try {
    await processWebhook(req.body); // switch on eventType, fetch dataset, alert
  } catch (error) {
    console.error('Webhook processing failed:', error);
  }
});

The full processWebhook switch (dataset fetch, log tail, oncall alerting) is in full implementation.

Step 4: Make Processing Idempotent, Chain Pipelines, and Manage Webhooks

Apify may deliver a webhook more than once, so dedupe on ${actorRunId}:${eventType} before doing work. You can also chain Actors (Stage 1 SUCCEEDED → start Stage 2) and manage the webhook lifecycle (list, update, delete, inspect dispatches). All three patterns — idempotent processing, event-driven pipeline, and lifecycle management — are in full implementation.

Output

  • A created webhook returns its id (persistent webhooks are visible under client.webhooks().list(); ad-hoc webhooks are scoped to one run)
  • On each matching event, Apify POSTs the rendered payloadTemplate JSON to your requestUrl
  • client.webhook(id).dispatches().list() returns the delivery history — each entry carries a status, createdAt, and the endpoint's responseStatus so you can confirm delivery or diagnose retries

Examples

  • Persistent + ad-hoc webhook creation — Steps 1 and 2 above
  • Full handler, idempotency, pipeline chaining, lifecycle managementfull implementation
  • Payload template variables, REST/curl creation, and local testing with ngrokpayload templates & local testing

Error Handling

IssueCauseSolution
Webhook not deliveredURL unreachableVerify HTTPS, check firewall
Duplicate processingWebhook retry on non-2xxImplement idempotency
Slow processingHandler takes >30sRespond 200 immediately, process async
Missing data in payloadWrong template varsCheck template variable spelling
Webhook disabledToo many failuresRe-enable in Console or via API

Resources

Next Steps

For performance optimization, see apify-performance-tuning.

What ships with it: 2 files

6.0 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 326,144. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.