Register your webhook endpoint to receive real-time notifications when new Snek.fun assets are discovered.
Your endpoint will receive POST requests with new_asset_discovered events whenever a new Snek.fun asset matching our criteria is found.
| 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 |
{
"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 | Type | Description |
|---|---|---|
| event_type | string | Always "new_asset_discovered" |
| timestamp | string | ISO 8601 timestamp of discovery |
| asset.id | number | Internal database ID |
| asset.policy_id | string | 56-character hex policy ID |
| asset.asset_name_hex | string | Asset name in hex encoding |
| asset.asset_name_ascii | string | Human-readable asset name |
| asset.first_seen_block_height | number | Block where asset was minted |
| asset.first_seen_tx_hash | string | Transaction hash of mint |
| asset.metadata_name | string? | Token name from CIP-25/68 metadata |
| asset.metadata_ticker | string? | Token ticker symbol |
| asset.metadata_description | string? | Token description |
| asset.metadata_image | string? | IPFS/HTTP URL to token image |
| metadata.has_metadata | boolean | Whether token has on-chain metadata |
Every webhook is signed with your unique secret. Verify the X-Hub-Signature-256 header to ensure requests are authentic.
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
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 });
});
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}`))
}
Verify your HMAC implementation is correct by testing against our server.