Skip to main content

Webhooks

Register webhook endpoints to receive real-time HTTP POST notifications when events occur in your organization. Deliveries include an HMAC-SHA256 signature for verification. Failed deliveries retry up to 5 times with exponential backoff.

Human-only management

Webhook CRUD endpoints require a user JWT (principal_type: "user"). Agents cannot register or modify webhooks.

Quickstart

curl -X POST "https://api.1claw.xyz/v1/webhooks" \
-H "Authorization: Bearer $USER_JWT" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/1claw",
"events": ["agent.transaction.broadcast", "policy.created"],
"description": "Production event handler"
}'

The response includes a one-time secret — store it securely. All subsequent deliveries are signed with this secret in the X-Webhook-Signature header.

Endpoints

MethodPathDescription
POST/v1/webhooksRegister a webhook (returns signing secret once)
GET/v1/webhooksList webhooks for the org
GET/v1/webhooks/{id}Get webhook details
PATCH/v1/webhooks/{id}Update URL, events, active status, or description
DELETE/v1/webhooks/{id}Delete a webhook
Signing secret rotation

Org webhook HMAC secrets are returned once at create time. There is no org-level rotate endpoint today — delete and recreate the webhook, or store the secret in your own rotation workflow. Platform apps can rotate delivery secrets via POST /v1/platform/apps/{app_id}/rotate-webhook-secret.

Verifying signatures

Each delivery includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the raw request body, computed with your webhook secret. Verify the signature before processing the payload.

import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)

Supported events

Subscribe to one or more event types when creating or updating a webhook:

Treasury & wallets

EventDescription
wallet.transfer.sentOutgoing transfer from a treasury wallet
wallet.transfer.receivedIncoming transfer to a treasury wallet
deposit.receivedInbound deposit detected
deposit.confirmedDeposit confirmed on-chain
deposit.creditedDeposit credited to internal ledger
deposit_destination.createdNew deposit destination created
fiat.onramp.completedFiat on-ramp completed
fiat.offramp.completedFiat off-ramp completed
internal_transfer.completedInternal ledger transfer completed

Multisig proposals

EventDescription
proposal.createdNew Safe multisig proposal created
proposal.signedProposal received a signature
proposal.executedProposal executed on-chain
proposal.cancelledProposal cancelled

Agent transactions & signing

EventDescription
agent.transaction.broadcastAgent transaction broadcast to chain
agent.transaction.signedAgent transaction signed (sign-only mode)
signing_key.rotatedAgent signing key rotated

Policies

EventDescription
policy.createdAccess policy created
policy.updatedAccess policy updated
policy.deletedAccess policy deleted

Payment cards

EventDescription
card.orderedCard order submitted
card.readyCard ready for use
card.revealedCard PAN revealed (human or agent)
card.voidedCard voided
card.depletedCard balance depleted
card.orphaned_paymentOrder stuck in ordering (reconciliation needed)
card.rejectedCard order rejected

Approvals

EventDescription
approval.createdAgent approval request created
approval.decidedApproval approved or rejected
pending_approval.createdConsensus pending approval created
pending_approval.approvedPending approval approved
pending_approval.rejectedPending approval rejected
pending_approval.executedPending approval executed
pending_approval.expiredPending approval expired

Platform API

EventDescription
platform.user.connectedUser connected to platform app
platform.user.claimedUser claimed bootstrapped resources
platform.user.disconnectedUser disconnected from platform app
platform.bootstrap.completedBootstrap finished for connected user
platform.grant.createdUser granted platform app access to resources
platform.grant.revokedResource grant revoked

Policy backend (Cedar/OPA)

EventDescription
policy_backend.circuit_breaker_openedAdvanced policy backend circuit breaker opened
policy_backend.circuit_breaker_closedAdvanced policy backend circuit breaker closed

Signing secret rotation

Org webhook signing secrets are shown once when you create the webhook. To rotate:

  1. Register a new webhook (or delete and recreate the existing one).
  2. Update your verification logic with the new secret.
  3. Delete the old webhook when deliveries have switched over.

Platform app webhooks support in-place rotation:

curl -X POST "https://api.1claw.xyz/v1/platform/apps/APP_ID/rotate-webhook-secret" \
-H "Authorization: Bearer $USER_JWT"

The new secret is returned once. Update your verification logic before the next delivery.

Delivery behavior

  • Events are dispatched via HTTP POST to your registered URL
  • A background worker processes pending deliveries every 5 seconds
  • Failed deliveries retry up to 5 times with exponential backoff
  • Delivery history is stored in the webhook_deliveries table
  • Webhook destination URLs are validated via SSRF protection (blocks private IPs, cloud metadata endpoints, and .internal hostnames)
  • HTTP redirect following is disabled to prevent SSRF

SDK

// TypeScript SDK
const webhook = await client.webhooks.create({
url: "https://your-app.com/webhooks/1claw",
events: ["agent.transaction.broadcast"],
});

await client.webhooks.update(webhook.id, { is_active: false });
await client.webhooks.delete(webhook.id);

Platform apps

Platform developers often subscribe to platform lifecycle events. See Platform API — Webhook Events for platform-specific setup patterns and the platform.* event types.

Treasury-focused webhook examples (transfers, proposals) are also covered in the Treasury guide.

See also