> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.pivotal.app/llms.txt.
> For full documentation content, see https://docs.pivotal.app/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.pivotal.app/_mcp/server.

# Webhooks quickstart

Receive your first Pivotal event on a local server in under five minutes. The flow: tunnel a local port to a public URL, register the URL as a Pivotal webhook endpoint, send a test event from the dashboard, verify the signature on receipt.

PREREQUISITES

* Node 20+ or Python 3.10+
* An admin role on your Pivotal workspace (you'll need to register the endpoint)
* A local tunnel — [ngrok](https://ngrok.com), [Cloudflare tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/), or [Tailscale Funnel](https://tailscale.com/kb/1223/funnel/)

1\. RUN A LOCAL RECEIVER

```typescript title="webhook-receiver.ts"
import { Webhook } from "svix";
import { createServer } from "node:http";

const SECRET = process.env.PIVOTAL_WEBHOOK_SECRET!;
const wh = new Webhook(SECRET);

createServer((req, res) => {
  if (req.method !== "POST") return res.writeHead(405).end();

  let body = "";
  req.on("data", (chunk) => (body += chunk));
  req.on("end", () => {
    const headers = {
      "svix-id": req.headers["svix-id"] as string,
      "svix-timestamp": req.headers["svix-timestamp"] as string,
      "svix-signature": req.headers["svix-signature"] as string,
    };
    try {
      const event = wh.verify(body, headers) as { type: string; id: string };
      console.log(`${event.type} · ${event.id}`);
      res.writeHead(200).end("ok");
    } catch {
      res.writeHead(401).end("invalid signature");
    }
  });
}).listen(8787, () => console.log("listening on :8787"));
```

```bash
bun webhook-receiver.ts
# or: ts-node webhook-receiver.ts
```

2\. EXPOSE THE PORT

Pick whichever tunnel you already use. ngrok example:

```bash
ngrok http 8787
# Forwarding  https://aurora-1234.ngrok.app -> http://localhost:8787
```

Copy the `https://` URL.

3\. REGISTER THE ENDPOINT

1. Open [Admin → Developer → Webhooks](https://my.pivotal.app/admin/webhooks)
2. Click **Add endpoint**
3. Paste the ngrok URL
4. Pick `customer.created` and `task.completed` for now
5. Copy the **signing secret** and `export PIVOTAL_WEBHOOK_SECRET=…` in your receiver shell

4\. FIRE A TEST EVENT

In the Webhooks dashboard, click your endpoint, then **Send test event**. Pick `customer.created`. Your terminal logs the event type + id, the dashboard shows a green check, and the **Logs** tab records the delivery with the full payload.

5\. WHAT TO READ NEXT

* [Event envelope](/webhooks/envelope) — the standard shape of every payload
* [Signature verification](/webhooks/signing) — what the Svix SDK does under the hood
* [Retries and backoff](/webhooks/retries) — what happens when your server returns non-2xx

Stuck? Email **[help@pivotal.app](mailto:help@pivotal.app)** with your endpoint URL and the Pivotal event id (`evt_…`) from the delivery log.