Webhooks

Webhooks let you receive real-time payment.succeeded notifications whenever a buyer pays for any of your resources โ€” endpoints, products, components, or agent endpoints.

Plan Requirement: Webhooks are available on Pro and Business plans only.

Free plan accounts receive a 403 response when attempting to use the webhook API.

How It Works

Webhooks are account-level (seller-level), not per-resource. You register one webhook URL and it receives events for all resources you own.

๐Ÿ’ฐ

Payment Happens

Buyer pays for any of your resources

๐Ÿ“ก

Webhook Fires

Signed POST request to your URL

โœ…

You Act

Fulfill order, grant access, log it

Setup via Dashboard

  1. Go to Dashboard โ†’ Webhooks
  2. Click Create Webhook
  3. Enter your HTTPS endpoint URL
  4. A signing secret is generated automatically โ€” copy and store it securely

From the Webhooks dashboard you can also toggle webhooks on/off, rotate the signing secret, delete webhooks, and view recent delivery logs.

Event: payment.succeeded

Every webhook delivery is a POST request with this JSON body:

Webhook Payloadjson
{
  "id": "evt_abc123",
  "event": "payment.succeeded",
  "timestamp": "2026-02-26T19:30:00Z",
  "data": {
    "source": "endpoint",
    "source_id": "ep_xyz789",
    "source_slug": "my-api",
    "amount": "1.00",
    "currency": "USDC",
    "tx_hash": "0xabc...def",
    "payer_wallet": "0x1234...5678",
    "network": "base",
    "status": "settled"
  }
}
FieldDescription
sourceResource type: endpoint, product
source_slugThe slug of the resource that was paid for
amount / currencyPayment amount and asset (e.g. USDC)
tx_hashOn-chain transaction hash
networkbase or solana

Verifying Signatures

Studio seller webhooks are HMAC-signed. Current deliveries include four important headers:

  • X-X402-Signature โ€” HMAC-SHA256 hex digest of the raw body
  • X-X402-Timestamp โ€” Unix timestamp of when the event was sent
  • X-X402-Event โ€” event type for quick routing / logging
  • X-X402-Event-Id โ€” stable event id for idempotency / replay detection

Verify HMAC-SHA256(timestamp + "." + rawBody) with the webhook signing_secret. Use the raw request body bytes; do not parse and re-serialize JSON before hashing.

Node.js โ€” Verify Webhook Signaturejavascript
const crypto = require('crypto');

function verifyWebhook(rawBody, signature, timestamp, secret) {
  const payload = `${timestamp}.${rawBody}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
Python โ€” Verify Webhook Signaturepython
import hmac, hashlib

def verify_webhook(raw_body: bytes, signature: str, timestamp: str, secret: str) -> bool:
    payload = f"{timestamp}.{raw_body.decode()}"
    expected = hmac.new(
        secret.encode(), payload.encode(), hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

Backward Compatibility

Some older receivers still accept raw-secret headers like x-x402layer-secret, x-x402-secret, or Authorization: Bearer <secret>. Keep that only as fallback for legacy clients. Current Studio deliveries should be verified with the signed HMAC headers first.

Two Secret Hops

1) Studio โ†’ your webhook receiver

Use the webhook signing_secret and the signed HMAC headers.

2) Your receiver โ†’ your app settlement route

Use your own app-internal shared secret. Example: a worker sends x-x402-secret and the app verifies it with X402_WEBHOOK_SECRET.

Do not confuse the Studio webhook signing secret with the app settlement secret. They solve different trust boundaries.

Coverage Matrix

SourceRouteStatus
Endpoint payments/e/:slugLive
Product payments/p/:slugLive
Components (via endpoints)โ€”Live
Agent endpoint create/agent/endpointsLive
Agent endpoint top-up/agent/endpointsLive

Best Practices

๐Ÿ”

Always verify signed headers first

Never trust unverified payloads. Verify the HMAC using timestamp + raw body before any fulfillment logic.

โšก

Respond quickly (< 5s)

Process asynchronously and return 200 immediately. Queue heavy work.

๐Ÿ”„

Handle duplicates

Use the event id for idempotency โ€” you may receive the same event more than once.

๐Ÿ”‘

Rotate secrets carefully

If deliveries suddenly start returning 401, first check whether the webhook signing secret rotated or drifted. Update the receiver before discarding the old value.

๐Ÿงพ

Log headers, not secrets

For debugging, log the presence of signature/timestamp/event/event-id headers. Do not log the secret itself or full sensitive payloads unless absolutely necessary.

๐Ÿ› ๏ธ

Know the common failure mode

If Studio deliveries 401 but a manual POST with the stored secret works, your receiver likely only supports legacy raw-secret auth while Studio is sending signed webhooks.

Webhook API Reference

MethodEndpointDescription
GET/api/webhooksList your webhooks
POST/api/webhooksCreate a new webhook
PATCH/api/webhooks/:idToggle active / rotate secret
DELETE/api/webhooks/:idDelete a webhook