# Webhook Signature Docs Audit (`defenestrator/webhook-signature-doc-audit`) Actor

Audit public API documentation for webhook signature-verification completeness: headers, HMAC/signing algorithm, timestamp/replay protection, secrets, examples, and payload guidance.

- **URL**: https://apify.com/defenestrator/webhook-signature-doc-audit.md
- **Developed by:** [Defenestrator](https://apify.com/defenestrator) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 webhook docs audit rows

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Webhook Signature Docs Audit

Audit public API documentation for webhook signature-verification coverage and export one structured checklist row per docs URL.

Use this Actor when you need a repeatable way to review whether webhook docs explain the security details developers need: signature headers, signing algorithms, raw-body handling, replay protection, secret setup, test events, and implementation examples.

This is an unofficial documentation-audit utility. It does not test live webhook delivery, log in to private portals, or certify a provider's security implementation.

### Common use cases

| Use case | Why it helps |
|---|---|
| API documentation launch review | Check whether webhook verification docs are ready before publishing or relaunching developer docs. |
| Vendor technical diligence | Compare how clearly SaaS vendors document webhook verification before building integrations. |
| Security checklist automation | Produce one row per provider with scoring, evidence URLs, warnings, and recommendations. |
| DevRel / docs QA | Identify missing implementation details that cause insecure or broken webhook receivers. |
| Integration agency review | Triage many public docs sites before deeper manual review. |

### Input

Provide public HTTP(S) documentation URLs. Direct webhook verification pages work best, but broader developer-portal URLs can also be used with a small crawl budget.

```json
{
  "startUrls": [
    { "url": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries" }
  ],
  "maxPagesPerSite": 3,
  "timeoutSecs": 20,
  "sameHostOnly": true
}
````

#### Input fields

| Field | Type | Default | Notes |
|---|---:|---:|---|
| `startUrls` | array | required | Public API docs, webhook docs, developer-portal pages, or vendor docs URLs. |
| `maxPagesPerSite` | integer | `8` | Maximum successful pages analyzed per input URL. Lower values keep runs cheap and focused. |
| `timeoutSecs` | integer | `20` | HTTP timeout per page request. |
| `sameHostOnly` | boolean | `true` | Keeps discovered candidate links on the same host as the input URL. |

Do not submit confidential, authenticated, internal, or non-public documentation URLs.

### Output

The Actor writes one dataset item per input URL. Rows include:

- `domain`, `inputUrl`, `normalizedUrl`
- `auditScore`, `grade`, and `riskLevel`
- checklist booleans such as `webhookDocsFound`, `signatureVerificationDocumented`, `signatureAlgorithmMentioned`, `signatureHeaderNamed`, `timestampOrReplayProtectionMentioned`, `signingSecretMentioned`, `codeExamplesFound`, and `rawBodyOrCanonicalizationMentioned`
- detected signature headers and algorithms when found
- `bestPageUrl`, `evidenceUrls`, sampled URLs, warnings, and practical recommendations

### Pricing

from $4.00 / 1,000 audited webhook documentation URLs

This Actor uses Apify Pay per Event pricing with platform usage included. The row event is charged only for useful rows written to the default dataset.

| Event | Price | Unit |
|---|---:|---|
| Actor start (`apify-actor-start`) | `$0.00005` | Once when the run starts. |
| Webhook docs audit row (`apify-default-dataset-item`) | `$0.004` | Per audited webhook documentation URL row. |

A row is one public webhook documentation URL audit result. Apify plan discounts, user-configured max-charge limits, and any future Apify pricing UI changes may affect final charges.

### Limitations and responsible use

- This is a heuristic documentation audit, not legal advice, security certification, penetration testing, or live webhook validation.
- A high score means the public docs appear to cover important implementation details; it does not prove webhooks are signed correctly in production.
- JavaScript-heavy, blocked, sparse, or login-gated documentation may under-score.
- Human review is recommended before relying on results for high-stakes vendor, security, procurement, or compliance decisions.
- Use only with documentation you are allowed to access and review.

### Data handling

The Actor fetches the public URLs supplied in the input and, when enabled, a small set of same-host candidate links. It writes structured audit rows to the run's default dataset and intentionally avoids storing full page contents in output.

### Related Actors in this portfolio

This Actor is part of the **API documentation reliability audits** group. These are narrow, source-specific Apify Actors intended for scheduled checks and repeatable dataset exports — not broad scraped-content feeds.

- [Webhook Signature Docs Audit](https://apify.com/defenestrator/webhook-signature-doc-audit) — Webhook signature-verification documentation audit for integration readiness.
- [Rate Limit Docs Audit](https://apify.com/defenestrator/rate-limit-docs-audit) — API rate-limit documentation audit for quota, header, reset, and retry clarity.
- [Idempotency Docs Audit](https://apify.com/defenestrator/idempotency-docs-audit) — API idempotency documentation audit for retry-safety and duplicate handling.
- [API Error Contract Docs Audit](https://apify.com/defenestrator/api-error-contract-docs-audit) — API error-contract documentation audit for status codes, error bodies, and examples.

Each listing includes its own source notes, limits, pricing, and responsible-use caveats. Use the official source links in each Actor when decisions require verification.

# Actor input Schema

## `startUrls` (type: `array`):

Public HTTP(S) API documentation, developer portal, webhook documentation URL, or vendor domain to audit. Do not enter private, confidential, localhost, internal-network, or non-public URLs.

## `maxPagesPerSite` (type: `integer`):

Maximum number of successful HTML/text pages to analyze per input. The Actor may fetch additional candidate URLs to find webhook docs, but only analyzes up to this many pages.

## `timeoutSecs` (type: `integer`):

HTTP timeout per request.

## `sameHostOnly` (type: `boolean`):

Only follow discovered links on the same hostname as the input URL. Recommended for predictable, low-cost audits.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries"
    },
    {
      "url": "https://www.svix.com/resources/glossary/webhook-signature"
    }
  ],
  "maxPagesPerSite": 8,
  "timeoutSecs": 20,
  "sameHostOnly": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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 = {
    "startUrls": [
        {
            "url": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries"
        },
        {
            "url": "https://www.svix.com/resources/glossary/webhook-signature"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("defenestrator/webhook-signature-doc-audit").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 = { "startUrls": [
        { "url": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries" },
        { "url": "https://www.svix.com/resources/glossary/webhook-signature" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("defenestrator/webhook-signature-doc-audit").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries"
    },
    {
      "url": "https://www.svix.com/resources/glossary/webhook-signature"
    }
  ]
}' |
apify call defenestrator/webhook-signature-doc-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=defenestrator/webhook-signature-doc-audit",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Webhook Signature Docs Audit",
        "description": "Audit public API documentation for webhook signature-verification completeness: headers, HMAC/signing algorithm, timestamp/replay protection, secrets, examples, and payload guidance.",
        "version": "0.0",
        "x-build-id": "HdG87AIViOlOm8lvs"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/defenestrator~webhook-signature-doc-audit/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-defenestrator-webhook-signature-doc-audit",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/defenestrator~webhook-signature-doc-audit/runs": {
            "post": {
                "operationId": "runs-sync-defenestrator-webhook-signature-doc-audit",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/defenestrator~webhook-signature-doc-audit/run-sync": {
            "post": {
                "operationId": "run-sync-defenestrator-webhook-signature-doc-audit",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "API docs or vendor URLs to audit",
                        "maxItems": 100,
                        "type": "array",
                        "description": "Public HTTP(S) API documentation, developer portal, webhook documentation URL, or vendor domain to audit. Do not enter private, confidential, localhost, internal-network, or non-public URLs.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "maxPagesPerSite": {
                        "title": "Max documentation pages per site",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "Maximum number of successful HTML/text pages to analyze per input. The Actor may fetch additional candidate URLs to find webhook docs, but only analyzes up to this many pages.",
                        "default": 8
                    },
                    "timeoutSecs": {
                        "title": "Request timeout seconds",
                        "minimum": 5,
                        "maximum": 60,
                        "type": "integer",
                        "description": "HTTP timeout per request.",
                        "default": 20
                    },
                    "sameHostOnly": {
                        "title": "Stay on the same host",
                        "type": "boolean",
                        "description": "Only follow discovered links on the same hostname as the input URL. Recommended for predictable, low-cost audits.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
