Developers

Built for developers. Documented like it.

Quickstart in 2 minutes. Full REST API. Webhook payloads you can actually read.

Quickstart

1

Create an account

Sign up for free at streamhook.in. No credit card required.

2

Add a source

Paste your database connection URI. We validate permissions and discover tables automatically.

curl -X POST https://api.streamhook.in/v1/sources \
  -H "X-API-Key: sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Postgres",
    "type": "postgresql",
    "connection_uri": "postgres://user:pass@host:5432/mydb",
    "tables": ["orders", "users", "payments"]
  }'
3

Add a destination

Point us to your webhook endpoint. Optionally set a signing secret for HMAC verification.

curl -X POST https://api.streamhook.in/v1/sources/src_xyz/destinations \
  -H "X-API-Key: sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/streamhook",
    "secret": "whsec_your_signing_secret",
    "headers": { "Authorization": "Bearer your_token" }
  }'
4

Receive events

That's it. Every INSERT, UPDATE, DELETE on your selected tables will hit your endpoint in real time.

// Your endpoint receives events like this:
app.post('/webhooks/streamhook', (req, res) => {
  const event = req.body;
  console.log(event.operation);    // "INSERT"
  console.log(event.source.table); // "orders"
  console.log(event.after);        // { id: 42, total: 99.00, status: "paid" }
  res.status(200).send('ok');
});

Webhook Payload Format

Every event delivered to your webhook follows this structure:

{
  "id": "evt_a1b2c3d4e5f6",
  "timestamp": "2026-03-13T10:30:00.123Z",
  "source": {
    "database": "myapp_production",
    "schema": "public",
    "table": "orders"
  },
  "operation": "UPDATE",
  "before": {
    "id": 42,
    "status": "pending",
    "amount": 99.00,
    "updated_at": "2026-03-13T10:29:50.000Z"
  },
  "after": {
    "id": 42,
    "status": "shipped",
    "amount": 99.00,
    "updated_at": "2026-03-13T10:30:00.000Z"
  },
  "metadata": {
    "source_id": "src_xyz789",
    "connector": "postgresql",
    "lsn": "0/1A2B3C4",
    "snapshot": false
  }
}

Fields

id Unique event ID. Use for idempotent processing.
timestamp ISO 8601 timestamp of when the change occurred.
source Database, schema, and table where the change happened.
operation One of: INSERT, UPDATE, DELETE.
before Row state before the change (null for INSERT).
after Row state after the change (null for DELETE).
metadata Internal tracking info: source ID, connector type, LSN offset.

Headers

Content-Type application/json
X-StreamHook-Event-ID evt_a1b2c3d4e5f6
X-StreamHook-Signature sha256=...
X-StreamHook-Timestamp Unix timestamp of delivery
User-Agent StreamHook/1.0

Verifying Webhook Signatures

If you configured a signing secret, verify the HMAC-SHA256 signature on every request:

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

app.post('/webhooks/streamhook', (req, res) => {
  const signature = req.headers['x-streamhook-signature'];

  if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Process the verified event...
  res.status(200).send('ok');
});

API Reference

Base URL: https://api.streamhook.in/v1. Authenticate with X-API-Key header.

POST /sources
Create a new source (database connection)
GET /sources
List all sources
GET /sources/:id
Get source details and stats
PATCH /sources/:id
Update source (pause, resume, edit tables)
DELETE /sources/:id
Delete a source
POST /sources/:id/destinations
Add a webhook destination
GET /sources/:id/destinations
List destinations for a source
PATCH /sources/:id/destinations/:did
Update a destination
DELETE /sources/:id/destinations/:did
Remove a destination
GET /events
List recent events (filterable)
POST /events/:id/retry
Retry a failed event delivery

Ready to integrate?

Get your API key in 30 seconds. 50K events/month free.

No credit card required. Free forever on the Free plan.