Edictum
Edictum Control PlaneNotifications

Webhook Setup

Send approval notifications to any HTTPS endpoint with the shipped generic webhook channel.

AI Assistance

Right page if: you need the shipped generic webhook channel in edictum-api. Wrong page if: you want interactive approve/deny buttons -- webhooks are one-way. Telegram is the only interactive channel today. Gotcha: the current backend only validates and stores a single `url` field. It does not sign webhook payloads and does not add an event wrapper.

Send approval notifications to any HTTPS endpoint. One-way notifications -- no interactive approve/deny.

Add the Channel

App > Settings > Notifications > Add Channel > Webhook.

FieldRequiredDescription
URLYesHTTPS endpoint that receives POST requests

Payload Format

The webhook sender posts JSON. For approval requests, the payload matches the backend ApprovalMessage shape:

POST https://your-endpoint.com/webhook
Content-Type: application/json

{
  "approval_id": "550e8400-e29b-41d4-a716-446655440000",
  "agent_id": "prod-agent",
  "tool_name": "run_command",
  "tool_args": {"command": "rm -rf /tmp/cache"},
  "decision": "pending",
  "rule_name": "destructive-ops",
  "reason": "Destructive command requires approval",
  "timestamp": "2026-04-14T09:00:00Z",
  "timeout_seconds": 300,
  "message": "Destructive command requires approval"
}
FieldTypeDescription
approval_idstringUnique ID for this approval request
agent_idstringThe agent that triggered the tool call
tool_namestringName of the tool being called
tool_argsobject or nullArguments passed to the tool
decisionstringCurrent decision label from the notification payload
rule_namestringRule that triggered the approval
reasonstringHuman-readable reason for the notification
timestampstringNotification timestamp
timeout_secondsintHow long the agent waits before the timeout effect applies
messagestringHuman-readable description shown to operators

Example Receiver

A minimal FastAPI webhook receiver:

from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/webhook")
async def handle_webhook(request: Request):
    data = await request.json()
    if "approval_id" in data:
        print(f"Approval {data['approval_id']} for {data['agent_id']} -> {data['tool_name']}")
    else:
        print(f"Notification: {data}")

    return {"ok": True}

Use Cases

Webhooks are useful for integrating with systems that don't have a dedicated channel type:

  • Forward to PagerDuty or OpsGenie for on-call routing
  • Post to Microsoft Teams via incoming webhook
  • Trigger a CI/CD pipeline
  • Log to a SIEM
  • Send to a custom internal tool

Test

Click Test in the app or call:

POST /v1/notifications/channels/{id}/test

A test payload is sent to your URL. Check that your endpoint receives it and responds with a 2xx status.

Troubleshooting

ProblemFix
Test fails with connection errorVerify the URL is reachable from the control plane server
No requests receivedCheck firewall rules -- the control plane server must be able to reach your endpoint
Timeout on testYour endpoint must respond within 10 seconds

Next Steps

Last updated on

On this page