Hooktopus

For developers

POST to a URL. Get a typed BigQuery table.

No SDK to install. No wrappers to maintain. Hooktopus is a single HTTPS endpoint per stream and a small REST API to manage destinations. The platform is documented top-to-bottom and public-facing — what we ship is what you read.

OpenAPI 3.1 spec · Stainless-generated TS & Python clients · public Postman collection.

curl
# Send any JSON to your endpoint
curl -X POST "https://in.hooktopus.io/ws_abc123/stripe" \
  -H 'content-type: application/json' \
  -H 'authorization: t_••••' \
  -d '{
    "id": "evt_3Pkx9aL",
    "type": "charge.succeeded",
    "data": { "object": { "amount": 12999, "currency": "usd" } }
  }'

# Response (202)
# {"ok":true,"event_id":"019e326c-96f5-7a5f-b104-17239aa5bea4"}

Receive

What we promise on ingest.

UUIDv7 event IDs

Every event gets a 128-bit time-ordered ID. Sortable. Deduplicable. Stable across replays. Returned in the 202 response body and stamped on the BigQuery row.

Canonical archive

Body, headers, source IP, content type — written to R2 as one JSON object ws_/yyyy/mm/dd/hh/endpoint/event.json before we 202. If BigQuery is down, your events still exist.

At-least-once delivery

Queues batch up to 100 events / 30s. Failed BQ writes go to a dead-letter queue with the full error. event_id doubles as the BQ unique key — dedupe is free.

Signature verification

Hookdeck handles Stripe, GitHub, Shopify, HubSpot, Twilio, Linear, and ~25 more signature schemes out of the box. Custom sources can use HMAC-SHA256 with your secret.

Replay-from-anywhere

Re-write any time range from R2 back through the destination writer. Useful after BQ outages, schema changes, or just experimenting in dev.

Honest error semantics

4xx if you sent something we can't parse — payload still archived to a DLQ in R2 either way. 5xx never silently drops; the source's retry logic does its job.

Manage

A small REST API. No SDK required.

create an endpoint
POST /v1/endpoints HTTP/1.1
Host: api.hooktopus.io
Authorization: Bearer hk_live_••••
Content-Type: application/json

{
  "workspace": "ws_abc123",
  "name": "stripe",
  "source": "stripe",
  "hmac_secret": null
}
generate dbt files
POST /v1/endpoints/ep_stripe_x/dbt-export HTTP/1.1
Host: api.hooktopus.io
Authorization: Bearer hk_live_••••
Content-Type: application/json

{
  "min_occurrence_pct": 1.0,
  "include": ["data.object.amount", "type"]
}

# Returns a presigned ZIP URL valid for 5 minutes.
list recent events
GET /v1/endpoints/ep_stripe_x/events?limit=50 HTTP/1.1
Host: api.hooktopus.io
Authorization: Bearer hk_live_••••
replay a range
POST /v1/replay HTTP/1.1
Host: api.hooktopus.io
Authorization: Bearer hk_live_••••
Content-Type: application/json

{
  "endpoint_id": "ep_stripe_x",
  "from": "2026-05-10T00:00:00Z",
  "to":   "2026-05-11T00:00:00Z",
  "destination_id": "dst_bq_prod"
}

Full reference at /docs/api or via the public OpenAPI spec at api.hooktopus.io/openapi.json.

The CLI

On the way (v1.2). Sneak peek:

terminal
# Tail events from any endpoint, like wrangler tail
hooktopus events tail --endpoint stripe

# Sample 50 events into a local file
hooktopus events sample stripe --limit 50 > events.ndjson

# Generate dbt files locally
hooktopus dbt generate stripe --out ./models/staging/hooktopus

# Validate destination connectivity
hooktopus destinations test dst_bq_prod

Want early access? Email cli@hooktopus.io and tell us how you'd use it. We're prioritizing tools we'll actually use ourselves.

Built for engineers

The tool you'd build if you had a Tuesday afternoon.

POST in, BigQuery out. Brutally focused on one job. Read the source code in our public OpenAPI spec — what you see is what we ship.