Skip to main content

Webhooks


Webhooks

Overview

Webhooks allow you to receive HTTP callbacks when events occur in your Synapse mind. When an event triggers, Synapse sends a POST request to the URL you configured, with a JSON body containing event data and a HMAC-SHA256 signature for verification.

Webhooks have a 20 webhooks per mind limit.

Events

Event Description
memory.created Fired when a new memory is stored
memory.updated Fired when a memory is updated
memory.deleted Fired when a memory is deleted
memory.verified Fired when a memory is verified
memory.unverified Fired when a memory is unverified
task.updated Fired when a scheduled task status changes
chat.message_sent Fired when a chat message is sent

Create Webhook

POST /webhooks

Create a new webhook for the authenticated mind.

Request Body

Field Type Required Description
url string yes The URL to call when the event fires. Must be HTTPS (or http://localhost for development).
events string yes Comma-separated event patterns. Use * for all events. Examples: memory.*, chat.*
secret string yes Secret for HMAC-SHA256 signature verification.

Response

Field Type Description
id string (UUID) Webhook ID
url string Webhook URL
events string Event pattern (e.g. memory.*)
mind_id string (UUID) Mind that owns this webhook
enabled boolean Whether the webhook is enabled
created_at number Unix timestamp (seconds)

List Webhooks

GET /webhooks

Lists all webhooks for the authenticated mind.

Response

Array of webhook objects with the following fields:

Field Type Description
id string (UUID) Webhook ID
url string Webhook URL
events string Event pattern (e.g. memory.*)
mind_id string (UUID) Mind that owns this webhook
enabled boolean Whether the webhook is enabled
created_at number Unix timestamp (seconds)
last_call number or null Unix timestamp of last call
last_status number or null HTTP status code of last call
last_error string or null Error message from last call

Get Webhook

GET /webhooks/:id

Gets a single webhook by ID. Requires ownership.

Response

Same fields as List.

Update Webhook

PUT /webhooks/:id

Update a webhook's URL, events, or secret. Requires ownership.

Request Body

Field Type Required Description
url string no New webhook URL
events string no New event patterns
secret string no New secret

Enable / Disable Webhook

POST /webhooks/:id/enable

Enable a webhook. Requires ownership.

POST /webhooks/:id/disable

Disable a webhook. Requires ownership.

Test Webhook

POST /webhooks/:id/test

Sends a test event (memory.created) to the webhook URL. Requires ownership.

Delete Webhook

DELETE /webhooks/:id

Delete a webhook by ID. Requires ownership.

Example

curl -X POST https://synapse.schaefer.zone/webhooks \
  -H "Authorization: Bearer YOUR_MIND_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/webhook",
  "events": "memory.*",
  "secret": "your-webhook-secret"
}'

Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://example.com/webhook",
  "events": "memory.*",
  "mind_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "enabled": true,
  "created_at": 1782756632
}

Signature Verification

The webhook payload includes an HMAC-SHA256 signature in the X-Synapse-Signature header. The signature is computed over the raw request body bytes (not parsed-then-restringified JSON).

import hashlib, hmac

# IMPORTANT: Use the RAW request body bytes, not parsed JSON
payload_body = request.get_data()  # Flask; or request.body in Django/FastAPI

sig = hmac.new(
    webhook_secret.encode(),
    payload_body,
    hashlib.sha256
).hexdigest()

expected_header = f"sha256={sig}"
actual_header = request.headers.get('X-Synapse-Signature', '')
assert hmac.compare_digest(expected_header, actual_header)

Limits & Auto-Disable

  • Rate Limit: 20 webhooks per mind.
  • Auto-Disable: A webhook returning HTTP 410 (Gone) is automatically disabled. This allows remote services to signal "stop sending" without deleting the webhook configuration.

Deprecated Event Names

Old Name New Name
memory.store memory.created
memory.update memory.updated
memory.delete memory.deleted