# Webhook Delivery-Gap Monitor (`mehdi_badawi/webhook-delivery-gap-monitor`) Actor

Find missing, pending, duplicate, late, and out-of-order webhook deliveries by reconciling provider manifests with receiver logs. Returns auditable results; does not deliver webhooks.

- **URL**: https://apify.com/mehdi\_badawi/webhook-delivery-gap-monitor.md
- **Developed by:** [Mehdi Badawi](https://apify.com/mehdi_badawi) (community)
- **Categories:** Developer tools, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 resolved webhook event reconciliations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Webhook Delivery-Gap Monitor

Find missing, pending, duplicate, late, and out-of-order webhook deliveries by
reconciling provider event manifests with receiver logs. Every result carries
the evidence needed to audit the verdict.

### Start in 30 seconds

1. Select **Try for free** and run with no input for a labeled demo.
2. Supply provider events, consumer receipts, a coverage window, and your
   delivery grace period.
3. Schedule the Actor after both systems export their logs.

**Price:** $0.0005 per resolved expected event, plus a $0.00005 start event.
Unknown, failed, unmatched-consumer, and demo rows are free.

This Actor does not deliver or replay webhooks and does not connect to Stripe,
Shopify, GitHub, or your receiver.

Webhooks are fundamentally asynchronous and best-effort. Platforms like Stripe, Shopify, and GitHub drop deliveries due to transient outages, exhausted retries (Shopify unregisters webhooks after 8 consecutive failures), or silent network loss.

This Apify Actor reconciles upstream provider manifests against downstream consumer receipt logs to pinpoint:

1. **Missed Deliveries (`missing`)**: Events logged by provider but absent from consumer database.
2. **Duplicates (`duplicate`)**: Events delivered multiple times.
3. **Delivery Delays (`delayed`)**: Deliveries exceeding latency SLA thresholds.
4. **Sequence Inversions (`out-of-order`)**: Out-of-order event sequence delivery.
5. **Truthful Unknowns (`unknown`)**: Unverifiable events due to incomplete provider logs, unattested sequence windows, or ambiguous timestamps.
6. **Pending (`pending`)**: An event is still inside its configured delivery grace period.

#### Truthful Unknown Semantics

The Actor never manufactures optimistic `ok` verdicts or false `missing` claims when evidence is ambiguous:

- When `coverage.isComplete === false`, missing records report `unknown` (`provider-log-truncated`).
- When events fall outside declared coverage windows, they report `unknown` (`coverage-unattested`).
- When timestamps are unparseable or inverted, they report `unknown` (`time-ambiguous`).
- A missing receipt is not called `missing` until the grace period has elapsed and a real complete coverage window contains the event.

***

### Quickstart & Local Execution

#### 1. Run Unit and Behavior Tests

The test suite uses Node.js built-in test runner without external dependencies or cloud tokens:

```bash
npm test
```

#### 2. Credential-Free Default Execution

Running `npm start` without any input or credentials completes in seconds, uses the built-in deterministic demo dataset, and writes a non-empty dataset to storage:

```bash
npm start
```

***

### File Structure

| File | Purpose |
|---|---|
| `package.json` | Actor manifest, dependencies (`apify: 3.7.2`), `start` and `test` scripts |
| `Dockerfile` | Apify Actor container image specification (`apify/actor-node:22`) |
| `.actor/` | Apify Actor specification, input/output/dataset/KVS JSON schemas |
| `contracts/` | Normative contract (`CONTRACT.md`) and JSON Schema validators |
| `fixtures/` | Realistic test fixtures (demo, Stripe gap, Shopify drop, GitHub gap, truthful unknowns) |
| `src/core/` | Pure deterministic evaluation core (`reconcile.mjs`, `detect.mjs`, `canonical.mjs`) |
| `src/main.mjs` | Thin Apify Actor adapter with injected seams and demo fallback |
| `tests/` | Comprehensive test suite covering gate, core, detect, and actor lifecycle |

***

### Security and privacy boundaries

- **Zero Secrets**: Requires no API tokens, user session cookies, or private credentials.
- **Zero Headless / Scraping Dependencies**: Pure Node.js data processing.
- **No Network Egress**: Processing is completely local and deterministic.
- Prefer event identifiers and timestamps over raw payloads. Receipt logs can
  expose transactions or customer data; minimize them and delete datasets and
  stores under your retention policy.
- Support owner: Mehdi Badawi through the Apify Store support channel, with an
  initial-response target of two business days.

# Actor input Schema

## `contractVersion` (type: `string`):

Must equal 1.0.0. The Actor stamps this automatically when omitted.

## `evaluationTime` (type: `string`):

ISO-8601 evaluation instant treated as 'now'. If omitted, uses the run start time.

## `provider` (type: `string`):

Webhook source provider.

## `providerEvents` (type: `array`):

Events emitted or logged by the upstream provider.

## `consumerEvents` (type: `array`):

Events received and processed by the downstream consumer application.

## `coverage` (type: `object`):

Attestation of provider coverage span (from, until, isComplete). If isComplete is false or omitted, unobserved spans report unknown.

## `tolerances` (type: `object`):

Configurable latency SLA thresholds and duplication policies.

## `useDemoFixture` (type: `boolean`):

Run the built-in deterministic demo dataset regardless of input.

## Actor input object example

```json
{
  "contractVersion": "1.0.0",
  "provider": "generic",
  "useDemoFixture": false
}
```

# Actor output Schema

## `gaps` (type: `string`):

Reconciled events and detected delivery gaps.

## `runOutput` (type: `string`):

Gap counts, run status, warnings, and provenance.

## `state` (type: `string`):

Cursor and receipt-order high-water state.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("mehdi_badawi/webhook-delivery-gap-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("mehdi_badawi/webhook-delivery-gap-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call mehdi_badawi/webhook-delivery-gap-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mehdi_badawi/webhook-delivery-gap-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9mQLLL9XBnf0vrxhj/builds/L02ohvoHdCyA7RGvm/openapi.json
