Register your webhook endpoint to receive real-time notifications when new Snek.fun assets are discovered.

+

Register Webhook

</>

Integration Guide

Quick Start

  1. Register your webhook URL using the form
  2. Save your secret — shown only once at registration
  3. Create an endpoint that accepts POST requests
  4. Verify signatures using your secret (see code below)
  5. Process the payload and return HTTP 200

Event Type

Your endpoint will receive POST requests with new_asset_discovered events whenever a new Snek.fun asset matching our criteria is found.

Request Headers

Header Description
Content-Type application/json
User-Agent TB3/1.0
X-Bot-Event asset_discovered
X-Bot-Timestamp Unix timestamp of the request
X-Hub-Signature-256 HMAC-SHA256 signature for verification

Payload Structure

JSON
{
  "event_type": "new_asset_discovered",
  "timestamp": "2025-01-15T10:30:45.123Z",
  "bot_version": "1.0",
  "asset": {
    "id": 1,
    "policy_id": "6dc3db01cae96a57baff...",
    "asset_name_hex": "5465737441737365744e616d65",
    "asset_name_ascii": "TestAssetName",
    "first_seen_block_height": 12172120,
    "first_seen_tx_hash": "abc123...",
    "metadata_name": "Test Token",
    "metadata_description": "A test token",
    "metadata_ticker": "TEST",
    "metadata_image": "ipfs://..."
  },
  "metadata": {
    "has_metadata": true,
    "metadata_fields_present": ["name", "ticker"]
  }
}
Field Reference
FieldTypeDescription
event_typestringAlways "new_asset_discovered"
timestampstringISO 8601 timestamp of discovery
asset.idnumberInternal database ID
asset.policy_idstring56-character hex policy ID
asset.asset_name_hexstringAsset name in hex encoding
asset.asset_name_asciistringHuman-readable asset name
asset.first_seen_block_heightnumberBlock where asset was minted
asset.first_seen_tx_hashstringTransaction hash of mint
asset.metadata_namestring?Token name from CIP-25/68 metadata
asset.metadata_tickerstring?Token ticker symbol
asset.metadata_descriptionstring?Token description
asset.metadata_imagestring?IPFS/HTTP URL to token image
metadata.has_metadatabooleanWhether token has on-chain metadata

Signature Verification

Every webhook is signed with your unique secret. Verify the X-Hub-Signature-256 header to ensure requests are authentic.

Important: Use the secret you received at registration. The signature is computed over the raw request body bytes, not parsed JSON.
Python (Flask)
import hmac
import hashlib
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = "your-secret-from-registration"

def verify_signature(payload: bytes, signature: str) -> bool:
    expected = 'sha256=' + hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route('/webhook', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Hub-Signature-256', '')

    # Verify signature using raw body bytes
    if not verify_signature(request.data, signature):
        return jsonify({'error': 'Invalid signature'}), 401

    # Parse and process the event
    data = request.get_json()
    asset = data['asset']

    print(f"New asset: {asset['metadata_ticker']} - {asset['policy_id']}")

    return jsonify({'success': True}), 200
Node.js (Express)
const express = require('express');
const crypto = require('crypto');

const app = express();
const WEBHOOK_SECRET = 'your-secret-from-registration';

// Important: use raw body for signature verification
app.use('/webhook', express.raw({ type: 'application/json' }));

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

app.post('/webhook', (req, res) => {
    const signature = req.headers['x-hub-signature-256'] || '';

    if (!verifySignature(req.body, signature)) {
        return res.status(401).json({ error: 'Invalid signature' });
    }

    const data = JSON.parse(req.body);
    const asset = data.asset;

    console.log(`New asset: ${asset.metadata_ticker} - ${asset.policy_id}`);

    res.json({ success: true });
});
Go
package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "io"
    "net/http"
)

var webhookSecret = "your-secret-from-registration"

func verifySignature(payload []byte, signature string) bool {
    mac := hmac.New(sha256.New, []byte(webhookSecret))
    mac.Write(payload)
    expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signature))
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    signature := r.Header.Get("X-Hub-Signature-256")

    if !verifySignature(body, signature) {
        http.Error(w, "Invalid signature", 401)
        return
    }

    var data map[string]interface{}
    json.Unmarshal(body, &data)

    // Process the asset...
    w.WriteHeader(200)
    w.Write([]byte(`{"success": true}`))
}

Test Your Signature

Verify your HMAC implementation is correct by testing against our server.