> ## Documentation Index
> Fetch the complete documentation index at: https://developers.vantageclaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> From zero to verified test event in under 10 minutes.

This guide walks you end-to-end through a working integration: provisioning a key, building a minimal webhook handler with signature verification, subscribing to events, and triggering a test delivery.

## Prerequisites

* A VantageClaw partner organization with a Partner API key issued to you. Keys are admin-provisioned in v1 — contact your VantageClaw representative if you don't have one yet.
* A publicly reachable HTTPS URL for your handler. For local development, [ngrok](https://ngrok.com) or [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) work well.
* Python 3.10+ or Node.js 18+ for the example handler.

## Step 1 — Verify your key

Confirm your key is valid and check what scopes it carries:

```bash theme={null}
curl https://app.vantageclaw.ai/api/v1/partner/me \
  -H "Authorization: Bearer vck_test_REPLACE_ME.your_secret_half_here"
```

You should see your org slug, key ID, and scope list. If you get `401`, double-check the full token includes both halves separated by a dot.

## Step 2 — Build a minimal webhook handler

This handler reads the raw body, verifies the signature, and returns 200. Save as `handler.py`:

```python theme={null}
import hashlib
import hmac
import os
import time
from http.server import BaseHTTPRequestHandler, HTTPServer

SECRET = os.environ["WEBHOOK_SECRET"]
REPLAY_WINDOW_MS = 5 * 60 * 1000


def verify(body: bytes, sig: str, ts: str) -> bool:
    if not sig.startswith("sha256="):
        return False
    try:
        ts_ms = int(ts)
    except ValueError:
        return False
    if abs(int(time.time() * 1000) - ts_ms) > REPLAY_WINDOW_MS:
        return False
    expected = hmac.new(
        SECRET.encode(),
        msg=f"{ts_ms}.".encode() + body,
        digestmod=hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(sig[len("sha256="):], expected)


class Handler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(length)
        sig = self.headers.get("X-VC-Signature", "")
        ts = self.headers.get("X-VC-Timestamp", "")

        if not verify(body, sig, ts):
            self.send_response(401)
            self.end_headers()
            return

        print(f"Verified event: {body.decode()}")
        self.send_response(200)
        self.end_headers()


if __name__ == "__main__":
    HTTPServer(("0.0.0.0", 8080), Handler).serve_forever()
```

Don't start it yet — we need the subscription's secret first.

## Step 3 — Subscribe to the test event

Expose your handler to the public internet. With ngrok:

```bash theme={null}
ngrok http 8080
# Note the https://... forwarding URL
```

Then create the subscription. The response will include a `secret` field — **copy it now**, it is shown only once:

```bash theme={null}
curl https://app.vantageclaw.ai/api/v1/partner/webhooks \
  -H "Authorization: Bearer vck_test_REPLACE_ME.your_secret_half_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-ngrok-id.ngrok.io",
    "events": ["vc.test.ping"]
  }'
```

Response:

```json theme={null}
{
  "id": "wh_a1b2c3d4-...",
  "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "url": "https://your-ngrok-id.ngrok.io",
  ...
}
```

Save the `id` (`wh_...`) and the `secret` (`whsec_...`) — you'll need both.

<Warning>
  The secret is unrecoverable. If you lose it before saving, delete this subscription and create a new one.
</Warning>

## Step 4 — Start your handler with the secret

```bash theme={null}
export WEBHOOK_SECRET="whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
python handler.py
```

You should see `Serving HTTP on 0.0.0.0 port 8080`.

## Step 5 — Trigger the test event

The test endpoint requires you to **echo back your stored secret** in the request body. This is deliberate: VantageClaw does not cache your secret server-side after creation, so the only way to authorize a test is for you to prove you still hold it.

```bash theme={null}
curl https://app.vantageclaw.ai/api/v1/partner/webhooks/wh_a1b2c3d4-.../test \
  -H "Authorization: Bearer vck_test_REPLACE_ME.your_secret_half_here" \
  -H "Content-Type: application/json" \
  -d '{
    "secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  }'
```

Response (`200`):

```json theme={null}
{
  "event_id": "evt_aabbccdd-...",
  "enqueued": true
}
```

The event is now in the dispatch queue. Within a few seconds your handler should log:

```
Verified event: {"event":"vc.test.ping","id":"evt_aabbccdd-...","subscription_id":"wh_a1b2c3d4-...","occurred_at":"...","data":{"message":"integration test"}}
```

The `evt_` ID in your handler's log matches the `event_id` in the test endpoint's response — use this for trace correlation.

## Step 6 — Confirm idempotency (optional but recommended)

Fire the same test twice and watch your handler. Both deliveries will have **different `id` values** (each test invocation generates a fresh envelope ID), so a naive "dedupe on id" handler will process both.

In production, dedupe is most useful when the dispatcher retries after a network blip — the **same** envelope ID arrives twice. To test that scenario, deliberately reject the first delivery (return 500 from your handler for one request) and watch the retry arrive 60 seconds later with the same `id`. Your handler should recognize the duplicate and short-circuit.

## What's next

<Columns cols={2}>
  <Card title="Integration test" icon="circle-check" href="/guides/integration-test">
    The full production-readiness checklist.
  </Card>

  <Card title="Webhook security" icon="shield-check" href="/webhooks/security">
    Verification deep-dive, including Node.js reference code.
  </Card>
</Columns>
