Skip to main content

Documentation Index

Fetch the complete documentation index at: https://yieldxyz.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

In Development — The webhook system is currently being finalized. This documentation describes the target architecture and may be subject to change.

Overview

Webhooks allow you to receive real-time notifications when events occur in your Yield.xyz integration. The system is designed for reliability with at-least-once delivery, automatic retries, and per-subject ordering.

At-least-once delivery

Guaranteed delivery with automatic retries

Per-subject ordering

Sequence numbers for event ordering

HMAC signing

Cryptographic verification of payloads

Comprehensive diagnostics

Delivery status and error tracking

Concepts

A customer destination URL + secret. This is where webhook payloads are delivered via HTTP POST.
Rules determining which events an endpoint receives:
  • events (resources): e.g., transaction, balance, position
  • actions: e.g., status_changed, amount_changed
  • Optional filters: yield_id, address, network, balance_type
An immutable record of “something happened” — the payload we deliver.
A mutable work item representing one attempt to send one event to one endpoint.

How It Works

1

Configure endpoint

Set up an endpoint URL and secret in your dashboard
2

Create subscriptions

Define which events to receive with optional filters
3

Events are emitted

When something happens (transaction confirmed, balance changed), an event is created
4

Deliveries are created

The system matches subscriptions and creates delivery work items
5

Dispatcher sends webhooks

A background worker claims deliveries and sends HTTP POST requests with HMAC signatures
6

Retries on failure

Failed deliveries are retried with exponential backoff

Event Envelope

All webhook payloads use a consistent envelope format:
interface WebhookEventV1 {
  id: string;
  schema_version: 1;

  resource: 'transaction' | 'position' | 'balance' | 'rewards' | 'yield';
  action: 'status_changed' | 'state_changed' | 'amount_changed' | 
          'amount_increased' | 'sweep_eligible' | 'metadata_changed';
  type: string; // `${resource}.${action}`

  created_at: string; // ISO 8601
  project_id: string;

  subject: {
    yield_id?: string;
    position_id?: string;
    transaction_id?: string;
    address?: string;
    balance_type?: string;
    network?: string;
  };

  sequence: number;       // Monotonic per subject for ordering
  idempotency_key: string;

  data: Record<string, unknown>;
  previous?: Record<string, unknown>;
  changes?: Record<string, { from: unknown; to: unknown }>;
  meta?: {
    environment?: string;
    source?: string;
    trace_id?: string;
    request_id?: string;
  };
}

Supported Events

ResourceActionDescription
transactionstatus_changedTransaction status updated (pending → confirmed → success/failed)
balanceamount_changedBalance amount changed
balanceamount_increasedBalance increased (deposits, rewards)
positionstate_changedPosition lifecycle state changed
rewardssweep_eligibleRewards ready to claim
yieldmetadata_changedYield metadata updated (APY, TVL)

Signing & Headers

Every webhook request is an HTTP POST with JSON body and these headers:
HeaderDescription
X-Yield-DeliveryUnique delivery ID
X-Yield-EventResource type
X-Yield-ActionAction type
X-Yield-TimestampUnix timestamp (seconds)
X-Yield-SignatureHMAC signature

Signature Format

sha256=<hex(hmac(secret, timestamp + "." + rawBody))>

Verification Example

import crypto from 'crypto';

function verifyWebhook(
  rawBody: string,
  timestamp: string,
  signature: string,
  secret: string
): boolean {
  const signaturePayload = `${timestamp}.${rawBody}`;
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(signaturePayload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
Optionally reject old timestamps (e.g., older than 5 minutes) for replay protection.

Delivery Semantics

At-Least-Once Delivery

Receivers may see the same event more than once. Dedupe using:
  • event.id (recommended)
  • X-Yield-Delivery header

Ordering

Events may arrive out of order. Use the sequence field (monotonic per subject) to:
  • Reorder events
  • Detect gaps

Retry Policy

AttemptWait Time
11 minute
25 minutes
315 minutes
41 hour
56 hours
6–1024 hours
  • Success: Any 2xx response
  • Failure: Network errors, timeouts, non-2xx responses
  • Max attempts: 10
  • After max: Delivery marked as dead

Delivery Lifecycle

StatusDescription
pendingCreated, ready for delivery
sendingClaimed by dispatcher, in-flight
deliveredSuccessfully delivered (2xx)
retry_scheduledFailed, will retry
deadPermanently failed after max attempts

Configuration

Configure Webhooks

Set up webhook endpoints and subscriptions in your dashboard

Best Practices

Respond quickly

Return 2xx within 15 seconds to avoid timeouts

Deduplicate

Use event.id to handle duplicate deliveries

Verify signatures

Always verify HMAC signatures before processing

Handle ordering

Use sequence numbers to reorder events per subject

Next Steps

Quickstart

Complete integration guide

Staking Extensions

Advanced staking options