Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/vectorize-io/hindsight/llms.txt

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

Webhooks let your application receive real-time HTTP notifications when Hindsight completes background operations. Instead of polling the Operations API, you register an endpoint on your server and Hindsight calls it automatically whenever a matching event occurs — such as a retain completing, observations being consolidated, or a mental model being refreshed. Webhooks are registered per memory bank and fire once per event.

Delivery and retries

Failed deliveries (non-2xx response or timeout after 30 seconds) are retried with exponential backoff:
AttemptDelay after failure
15 seconds
25 minutes
330 minutes
42 hours
55 hours
6Permanent failure
Webhook delivery is at-least-once. Delivery tasks are enqueued in the same database transaction as the triggering operation, so your endpoint may receive the same event more than once. Use the operation_id field to deduplicate.

Create a webhook

POST /v1/{tenant}/banks/{bank_id}/webhooks
Registers a new webhook endpoint for the specified bank.

Request parameters

path.tenant
string
required
Your tenant identifier. Use default for single-tenant deployments.
path.bank_id
string
required
The memory bank to register the webhook for.
url
string
required
The HTTPS URL Hindsight will POST events to. Must be publicly reachable.
events
string[]
required
One or more event types to subscribe to. Accepted values: "retain.completed", "consolidation.completed".

Response fields

id
string
required
Unique webhook ID. Use this to list or delete the webhook.
bank_id
string
required
The memory bank this webhook is registered for.
url
string
required
The registered endpoint URL.
events
string[]
required
The event types this webhook listens for.
created_at
string
required
ISO 8601 timestamp of when the webhook was created.

Example

curl -X POST "https://your-hindsight-host/v1/default/banks/my-bank/webhooks" \
  -H "Authorization: Bearer $HINDSIGHT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example.com/hooks/hindsight",
    "events": ["retain.completed", "consolidation.completed"]
  }'
Example response:
{
  "id": "wh_a1b2c3d4e5f6",
  "bank_id": "my-bank",
  "url": "https://your-app.example.com/hooks/hindsight",
  "events": ["retain.completed", "consolidation.completed"],
  "created_at": "2026-03-04T12:00:00Z"
}

List webhooks

GET /v1/{tenant}/banks/{bank_id}/webhooks
Returns all webhooks registered for the specified bank.

Response fields

items
object[]
required
List of registered webhooks.

Example

curl "https://your-hindsight-host/v1/default/banks/my-bank/webhooks" \
  -H "Authorization: Bearer $HINDSIGHT_API_KEY"

Delete a webhook

DELETE /v1/{tenant}/banks/{bank_id}/webhooks/{webhook_id}
Permanently removes a webhook. No further events are delivered to the registered URL.

Example

curl -X DELETE "https://your-hindsight-host/v1/default/banks/my-bank/webhooks/wh_a1b2c3d4e5f6" \
  -H "Authorization: Bearer $HINDSIGHT_API_KEY"

Webhook payload format

When an event fires, Hindsight sends an HTTP POST to your registered URL with a JSON body. All payloads share the following top-level fields:
event
string
required
The event type that triggered this delivery: "retain.completed" or "consolidation.completed".
bank_id
string
required
The memory bank the event originated from.
operation_id
string
required
Unique identifier for the operation. Use this to deduplicate deliveries — Hindsight provides at-least-once delivery.
status
string
required
Terminal status of the operation: "completed" or "failed".
timestamp
string
required
ISO 8601 timestamp of when the event occurred.
data
object
required
Event-specific data. Shape varies by event type — see the sections below.

retain.completed

Fired once per content item after a retain operation finishes. When a batch contains N items, N separate events are delivered.
data.document_id
string | null
The document ID if one was provided in the retain request. null if auto-generated.
data.tags
string[] | null
Document-level tags applied during retain.
Example payload:
{
  "event": "retain.completed",
  "bank_id": "my-bank",
  "operation_id": "a1b2c3d4e5f6",
  "status": "completed",
  "timestamp": "2026-03-04T12:00:01Z",
  "data": {
    "document_id": "doc-abc123",
    "tags": ["meeting", "q1-2026"]
  }
}
For async retain (async: true), operation_id matches the ID returned by the retain API. For sync retain, operation_id is a generated tracing identifier.

consolidation.completed

Fired after Hindsight finishes consolidating new memories into observations for a bank.
data.observations_created
integer | null
Number of new observations created.
data.observations_updated
integer | null
Number of existing observations updated.
data.observations_deleted
integer | null
Number of observations deleted.
data.error_message
string | null
Set when status is "failed". Describes what went wrong.
Example payload:
{
  "event": "consolidation.completed",
  "bank_id": "my-bank",
  "operation_id": "a1b2c3d4e5f6",
  "status": "completed",
  "timestamp": "2026-03-04T12:00:00Z",
  "data": {
    "observations_created": 3,
    "observations_updated": 1,
    "observations_deleted": null,
    "error_message": null
  }
}

Receiving and handling events

Your endpoint should return a 2xx status code as quickly as possible. If processing takes time, acknowledge the request immediately and handle the payload asynchronously.
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/hooks/hindsight", methods=["POST"])
def handle_hindsight_event():
    payload = request.get_json()
    event = payload.get("event")
    operation_id = payload.get("operation_id")

    # Deduplicate using operation_id
    if already_processed(operation_id):
        return jsonify({"ok": True}), 200

    if event == "retain.completed":
        document_id = payload["data"].get("document_id")
        # handle retain completion...

    elif event == "consolidation.completed":
        created = payload["data"].get("observations_created", 0)
        # handle consolidation completion...

    mark_processed(operation_id)
    return jsonify({"ok": True}), 200

Error codes

StatusCodeDescription
400invalid_requestMalformed request body or missing required fields.
401unauthorizedMissing or invalid API key.
404bank_not_foundThe specified bank does not exist.
404webhook_not_foundThe specified webhook does not exist.
422validation_errorOne or more fields failed validation (e.g. unsupported event type).
500internal_errorServer error.

Build docs developers (and LLMs) love