Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.leokit.dev/llms.txt

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

Overview

LeoKit webhooks push real-time event notifications to your server as swaps progress through their lifecycle. Discord and Slack webhook URLs are auto-detected and receive formatted embeds/blocks instead of raw JSON.

Supported Events

EventDescriptionWhen it fires
quote.createdA quote was requestedAfter /leokit/quote responds and the quote is saved
deposit.initiatedA deposit was builtAfter /leokit/deposit returns transaction data
swap.pendingTransaction submittedAfter /leokit/save-transaction records the tx hash
swap.successSwap completedStatus polling detects completion
swap.failedSwap failedStatus polling detects failure
swap.refundedSwap refundedStatus polling detects refund

Webhook Types

TypeAuto-detectedPayload formatSigning
standardDefaultRaw JSONHMAC-SHA256
discorddiscord.com / discordapp.com URLsDiscord embedNone
slackhooks.slack.com URLsSlack Block KitNone

POST /leokit/webhooks

Register a new webhook endpoint.

Authentication

Requires Api-Key header.

Request Body

{
  "url": "https://your-server.com/webhooks/leokit",
  "events": ["swap.success", "swap.failed", "swap.refunded"],
  "type": "standard"
}
FieldTypeRequiredDescription
urlstringYesHTTPS endpoint URL. Discord/Slack URLs are auto-detected.
eventsstring[]NoEvents to subscribe to. Defaults to all 6 events.
typestringNostandard, discord, or slack. Auto-detected from URL if omitted.

Response

Status Code: 200 OK
{
  "data": {
    "id": "01953c9a-...",
    "url": "https://your-server.com/webhooks/leokit",
    "events": ["swap.success", "swap.failed", "swap.refunded"],
    "type": "standard",
    "is_active": true,
    "created_at": "2026-02-07T12:00:00.000Z",
    "secret": "a1b2c3d4e5f6..."
  }
}
Important: The secret is only returned on creation. Save it immediately — you’ll need it to verify webhook signatures.

GET /leokit/webhooks

List all webhooks for the authenticated client.

Authentication

Requires Api-Key header.

Response

{
  "data": {
    "webhooks": [
      {
        "id": "01953c9a-...",
        "url": "https://your-server.com/webhooks/leokit",
        "events": ["swap.success", "swap.failed", "swap.refunded"],
        "type": "standard",
        "is_active": true,
        "created_at": "2026-02-07T12:00:00.000Z",
        "updated_at": "2026-02-07T12:00:00.000Z"
      }
    ]
  }
}

DELETE /leokit/webhooks?id=

Delete a webhook by ID.

Authentication

Requires Api-Key header.

Query Parameters

ParameterTypeRequiredDescription
idstringYesWebhook ID to delete

Response

{
  "data": {
    "deleted": true
  }
}

Webhook Payload (Standard)

Standard webhooks receive a JSON payload with HMAC-SHA256 signature headers.

Headers

HeaderDescription
X-LeoKit-EventEvent type (e.g., swap.success)
X-LeoKit-SignatureHMAC-SHA256 signature: sha256=<hex>
X-LeoKit-Delivery-IDUnique delivery ID
X-LeoKit-TimestampUnix timestamp (seconds)

Body

{
  "event": "swap.success",
  "timestamp": "2026-02-07T12:30:00.000Z",
  "data": {
    "quote_id": "01953c9a-...",
    "protocol": "chainflip",
    "status": "completed",
    "from_asset": "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "to_asset": "BTC.BTC",
    "from_address": "0x1234...",
    "to_address": "bc1q...",
    "tx_hash": "0xabc...",
    "scanner_url": "https://etherscan.io/tx/0xabc..."
  }
}

Verifying Signatures

Compute HMAC-SHA256 of the raw request body using your webhook secret, then compare to the X-LeoKit-Signature header:
import crypto from "crypto";

function verifyWebhook(body, secret, signature) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Delivery & Retry

  • Timeout: 10 seconds per delivery attempt
  • Max attempts: 5
  • Backoff schedule: 30s, 1m, 5m, 15m, 1h
  • Final state: Marked as failed after 5 failed attempts
Deliveries are processed by a background worker on the leader instance.

Rate Limits

  • Webhooks per client: 20 active webhooks max
  • Events per webhook: No per-event rate limit; high-volume clients may see deliveries batched within the same backoff window
  • TLS required: url must be https:// (Discord/Slack URLs are also enforced as HTTPS)

Discord Webhooks

Discord webhook URLs (discord.com/api/webhooks/...) automatically receive formatted embed payloads with color-coded event types:
  • Green: swap.success
  • Red: swap.failed
  • Yellow: swap.refunded
  • Blue: quote.created, deposit.initiated, swap.pending
No signature verification — Discord handles authentication via the webhook URL secret.

Slack Webhooks

Slack incoming webhook URLs (hooks.slack.com/services/...) automatically receive Block Kit formatted payloads with header blocks, mrkdwn fields, and contextual metadata.

Examples

Register a Discord webhook

curl -X POST https://api.leokit.dev/leokit/webhooks \
  -H "Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://discord.com/api/webhooks/123/abc"}'
Response will show "type": "discord" (auto-detected).

Register for specific events only

curl -X POST https://api.leokit.dev/leokit/webhooks \
  -H "Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/hook",
    "events": ["swap.success", "swap.failed"]
  }'

List webhooks

curl https://api.leokit.dev/leokit/webhooks \
  -H "Api-Key: YOUR_API_KEY"

Delete a webhook

curl -X DELETE "https://api.leokit.dev/leokit/webhooks?id=01953c9a-..." \
  -H "Api-Key: YOUR_API_KEY"