Skip to main content
The webhook system is not yet implemented. This page documents what is available today (audit logs + polling) and the planned webhook schema for integrators building against the future API.

Current: Audit Logs as Event Stream

The audit log endpoint in Erebor serves as an interim event stream for vault operations:

Query Audit Logs

GET /api/v1/audit/logs
Authorization: Bearer <jwt>

# Query params:
# ?vault_address={addr}&chain_id={id}
# &limit=100&offset=0
# &action_type={type}
# &from_timestamp={iso}&to_timestamp={iso}
{
  "logs": [
    {
      "id": "uuid",
      "timestamp": "2025-03-01T10:00:00Z",
      "action_type": "yield_source_add",
      "vault_address": "0x...",
      "chain_id": 8453,
      "actor_wallet": "0xManager...",
      "details": {
        "yield_source": "0xMorphoVault...",
        "oracle": "0xOracle..."
      }
    }
  ],
  "total": 48,
  "has_more": false
}

Export Audit Logs

GET /api/v1/audit/export
Authorization: Bearer <jwt>
# Returns CSV or JSON depending on Accept header

Polling Pattern

import requests
import time
from datetime import datetime, timezone

EREBOR_URL = "https://erebor.superform.xyz"
headers = {"Authorization": "Bearer <jwt>"}
CHAIN_ID = 8453
VAULT = "0xYourVault..."

def poll_audit_logs(since: datetime):
    resp = requests.get(
        f"{EREBOR_URL}/api/v1/audit/logs",
        headers=headers,
        params={
            "vault_address": VAULT,
            "chain_id": CHAIN_ID,
            "from_timestamp": since.isoformat(),
            "limit": 100
        }
    )
    resp.raise_for_status()
    return resp.json().get("logs", [])

last_check = datetime.now(timezone.utc)

while True:
    new_events = poll_audit_logs(since=last_check)
    for event in new_events:
        print(f"New event: {event['action_type']} by {event['actor_wallet']}")
        # Process event...

    if new_events:
        last_check = datetime.now(timezone.utc)

    time.sleep(60)  # Poll every 60s

Planned: Webhook System

When the webhook system ships, it will provide push-based event delivery.

Planned Events

Event TypeDescription
pps.stalePPS staleness threshold crossed
pps.updatedNew PPS recorded on-chain
vault.pausedVault paused on-chain
vault.unpausedVault unpaused
service.degradedService success rate below threshold
service.downService stopped responding
merkle.syncedNew merkle root confirmed on-chain
yield_source.addedYield source whitelisted
yield_source.removedYield source removed
redemption.fulfilledRedemption request(s) fulfilled
deposit.fulfilledDeposit executed

Planned Delivery Format

{
  "event_id": "evt_uuid",
  "event_type": "pps.stale",
  "timestamp": "2025-03-01T10:00:00Z",
  "vault_address": "0x...",
  "chain_id": 8453,
  "data": {
    "remaining_seconds": 120,
    "last_update": "2025-03-01T07:00:00Z"
  }
}

Planned Integrations

Slack, PagerDuty, Discord, and custom HTTPS endpoints. Failed deliveries retried with exponential backoff (1s → 2s → 4s → 8s → 16s, max 5 attempts).

Current Workaround Summary

NeedSolution
Vault state changesPoll GET /api/v1/vaults/{chain_id}/{address} every 15s
Service degradationPoll GET /services/status every 30s
Operation eventsPoll GET /api/v1/audit/logs every 60s
PPS stalenessCalculate from remaining_staleness_time in vault state
Redemption activityPoll GET /fulfill-redeems/executions every 60s
See Monitoring Vault State for production-ready polling examples.