Web-Nothing Docs
Guides

Webhooks

Webhooks

Webhooks let external services (GitHub, Stripe, Zapier, etc.) push data into your Web-Nothing apps. Each incoming payload creates a record in the target data table and can trigger automated workflows.


Quick Start

  1. Create a webhook on your app (from the workspace or via API)
  2. Configure the external service to POST to the webhook URL
  3. Include the shared secret in the x-webhook-secret header

Creating a Webhook

From the Workspace

  1. Open your app in the editor.
  2. Go to the app's settings panel.
  3. Add a new webhook with a name, target data table, and a secret (minimum 8 characters).

Via API

curl -X POST https://web-nothing.vercel.app/api/apps/APP_ID/webhooks \
  -H "Content-Type: application/json" \
  -H "Cookie: authjs.session-token=SESSION" \
  -d '{
    "name": "GitHub Push Events",
    "targetSchema": "events",
    "secret": "my-secure-secret-123"
  }'

Required fields:

FieldTypeConstraints
namestring1-255 characters
targetSchemastringMust match a data table name in your app
secretstringMinimum 8 characters, stored as SHA-256 hash

Response (201):

{
  "webhook": {
    "id": "clxyz...",
    "name": "GitHub Push Events",
    "targetSchema": "events",
    "enabled": true,
    "hasSecret": true,
    "url": "/api/apps/APP_ID/webhook",
    "createdAt": "2026-03-17T12:00:00.000Z"
  }
}

Receiving Events

External services POST JSON payloads to the webhook receiver endpoint. No session auth is required -- the shared secret authenticates the request.

curl -X POST https://web-nothing.vercel.app/api/apps/APP_ID/webhook \
  -H "Content-Type: application/json" \
  -H "x-webhook-secret: my-secure-secret-123" \
  -d '{
    "repo": "octocat/Hello-World",
    "branch": "main",
    "commit": "abc123",
    "message": "Update README"
  }'

Response (201):

{
  "success": true,
  "id": "generated-uuid"
}

The payload fields are written directly as record fields in the target data table. System fields (id, _webhook, created_at, updated_at) are added automatically and cannot be overridden by the caller.


Secret Verification

Every inbound webhook request must include the x-webhook-secret header. The server:

  1. Hashes the provided secret with SHA-256
  2. Compares it against the stored hash using constant-time comparison (prevents timing attacks)
  3. Returns 401 Unauthorized if the secret is missing or does not match

Secrets are never stored in plaintext -- only the SHA-256 hash is persisted. The hash is never returned in any API response.


Limits

LimitValue
Webhooks per app5
Requests per app30/min
Requests per IP100/min (global)
Payload size64 KB
Records per data table10,000

Exceeding rate limits returns 429 Too Many Requests. Exceeding payload size returns 413 Payload Too Large. Hitting the record cap returns 429 with "Record limit reached".


Workflow Integration

Each received webhook fires two workflow triggers (non-blocking):

  • record_created -- standard data trigger, same as manual record creation
  • webhook_received -- webhook-specific trigger for dedicated automation

Both triggers pass the full new record (including system fields) as the trigger payload. Use these in workflow rules to send notifications, transform data, call external APIs, or chain further actions.


Managing Webhooks

List Webhooks

curl https://web-nothing.vercel.app/api/apps/APP_ID/webhooks \
  -H "Cookie: authjs.session-token=SESSION"

Returns all webhooks for the app with stats (receivedCount, lastReceivedAt). The secret is never exposed -- only a hasSecret boolean is returned.

Enable / Disable

curl -X PUT https://web-nothing.vercel.app/api/apps/APP_ID/webhooks/WEBHOOK_ID \
  -H "Content-Type: application/json" \
  -H "Cookie: authjs.session-token=SESSION" \
  -d '{ "enabled": false }'

Disabled webhooks still exist but the receiver endpoint returns 404 for them.

Update

You can update name, targetSchema, enabled, and secret in a single PUT request. Only include the fields you want to change.

curl -X PUT https://web-nothing.vercel.app/api/apps/APP_ID/webhooks/WEBHOOK_ID \
  -H "Content-Type: application/json" \
  -H "Cookie: authjs.session-token=SESSION" \
  -d '{
    "name": "Renamed Webhook",
    "targetSchema": "new_table",
    "secret": "new-secret-value"
  }'

Delete

curl -X DELETE https://web-nothing.vercel.app/api/apps/APP_ID/webhooks/WEBHOOK_ID \
  -H "Cookie: authjs.session-token=SESSION"

Returns { "success": true }.


Example: GitHub Push Webhook

1. Create the webhook in Web-Nothing:

curl -X POST https://web-nothing.vercel.app/api/apps/APP_ID/webhooks \
  -H "Content-Type: application/json" \
  -H "Cookie: authjs.session-token=SESSION" \
  -d '{
    "name": "GitHub Pushes",
    "targetSchema": "push_events",
    "secret": "gh-webhook-secret-2026"
  }'

2. Configure GitHub:

In your GitHub repo, go to Settings > Webhooks > Add webhook:

  • Payload URL: https://web-nothing.vercel.app/api/apps/APP_ID/webhook
  • Content type: application/json
  • Secret: GitHub uses X-Hub-Signature-256 by default, but Web-Nothing expects x-webhook-secret. Use a proxy or middleware to forward the raw secret in the x-webhook-secret header.

3. Test with curl:

curl -X POST https://web-nothing.vercel.app/api/apps/APP_ID/webhook \
  -H "Content-Type: application/json" \
  -H "x-webhook-secret: gh-webhook-secret-2026" \
  -d '{
    "ref": "refs/heads/main",
    "repository": "octocat/Hello-World",
    "pusher": "octocat",
    "head_commit_message": "Fix typo in README"
  }'

4. Verify: Check your app in the workspace -- a new record appears in the push_events data table with your payload fields plus id, _webhook, created_at, and updated_at.


Error Responses

StatusMeaning
400Invalid JSON, missing fields, body not an object, or data table not found
401Missing or invalid x-webhook-secret header
404App not found, not active, or no enabled webhook
413Payload exceeds 64 KB
429Rate limit exceeded or record cap reached
500Internal error

TopicDocument
Cross-app automationWorkflows
Connecting external APIsAPI Connectors
Connecting AI agents to your appMCP Quick Start
Full MCP referenceMCP Integration Guide
Full user guideUser Guide

On this page