Webhooks

Register a URL, get notified when things happen. HMAC-SHA256 signed. At-least-once delivery.

Register

curl -X POST https://api.stableyard.fi/v2/webhooks \
  -H "Authorization: Bearer sy_secret_*" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourserver.com/hooks",
    "events": ["payment.settled", "payment.failed", "deposit.detected"]
  }'
Returns a signing secret for this webhook. Use it to verify HMAC-SHA256 signatures.

Event Types

EventWhen
session.createdNew session created
payment.pendingPayment detected, confirming
payment.routingCross-chain routing in progress
payment.settledMoney arrived in recipient wallet
payment.failedExecution failed, auto-refund started
session.expiredSession timed out
deposit.detectedDeposit seen on-chain
refund.createdRefund initiated
refund.settledRefund completed
refund.failedRefund failed
dispute.flaggedDispute raised on a payment
dispute.resolvedDispute resolved

Payload Format

{
  "id": "evt_abc123",
  "object": "event",
  "type": "payment.settled",
  "created": 1710671400,
  "livemode": true,
  "data": {
    "sessionId": "ses_xyz",
    "status": "settled",
    "amount": 5000000,
    "currency": "USDC",
    "settledAt": 1710671400
  },
  "requestId": "req_abc"
}

Signature Verification

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Retry Policy

5 retries with exponential backoff:
AttemptDelay
1Immediate
21 second
35 seconds
430 seconds
52 minutes
After all retries exhausted, event status changes to exhausted.

Management

ActionEndpoint
Update URLPOST /v2/webhooks/:id/url
Rotate secretPOST /v2/webhooks/:id/rotate-secret
DeleteDELETE /v2/webhooks/:id
View eventsGET /v2/webhooks/:id/events