API Reference

Hooksterr REST API v1

🔑 Authentication

All requests require a Bearer token in the Authorization header.

Authorization: Bearer hk_your_api_key

Log in to see your API key.

Base URL: https://hooksterr.com/api/v1

GET /api/v1/endpoints/ List endpoints

Returns all active webhook endpoints for your account.

Example

curl https://hooksterr.com/api/v1/endpoints/ \
  -H "Authorization: Bearer hk_your_key"

Response

{
  "endpoints": [
    {
      "id": "uuid",
      "name": "My endpoint",
      "url": "https://hooksterr.com/hook/xxx/",
      "token": "xxx",
      "hmac_enabled": false,
      "today_requests": 12,
      "created_at": "2026-01-01T00:00:00Z"
    }
  ],
  "count": 1
}
GET /api/v1/requests/ List requests

Returns webhook requests for a specific endpoint. Supports JSON and CSV export.

Parameters

Name Type Description
token* string Endpoint token or custom slug
limit integer Max results (default: 50, max: 1000)
offset integer Pagination offset
method string Filter by HTTP method (GET, POST, etc.)
after ISO datetime Return requests after this timestamp
format json|csv Response format (default: json)

Example

# JSON
curl "https://hooksterr.com/api/v1/requests/?token=xxx&limit=10" \
  -H "Authorization: Bearer hk_your_key"

# CSV export
curl "https://hooksterr.com/api/v1/requests/?token=xxx&format=csv" \
  -H "Authorization: Bearer hk_your_key" -o requests.csv

Response

{
  "endpoint": "My endpoint",
  "total": 142,
  "limit": 50,
  "offset": 0,
  "requests": [
    {
      "id": "uuid",
      "method": "POST",
      "ip_address": "1.2.3.4",
      "payload_size": 256,
      "content_type": "application/json",
      "duration_ms": 12.4,
      "received_at": "2026-01-01T00:00:00Z",
      "payload": {...},
      "headers": {...}
    }
  ]
}
GET /api/v1/stats/ Account stats

Returns usage statistics and plan limits for your account.

Example

curl https://hooksterr.com/api/v1/stats/ \
  -H "Authorization: Bearer hk_your_key"

Response

{
  "plan": "Pro",
  "limits": {
    "requests_per_day": 2000,
    "retention_days": 14,
    "endpoints": 10
  },
  "usage": {
    "requests_today": 47,
    "requests_this_week": 312,
    "requests_total": 1840,
    "endpoints_active": 3
  }
}
POST /api/v1/rotate-key/ Rotate API key

Generates a new API key and invalidates the old one. Update your integrations immediately.

Example

curl -X POST https://hooksterr.com/api/v1/rotate-key/ \
  -H "Authorization: Bearer hk_your_key"

Response

{
  "key": "hk_new_key_here",
  "message": "API key rotated. Update your integrations."
}

HMAC Signature Verification

Verify webhook authenticity — works with Stripe, GitHub, PayPal, and any service that signs requests

Pro+

When HMAC is enabled on an endpoint, Hooksterr validates the incoming request signature using HMAC-SHA256. The result is stored on the request and visible in your dashboard as ✓ Valid or ✗ Invalid.

Enable HMAC on an endpoint from your Dashboard → ⚙ Settings → HMAC Verification toggle. Hooksterr will auto-generate a secret key.

How it works

1The sender signs the raw request body with your shared secret using HMAC-SHA256.
2The signature is sent in the X-Hook-Signature header as sha256=<hex>.
3Hooksterr recomputes the signature and compares — result logged on every request.

Accepted signature headers

Header Used by
X-Hook-SignatureHooksterr native
X-Hub-Signature-256GitHub, PayPal
X-Hub-SignatureGitHub (legacy), Facebook

Stripe uses Stripe-Signature with a different format — forward Stripe webhooks to your own server and verify there.

Verify in your app (Python)

import hmac
import hashlib

def verify_hooksterr(raw_body: bytes, secret: str, signature: str) -> bool:
    """
    raw_body  — request.body (raw bytes, do NOT parse first)
    secret    — your endpoint HMAC secret from Hooksterr dashboard
    signature — value of X-Hook-Signature header
    """
    sig = signature.replace("sha256=", "")
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

# Flask example
from flask import request, abort

@app.route("/webhook", methods=["POST"])
def webhook():
    sig = request.headers.get("X-Hook-Signature", "")
    if not verify_hooksterr(request.get_data(), "your-secret", sig):
        abort(400, "Invalid signature")
    # process webhook...
    return {"ok": True}

Node.js

const crypto = require('crypto');

function verifyHooksterr(rawBody, secret, signature) {
  const sig = signature.replace('sha256=', '');
  const expected = crypto.createHmac('sha256', secret)
    .update(rawBody)  // rawBody must be Buffer or string, NOT parsed JSON
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(sig, 'hex')
  );
}

// Express example
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
  const sig = req.headers['x-hook-signature'] || '';
  if (!verifyHooksterr(req.body, process.env.HOOKSTERR_SECRET, sig)) {
    return res.status(400).json({ error: 'Invalid signature' });
  }
  const payload = JSON.parse(req.body);
  // process...
  res.json({ ok: true });
});