Integrations
Webhooks
TradeClaw can push signal and price events to any URL in real time. Each delivery is signed with HMAC-SHA256 so your receiver can verify the payload came from your instance — not a third party.
Setup via the UI
Navigate to Settings → Webhooks in the dashboard. Click Add Webhook, enter your endpoint URL, optionally provide a secret, and save. You can test delivery immediately from the same panel.
Enter URL
HTTPS endpoint that accepts POST requests
Set Secret
Optional. Used to sign and verify payloads
Test Delivery
Send a sample payload to confirm connectivity
curl -X POST https://your-instance.com/api/webhooks \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/tradeclaw",
"name": "My Signal Receiver",
"secret": "whsec_your_secret_here"
}'
# Response
{
"id": "wh_abc123",
"url": "https://your-app.com/webhooks/tradeclaw",
"name": "My Signal Receiver",
"enabled": true,
"createdAt": "2026-03-27T12:00:00Z"
}HMAC-SHA256 Signing
Every delivery includes an X-TradeClaw-Signature header. The value is the HMAC-SHA256 of the raw request body using your webhook secret as the key, encoded as a hex string prefixed with sha256=.
Header: X-TradeClaw-Signature
Value: sha256=<hex(HMAC-SHA256(secret, rawBody))>
Also includes: X-TradeClaw-Delivery (unique delivery ID)
Also includes: X-TradeClaw-Event (event type string)
const crypto = require('crypto');
function verifySignature(secret, rawBody, signatureHeader) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('hex');
// Use timingSafeEqual to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(expected, 'utf8'),
Buffer.from(signatureHeader, 'utf8')
);
}
// Express receiver
app.post('/webhooks/tradeclaw', express.raw({ type: '*/*' }), (req, res) => {
const sig = req.headers['x-tradeclaw-signature'];
if (!verifySignature(process.env.WEBHOOK_SECRET, req.body, sig)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
console.log('Event type:', event.type);
res.sendStatus(200);
});Payload Schema
All webhook payloads share a common envelope. The data field contains the event-specific object.
interface WebhookPayload {
id: string; // Unique delivery ID (same as X-TradeClaw-Delivery)
type: WebhookEventType;
createdAt: string; // ISO 8601
data: SignalEvent | PriceEvent | AlertEvent;
}
type WebhookEventType =
| 'signal.created'
| 'signal.updated'
| 'price.alert'
| 'tp.hit'
| 'sl.hit';
// signal.created example
{
"id": "del_xyz789",
"type": "signal.created",
"createdAt": "2026-03-27T14:30:00Z",
"data": {
"id": "sig_abc123",
"symbol": "XAUUSD",
"timeframe": "H1",
"direction": "BUY",
"confidence": 87,
"entryPrice": 2345.50,
"tp1": 2360.00, "tp2": 2374.50, "tp3": 2389.00,
"sl": 2331.00
}
}Discord & Slack Auto-Formatting
TradeClaw detects Discord and Slack webhook URLs automatically and sends rich formatted messages instead of raw JSON — no middleware required.
Discord
Sends an embed with colored sidebar (green for BUY, red for SELL), symbol, direction, confidence, entry, TP levels, and SL. URLs matching discord.com/api/webhooks are auto-detected.
Slack
Sends a Block Kit message with sections and context blocks. URLs matching hooks.slack.com are auto-detected and formatted accordingly.
Retry Logic
If your endpoint returns a non-2xx status code or times out, TradeClaw retries with exponential backoff. A delivery is considered failed after 3 attempts.
| Attempt | Delay | Timeout |
|---|---|---|
| 1st (initial) | Immediate | 5s |
| 2nd | 5 seconds | 5s |
| 3rd (final) | 25 seconds | 5s |
View delivery history and retry status at GET /api/webhooks/[id]/deliveries. Trigger a manual redeliver with POST /api/webhooks/deliver.
Rate Limiting
Webhook deliveries are rate-limited to one per 5 seconds per endpoint URL. High-frequency price events are batched before dispatch to avoid overwhelming receivers. Signal events are never batched — each signal triggers an individual delivery.
Max delivery rate: 1 per 5 seconds per URL
Signal events: Immediate, never batched
Price events: Batched into 5s windows
Max webhooks per instance: 20
Python Flask Receiver
import hashlib
import hmac
import os
from flask import Flask, request, abort
app = Flask(__name__)
WEBHOOK_SECRET = os.environ['WEBHOOK_SECRET']
def verify_signature(secret: str, body: bytes, signature: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
@app.route('/webhooks/tradeclaw', methods=['POST'])
def receive_webhook():
sig = request.headers.get('X-TradeClaw-Signature', '')
if not verify_signature(WEBHOOK_SECRET, request.data, sig):
abort(401)
event = request.get_json()
event_type = event.get('type')
if event_type == 'signal.created':
data = event['data']
print(f"New signal: {data['symbol']} {data['direction']} @ {data['confidence']}%")
elif event_type == 'price.alert':
print(f"Alert triggered: {event['data']}")
return '', 200
if __name__ == '__main__':
app.run(port=3001)