Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.hopsule.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks let you react to events in your Hopsule workspace as they happen — a new decision is accepted, a memory is updated, a PR analysis finishes — by POSTing a signed JSON payload to a URL you control.

Configure your endpoint

In the dashboard, open Settings → Webhooks for the organization you want to subscribe from. You’ll see a single-form page:
1

Endpoint URL

The HTTPS URL Hopsule should POST to. Need a quick target for testing? webhook.site gives you a public URL instantly and shows every POST in real time, no signup.
2

Pick events

Tick the events you care about. Unticked events are dropped server- side — the dispatcher records a skipped row so you can audit silent paths.
3

Test endpoint

Click Test to POST a test.preflight envelope synchronously against your URL. If you get a 2xx back, Save unlocks and the signing secret is revealed once. Copy it now — Hopsule never echoes it back on subsequent reads.
4

Save

The secret used in the preflight is persisted, so the signature you just verified during testing is the same one production payloads will carry.
Webhooks are organization-scoped — one endpoint per org. The dispatcher fires asynchronously from the request that triggered the event, so webhook latency never affects user-facing operations.

Payload format

Every POST has the same envelope shape. Subscribers should match on the top-level event field:
POST /your/webhook HTTP/1.1
Content-Type: application/json
User-Agent: Hopsule-Webhooks/1.0
X-Hopsule-Event: decision.created
X-Hopsule-Signature: sha256=4f2a8e...
X-Hopsule-Attempt: 1

{
  "event": "decision.created",
  "occurred_at": "2026-05-11T13:00:00Z",
  "data": { /* the entity, exactly as the REST API returns it */ }
}
The headers are:
HeaderPurpose
X-Hopsule-EventEvent id (matches what you ticked in Settings).
X-Hopsule-Signaturesha256=<hex> HMAC of the raw body.
X-Hopsule-Attempt1 for the original delivery, 2 for the retry.
User-AgentAlways Hopsule-Webhooks/1.0.

Verifying signatures

Compute HMAC-SHA256 of the raw request body using your signing secret, prefix it with sha256=, then constant-time compare against the X-Hopsule-Signature header.
import express from "express";
import crypto from "node:crypto";

const SECRET = process.env.HOPSULE_WEBHOOK_SECRET;
const app = express();
app.use(express.raw({ type: "application/json" }));

app.post("/hopsule/webhook", (req, res) => {
  const sig = req.header("X-Hopsule-Signature") ?? "";
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", SECRET).update(req.body).digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).send("bad signature");
  }
  const event = JSON.parse(req.body.toString());
  console.log(event.event, event.data);
  res.sendStatus(200);
});

app.listen(3000);
Always use a constant-time compare (crypto.timingSafeEqual in Node, hmac.compare_digest in Python, hmac.Equal in Go). A plain == leaks timing information that lets attackers reconstruct your secret byte-by-byte.

Event catalog

Each event id is the same string you tick in Settings → Webhooks. The shape of data mirrors the REST API response for that entity.

Decisions

Event idFires when
decision.createdA draft or proposed decision is added.
decision.updatedStatement, rationale, tags, or links change.
decision.status_changedDRAFT → PENDING → ACCEPTED / REJECTED / DEPRECATED.
decision.deletedA decision is permanently removed.

Memories

Event idFires when
memory.createdA new memory entry is captured.
memory.updatedMemory content or metadata changes.
memory.deletedMemory is removed.

Capsules

Event idFires when
capsule.createdA new context capsule is created.
capsule.updatedBody, scope, or attachments change.
capsule.deletedCapsule is removed.

Tasks

Event idFires when
task.createdA new task is opened.
task.status_changedOpen ↔ in-progress ↔ done.
task.completedTask is marked done.

Pull request analysis

Event idFires when
pr.analysis_completedHopsule finished scanning a pull request.
pr.violation_detectedA PR change conflicts with an accepted decision.
pr.results_acceptedAn admin accepted the proposed PR findings.

Projects

Event idFires when
project.createdA new project is added to the org.
project.import_completedRepository import finished successfully.
project.import_failedRepository import errored; payload includes the reason.

Members

Event idFires when
member.addedA user joined the organization.
member.removedA user was removed.
member.role_changedMember promoted or demoted.

Retries and delivery log

Hopsule retries failed deliveries once, 2 seconds after the first attempt. Failure conditions:
  • network error or timeout (the dispatcher caps each attempt at 8s)
  • any 4xx or 5xx response
Both attempts are logged to the WebhookDelivery table with their response code, body (truncated to 4KB), latency, and error message. You can re-deliver a payload manually by re-saving the endpoint or by firing a Test event. For long-running endpoints, return 200 OK quickly and process asynchronously on your side — the dispatcher does not wait for slow subscribers and will mark them failed on timeout.

Rotating the signing secret

In Settings → Webhooks, click Rotate. A fresh secret is generated and shown once. The old secret stops being valid immediately, so update your subscriber before deployments complete — there is no overlap window.

Test event

The Test button POSTs a test.preflight envelope to your URL synchronously, regardless of your subscription. Use it to:
  • verify the URL is reachable before saving
  • confirm your signature verification code accepts our payload
  • re-check connectivity after a deploy on your side