Skip to content
Hightop docs header art
Hightop
API and Integrations

Webhooks#

Agent API webhooks send signed HTTPS POSTs when supported agent events are persisted. Webhook delivery is at least once; receivers should dedupe by event id.

Management Routes#

Agents can manage up to 10 webhook endpoints.

textexample
GET /v1/agent/webhooks
POST /v1/agent/webhooks
GET /v1/agent/webhooks/{id}
PATCH /v1/agent/webhooks/{id}
DELETE /v1/agent/webhooks/{id}
GET /v1/agent/webhooks/{id}/deliveries
POST /v1/agent/webhooks/{id}/rotate-secret
POST /v1/agent/webhooks/{id}/test

Webhook management writes use the webhook_management rate-limit class and require Idempotency-Key.

Create and rotate responses return the signing secret once. Store it immediately.

Endpoint Requirements#

Webhook URLs must be public HTTPS endpoints. Hightop rejects:

  • plain HTTP
  • private networks
  • localhost and *.localhost
  • redirects
  • unsupported schemes such as file://, gopher://, or ftp://
  • URL credentials such as https://user:pass@example.com/hook

Hightop revalidates DNS before delivery and pins the request to the validated public address set.

Event Envelope#

jsonexample
{
  "id": "uuid",
  "type": "payment.executed",
  "created_at": "2026-05-16T00:00:00.000Z",
  "agent_id": "uuid",
  "wallet_id": "wallet-id",
  "operation_id": "uuid",
  "resource": {
    "type": "payment",
    "id": "uuid"
  },
  "data": {}
}

Emitted Event Types#

Shipped v1 producers emit:

textexample
payment.executed
payment.execution_failed
one_off_payment.created
conversion.executed
conversion.execution_failed
earn.deposit.executed
earn.withdraw.executed
earn.move.executed
rewards.claimed
debt.borrowed
debt.repaid
debt.deleveraged
collateral.added
collateral.removed
withdrawal.settled
withdrawal.execution_failed
agent.webhook_disabled
operation.policy_rejected
webhook.test

Subscribable but not normally triggered by public Agent API calls:

textexample
trusted_destination.confirmed
trusted_destination.cancelled
trusted_destination.removed

These trusted-destination event types can be emitted by internal or system finalization paths. Public Agent API v1 does not expose trusted-destination mutation routes.

Reserved or not emitted by shipped v1 producers:

textexample
payment.submitted
payment.received
one_off_payment.claimed
one_off_payment.expired
withdrawal.submitted
deposit.received
recurring_payment.updated
recipient.changed
agent.limit_approaching
agent.limit_reached
agent.disabled
agent.expired
agent.expiring_soon

Execution-failure webhook events are explicit only for payment, conversion, and withdrawal operation families in v1. Other operation families still finalize and create Activity, but they do not emit a public failure webhook until a stable v1.x event type exists.

Signing#

Deliveries include:

textexample
User-Agent: Hightop-Webhooks/1.0
Hightop-Webhook-Id: <event id>
Hightop-Webhook-Timestamp: <unix timestamp>
Hightop-Webhook-Signature: v1=<hex hmac>
Content-Type: application/json

During the 24-hour secret-rotation grace window, Hightop-Webhook-Signature contains both current and previous signatures as comma-separated v1=<hex hmac> values.

The HMAC covers:

textexample
${timestamp}.${raw_body}

Verify the raw body bytes, not parsed JSON. Use a 5-15 minute timestamp tolerance.

TypeScript Verification#

typescriptexample
import crypto from 'crypto'
 
export function verifyHightopWebhook(secret: string, timestamp: string, rawBody: string, signature: string) {
  const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')
  const expectedBuffer = Buffer.from(expected, 'hex')
 
  return signature.split(',').some((part) => {
    const [version, value] = part.trim().split('=')
    if (version !== 'v1' || !value) return false
 
    const actualBuffer = Buffer.from(value, 'hex')
    return actualBuffer.length === expectedBuffer.length && crypto.timingSafeEqual(actualBuffer, expectedBuffer)
  })
}

Delivery Rules#

  • Payloads are capped at 256 KB.
  • Each delivery attempt has a 10-second total deadline.
  • Receiver response bodies are captured up to 4 KB for diagnostics.
  • Retryable failures retry for up to 72 hours.
  • Exhausted endpoints are auto-disabled with disabled_reason = "sustained_failures".
  • Endpoints auto-disabled for sustained_failures must be re-enabled by the owner in the app; PATCH enabled=true returns owner_only_action.
  • Rotating the secret for an endpoint disabled by sustained_failures also returns owner_only_action.

Retryable failures:

  • network errors and timeouts
  • HTTP 408
  • HTTP 429
  • HTTP 5xx

Terminal outcomes:

  • HTTP 2xx is delivered
  • HTTP 3xx redirects fail terminally
  • most HTTP 4xx fail terminally, except 408 and 429
  • TLS certificate failures fail terminally
  • SSRF validation failures fail terminally
  • oversize payloads fail terminally

Previous

Errors

Next

Capabilities