Appearance
Authentication
About 379 wordsAbout 1 min
API Keys
All management API endpoints require an API key passed as a Bearer token.
Authorization: Bearer hk_<key>API keys are prefixed with hk_ and are 32 bytes of random entropy. The full key is shown once at creation — GetHook stores only the SHA-256 hash and a display prefix.
Creating an API key
curl -s -X POST http://localhost:8080/v1/api-keys \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "CI/CD Pipeline"}' | jq .Revoking a key
curl -s -X DELETE http://localhost:8080/v1/api-keys/<key-id> \
-H "Authorization: Bearer $API_KEY"A revoked key returns 401 Unauthorized immediately on any subsequent request.
Ingest Endpoint Authentication
POST /ingest/{token} does not use Bearer authentication. The path_token embedded in the URL (prefixed src_) acts as the credential. Treat it as a secret.
Inbound Signature Verification
If a source has auth_mode: "shared_secret", GetHook can verify the provider's HMAC signature before accepting the event. Configure the verification in verification_config when creating the source.
Outbound HMAC Signing
GetHook signs all outbound HTTP deliveries using HMAC-SHA256. The signature header format is Stripe-compatible:
Webhook-Signature: t=1700000000,v1=a3f9b2...Where:
t— Unix timestamp of the delivery attemptv1— HMAC-SHA256 hex digest of{t}.{body}using the destination'ssigning_secret
Recipients should validate:
- Parse
tandv1from the header - Compute
HMAC-SHA256(signing_secret, "{t}.{body}") - Compare with constant-time equality
- Reject if
|now - t| > 300seconds (replay protection)
Example verification (Node.js)
const crypto = require("crypto");
function verifyWebhook(payload, header, secret) {
const [tPart, v1Part] = header.split(",");
const t = tPart.split("=")[1];
const v1 = v1Part.split("=")[1];
const expected = crypto
.createHmac("sha256", secret)
.update(`${t}.${payload}`)
.digest("hex");
const valid = crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(v1, "hex")
);
if (!valid) throw new Error("Invalid signature");
if (Math.abs(Date.now() / 1000 - parseInt(t)) > 300)
throw new Error("Timestamp too old");
return true;
}Example verification (Python)
import hmac, hashlib, time
def verify_webhook(payload: str, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t, v1 = parts["t"], parts["v1"]
expected = hmac.new(
secret.encode(), f"{t}.{payload}".encode(), hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, v1):
raise ValueError("Invalid signature")
if abs(time.time() - int(t)) > 300:
raise ValueError("Timestamp too old")
return True