# Spike API Webhooks

## When to Use This Skill

* How do I receive Spike API webhooks?
* How do I verify Spike API webhook signatures (`X-Body-Signature`)?
* How do I handle `record_change`, `provider_integration_created` or `provider_integration_deleted` events?
* Why is my Spike API webhook signature verification failing?
* Why does Spike API keep retrying my webhook?

## Verification (core)

Spike API signs the **raw request body** with **HMAC-SHA256**, keyed with the
shared secret from the admin console (used as-is, as UTF-8 bytes), and sends the
**bare lowercase hex digest** (no prefix, no timestamp) as the whole
`X-Body-Signature` header value. Always verify against the **raw body**, never
re-serialized JSON. There is no Spike API webhook SDK, so verify manually:

```javascript
const crypto = require('crypto');

function verifySpikeSignature(rawBody, signature, secret) {
  // Check shape first: Buffer.from(x, 'hex') silently drops invalid characters
  if (typeof signature !== 'string' || !/^[0-9a-f]{64}$/i.test(signature)) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
  const received = Buffer.from(signature.toLowerCase(), 'hex');
  return received.length === expected.length && crypto.timingSafeEqual(expected, received);
}

```

```python
import hashlib, hmac, re

def verify(raw_body: bytes, signature: str, secret: str) -> bool:
    if not re.fullmatch(r"[0-9a-fA-F]{64}", signature):
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    # Compare bytes, never str
    return hmac.compare_digest(expected.encode(), signature.lower().encode())

```

A missing, empty or malformed header, or a mismatch, is a `401`. Read the body
with `express.raw({ type: '*/*' })` (Express), `await request.arrayBuffer()`
(Next.js) or `await request.body()` (FastAPI), and parse JSON only after the check.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/spike-api-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/spike-api-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/spike-api-webhooks/examples/fastapi/).

## Common Event Types

The body is a **JSON array**; one delivery can batch several events, so loop over
every element. Each element carries its own `event_type`.

| Event | Triggered When | Common Use Cases |
| --- | --- | --- |
| `record_change` | New or updated data arrives from a provider | Fetch the changed records (`metrics`, `activity_types`, `earliest_record_start_at`..`latest_record_end_at`) |
| `provider_integration_created` | A user connects a provider | Mark the integration active |
| `provider_integration_deleted` | A user's integration is deleted | Stop syncing, clean up |

Treat every parsed field as untrusted: check that the body is an array and that
each element and nested field has the expected type before reading it. See
[references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/spike-api-webhooks/references/overview.md).

## Delivery Rules

Respond with exactly HTTP `200` within 30 seconds. Any other status, a network
error or a timeout is retried up to 10 times (5 s, 2 min, 30 min, 2 h, then every
12 h); after that the event is discarded. Return `200` quickly and process
asynchronously, and make handling idempotent.

## Environment Variables

```bash
# Shared HMAC key from the Spike API admin console
SPIKE_API_WEBHOOK_SECRET=your_spike_api_webhook_secret

```

## Local Development

For local webhook testing, run the Hookdeck CLI via `npx` — no install required:

```bash
npx hookdeck-cli listen 3000 spike-api --path /webhooks/spike-api

```

No account required — the CLI creates a guest account on first run and provides a
local tunnel + web UI for inspecting requests. Express and Next.js examples use
port 3000; the FastAPI example uses `8000`.

## Resources

* [Overview](https://github.com/hookdeck/webhook-skills/blob/main/skills/spike-api-webhooks/references/overview.md) - What Spike API webhooks are, event types and payloads
* [Setup](https://github.com/hookdeck/webhook-skills/blob/main/skills/spike-api-webhooks/references/setup.md) - Configure the endpoint and get the shared key
* [Verification](https://github.com/hookdeck/webhook-skills/blob/main/skills/spike-api-webhooks/references/verification.md) - Signature details and gotchas
* [Express Example](https://github.com/hookdeck/webhook-skills/tree/main/skills/spike-api-webhooks/examples/express/) - Express.js implementation
* [Next.js Example](https://github.com/hookdeck/webhook-skills/tree/main/skills/spike-api-webhooks/examples/nextjs/) - Next.js App Router implementation
* [FastAPI Example](https://github.com/hookdeck/webhook-skills/tree/main/skills/spike-api-webhooks/examples/fastapi/) - Python FastAPI implementation