Skip to content

Webhooks

intermediate

Register, manage, and monitor outbound webhooks for real-time event notifications.

List webhooks

GET/v1/webhooks

List all registered webhook endpoints.

200Response
{
  "data": [
    {
      "id": "wh_abc123",
      "url": "https://api.acme.com/webhooks/engramma",
      "events": [
        "regime.changed",
        "consolidation.completed",
        "pattern.limit.warning"
      ],
      "active": true,
      "secret": "whsec_...masked...",
      "created_at": "2026-01-15T10:00:00Z",
      "last_delivery": {
        "status": 200,
        "at": "2026-01-20T03:00:00Z"
      }
    }
  ]
}
import os
from engramma_cloud import EngrammaClient

client = EngrammaClient(api_key=os.environ["ENGRAMMA_API_KEY"])

webhooks = client.webhooks.list()
for wh in webhooks:
    status = "active" if wh.active else "inactive"
    print(f"{wh.url} ({status})")
    print(f"  Events: {', '.join(wh.events)}")

Create webhook

POST/v1/webhooks

Register a new webhook endpoint. A signing secret is generated for verifying payloads.

urlstringrequired

The HTTPS endpoint URL that will receive webhook events. Must be publicly accessible.

eventsarrayrequired

Array of event types to subscribe to.

descriptionstring

Optional description for this webhook.

201Response
{
  "id": "wh_abc123",
  "url": "https://api.acme.com/webhooks/engramma",
  "events": [
    "regime.changed",
    "consolidation.completed"
  ],
  "active": true,
  "secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "created_at": "2026-01-15T10:00:00Z"
}
webhook = client.webhooks.create(
    url="https://api.acme.com/webhooks/engramma",
    events=["regime.changed", "consolidation.completed", "pattern.limit.warning"],
    description="Production monitoring"
)
print(f"Webhook ID: {webhook.id}")
print(f"Secret: {webhook.secret}")  # Store this securely!
Danger

The webhook secret is only shown once at creation time. Store it securely — you'll need it to verify webhook signatures.


Delete webhook

DELETE/v1/webhooks/{webhook_id}

Delete a webhook endpoint. No more events will be delivered to this URL.

webhook_idstringrequired

Webhook ID (path parameter).

200Response
{
  "deleted": true,
  "id": "wh_abc123"
}

List deliveries

GET/v1/webhooks/{webhook_id}/deliveries

View delivery history for a webhook endpoint. Useful for debugging failed deliveries.

webhook_idstringrequired

Webhook ID (path parameter).

statusstring

Filter by delivery status: success, failed, or pending.

pageintegerDefault: 1

Page number.

200Response
{
"data": [
  {
    "id": "dlv_abc123",
    "event": "consolidation.completed",
    "status": "success",
    "response_code": 200,
    "response_time_ms": 145,
    "attempt": 1,
    "delivered_at": "2026-01-20T03:00:00Z",
    "payload_preview": "{"event":"consolidation.completed","data":{"merged":12...}}"
  },
  {
    "id": "dlv_def456",
    "event": "regime.changed",
    "status": "failed",
    "response_code": 500,
    "response_time_ms": 3200,
    "attempt": 3,
    "next_retry_at": "2026-01-20T03:30:00Z",
    "error": "Server returned 500 Internal Server Error"
  }
],
"pagination": {"page": 1, "per_page": 20, "total": 42, "total_pages": 3}
}

Available events

GET/v1/webhooks/events

List all available webhook event types with descriptions.

200Response
{
  "events": [
    {
      "type": "regime.changed",
      "description": "Memory space regime changed (Normal, Exploration, Anomaly)",
      "payload_example": {
        "event": "regime.changed",
        "data": {
          "previous_regime": "normal",
          "new_regime": "exploration",
          "reason": "Rapid pattern ingestion detected",
          "timestamp": "2026-01-20T14:30:00Z"
        }
      }
    },
    {
      "type": "consolidation.completed",
      "description": "A consolidation cycle has finished",
      "payload_example": {
        "event": "consolidation.completed",
        "data": {
          "merged": 12,
          "pruned": 5,
          "strengthened": 34,
          "duration_ms": 2340,
          "timestamp": "2026-01-20T03:00:00Z"
        }
      }
    },
    {
      "type": "pattern.limit.warning",
      "description": "Usage exceeds 80% of plan pattern limit",
      "payload_example": {
        "event": "pattern.limit.warning",
        "data": {
          "current": 80000,
          "limit": 100000,
          "percentage": 80,
          "timestamp": "2026-01-19T10:00:00Z"
        }
      }
    },
    {
      "type": "anomaly.detected",
      "description": "An anomalous pattern was detected during storage or retrieval",
      "payload_example": {
        "event": "anomaly.detected",
        "data": {
          "memory_id": "mem_xyz789",
          "anomaly_type": "contradiction",
          "confidence": 0.89,
          "details": "New memory contradicts existing fact with 89% confidence",
          "timestamp": "2026-01-20T11:15:00Z"
        }
      }
    },
    {
      "type": "export.ready",
      "description": "A GDPR data export is ready for download",
      "payload_example": {
        "event": "export.ready",
        "data": {
          "export_id": "exp_abc123",
          "download_url": "https://exports.engramma-memory.com/exp_abc123.json.gz",
          "expires_at": "2026-01-16T10:00:00Z",
          "timestamp": "2026-01-15T10:12:00Z"
        }
      }
    }
  ]
}

Webhook signature verification

Every webhook delivery includes an X-Engramma-Signature header containing an HMAC-SHA256 signature of the payload body using your webhook secret:

X-Engramma-Signature: sha256=a1b2c3d4e5f6...
import hmac
import hashlib

def verify_webhook(payload_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload_body,
        hashlib.sha256
    ).hexdigest()
    received = signature_header.replace("sha256=", "")
    return hmac.compare_digest(expected, received)

Retry policy

AttemptDelayTimeout
1stImmediate10s
2nd1 minute10s
3rd5 minutes10s
4th30 minutes10s
5th (final)2 hours10s

After 5 failed attempts, the delivery is marked as permanently failed. The webhook remains active for future events.

Next steps