Webhook tarifleri
Alarmlar size piyasanın ne yaptığını söyler. Webhook'lar ve Telegram, kendi araçlarınız ve kendi hesaplarınızla buna göre hareket etmenin yoludur. Asla sizin adınıza işlem yapmayız, asla fon tutmayız ve asla işlem yetkili API anahtarı istemeyiz.
Başlamadan önce
- Alarmlar sayfasında bir Özel JSON webhook ekleyin. VIP Quant ve deneme bunu içerir.
- İmzalama anahtarını kopyalayın. Bir kez gösterilir.
- Test gönder'e basın ve uç noktanızın onu aldığını kontrol edin.
- Bir kuralı hedefe yönlendirin. Varsayılan alarm da açık olduğu sürece ona gider.
8 saniye içinde herhangi bir 2xx ile yanıt verin. Başarısız gönderimler aynı id ile yeniden denenir, bu yüzden onun üzerinden tekilleştirin. Aşağıdaki her kod parçası gerçek bir imzalı gönderime karşı çalıştırıldı. Bu olaylardan otomatikleştirdiğiniz her şeyden siz sorumlusunuz.
Olaylar
opportunity.alert: bir rota bir kuralla veya Varsayılan alarmla eşleşti. Varsayılan alarm içinrule.iddeğeridefault'dir.listing.alert: bir piyasa yeni listelendi; listeleme başına bir olay.opportunity.closed: alarm aldığınız bir rota kapandı, kural bunu istiyorsa.position.alert: takip edilen bir işlemde bir şey oldu.notice.alert: bir borsa Varsayılan alarm kapsamında bir delisting, yatırma veya çekme duraklatması, bakım ya da listeleme duyurdu.tracked, takip ettiğiniz bir işlemde olduğunu söyler.watch.alert: izlediğiniz bir cüzdan Varsayılan alarm kapsamında bir transfer aldı veya gönderdi. İşlem hash'i bilinmediğindeevent.txnull olur.alert.test: Test gönder'den,"test": trueve TEST adlı sahte bir coin ile.
{
"id": "evt_7c1e...",
"type": "listing.alert",
"test": false,
"sentAt": "2026-11-02T10:00:00.000Z",
"rule": { "id": "...", "name": "New listings" },
"listing": { "coin": "ABC", "venue": "Binance", "kind": "spot", "symbol": "ABCUSDT", "listedMs": 1793000000000 },
"window": { "sizeUsd": 1000, "openMs": 4000, "avgWindowMs": null, "avgPeakNetBps": null, "windowSamples": 0 },
"opportunity": { "id": "ABC|Binance:spot|OKX:spot", "coin": "ABC", "...": "..." }
}Tüm alanlar webhook dokümanlarında.
İmzayı kontrol edin
Her istek X-ArbitrageX-Timestamp ve X-ArbitrageX-Signature taşır; ikincisi sha256= artı timestamp.rawBody değerinin hex HMAC-SHA256'sıdır. Ayrıştırmadan önce ham baytlar üzerinde kontrol edin, çünkü ayrıştırılıp yeniden kodlanmış JSON eşleşmez. Tekrar oynatmaları önlemek için şu andan 5 dakikadan fazla uzak zaman damgalarını reddedin.
Node.js
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(rawBody, headers, secret) {
const ts = headers["x-arbitragex-timestamp"];
if (!(Math.abs(Date.now() / 1000 - Number(ts)) <= 300)) return false;
const expected =
"sha256=" + createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const given = Buffer.from(String(headers["x-arbitragex-signature"]));
const wanted = Buffer.from(expected);
return given.length === wanted.length && timingSafeEqual(given, wanted);
}Python
import hashlib
import hmac
import time
def verify(raw_body: bytes, headers: dict, secret: str) -> bool:
ts = headers.get("x-arbitragex-timestamp", "")
try:
if abs(time.time() - int(ts)) > 300:
return False
except ValueError:
return False
signed = ts.encode() + b"." + raw_body
expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected.encode(), headers.get("x-arbitragex-signature", "").encode())Go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"math"
"net/http"
"strconv"
"time"
)
func Verify(rawBody []byte, headers http.Header, secret string) bool {
ts := headers.Get("X-ArbitrageX-Timestamp")
unix, err := strconv.ParseInt(ts, 10, 64)
if err != nil || math.Abs(float64(time.Now().Unix()-unix)) > 300 {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(ts + "."))
mac.Write(rawBody)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(headers.Get("X-ArbitrageX-Signature")))
}Yürütme araçları
Aşağıdaki her örnek, bir aracın beklediği gövdedir ve standart yükümüze göre yazılmıştır: köşeli parantez içindeki her değer, oraya konacak bizim alanımızdır. Bunu bir catch webhook'tan sonra bir Zapier veya Make adımında ya da Kendi betiğinizi çalıştırın altındaki alıcı gibi kendi aktarıcınızda oluşturun ve aracın webhook URL'sine gönderin. Büyük harfli değerler size aittir. Bir araca yalnızca opportunity.alert ve listing.alert ulaşmalıdır: test ve diğer tüm türleri filtreleyin, böylece kapanmış bir takip mesajı işlem açamaz. Asla işlem yapmayız: bir aracın bir mesajla ne yapacağı size ve araca kalmıştır.
Her araç zamanla kendi alanlarını değiştirir. Bir örneğe güvenmeden önce aracın güncel dokümanlarıyla karşılaştırın.
3Commas signal bot
Bir 3Commas sinyal botunun özel webhook'u için; secret ve bot UUID değerleri botun mesaj ayarlarından alınır. Bir sinyal botu tek bir borsada işlem yapar, bu yüzden kuralın borsa filtresiyle kuralı orada alım yapan rotalarla sınırlayın.
{
"secret": "YOUR_3COMMAS_SECRET",
"bot_uuid": "YOUR_BOT_UUID",
"max_lag": "300",
"timestamp": "<sentAt>",
"trigger_price": "<opportunity.buy.price>",
"tv_exchange": "<opportunity.buy.venue in capitals, e.g. BINANCE>",
"tv_instrument": "<opportunity.coin>USDT",
"action": "enter_long"
}Hummingbot
Hummingbot komutları bir webhook yerine kendi arayüzleri üzerinden alır; bu yüzden bu, sizin küçük bir script stratejinize ya da MQTT arayüzüne giden bir köprüye gider. Connector'ınızın kendi adını kullanın.
{
"connector": "<opportunity.buy.venue in lower case, e.g. binance>",
"trading_pair": "<opportunity.coin>-USDT",
"side": "BUY",
"price": <opportunity.buy.price>,
"amount_usd": <window.sizeUsd>,
"hedge_connector": "<opportunity.sell.venue in lower case>",
"hedge_price": <opportunity.sell.price>,
"net_bps": <opportunity.netBps>,
"event_id": "<id>"
}Cornix signal
Cornix'in bir TradingView botuna verdiği webhook adresi için, Cornix'in sinyal düzeninde düz metin. Kendi stop'unuzu belirleyin ve düzeni Cornix'in güncel kılavuzuyla karşılaştırın.
#<opportunity.coin>/USDT Exchanges: <opportunity.buy.venue> Signal Type: Regular (Long) Entry Targets: 1) <opportunity.buy.price> Take-Profit Targets: 1) <opportunity.sell.price> Stop Targets: 1) YOUR_STOP_PRICE
TradingView-style JSON
TradingView alarmlarını almak için yapılmış araçlar için, bir TradingView alarmının gönderdiği alan adları.
{
"ticker": "<opportunity.coin>USDT",
"exchange": "<opportunity.buy.venue in capitals>",
"action": "buy",
"price": <opportunity.buy.price>,
"time": "<sentAt>",
"message": "<opportunity.coin> <opportunity.buy.venue> to <opportunity.sell.venue>, net <opportunity.netBps> bps"
}Flat JSON
Bir tablo, n8n veya bir veritabanı için her rakam en üst düzeyde.
{
"id": "<id>",
"coin": "<opportunity.coin>",
"net_bps": <opportunity.netBps>,
"net_usd_1k": <opportunity.netUsd.1000>,
"max_size_usd": <opportunity.maxSizeUsd>,
"buy_exchange": "<opportunity.buy.venue>",
"buy_price": <opportunity.buy.price>,
"buy_url": "<opportunity.buy.url>",
"sell_exchange": "<opportunity.sell.venue>",
"sell_price": <opportunity.sell.price>,
"sell_url": "<opportunity.sell.url>"
}Diğer kanallar
Aşağıdaki her kanal Alarmlar sayfasında kurulur, bir Test gönder düğmesi vardır ve hesabın dilinde Telegram mesajı gibi okunur. Kurallar, bekleme süreleri, sessiz saatler, hız sınırı ve otomatik duraklatma hepsinde aynı çalışır.
- Slack (Pro Desk ve üzeri): Slack'te bir kanala Incoming Webhooks uygulamasını ekleyin ve verdiği
hooks.slack.comURL'sini yapıştırın. - ntfy (Starter ve üzeri): telefonda ve masaüstünde ücretsiz bildirimler.
https://ntfy.sh/your-topicgibi bir konu URL'sini ya da kendi sunucunuzdaki birini yapıştırın ve ntfy uygulamasında aynı konuya abone olun. Herkese açık bir konunun adını bilen herkes onu okuyabilir; bu yüzden uzun ve rastgele bir ad seçin ya da korumalı bir konu için erişim belirteci ekleyin. Her alarmda iki borsa için de düğmeler bulunur. - E-posta özeti (Starter ve üzeri): hesabınızın adresine, sonuncudan bu yana her alarmı içeren tek bir e-posta; her saat başı ya da her gün 08:00 UTC'de. Yeni bir şey yoksa hiçbir şey gönderilmez.
WhatsApp'ta bir hizmetin size ücretsiz mesaj göndermesinin yolu yok, bu yüzden sunulmuyor. Diğer her şey için özel bir webhook, https üzerinden düz JSON'dur.
Slack'e gönderin
Çalıştırılacak sunucu gerektirmeyen bir Cloudflare Worker. ARBITRAGEX_SECRET ve SLACK_WEBHOOK_URL değerlerini gizli değişken olarak ayarlayın, ardından Worker'ın URL'sini hedefiniz olarak kullanın. Aynı kod Web Crypto olan her yerde çalışır.
async function verify(rawBody, headers, secret) {
const ts = headers.get("x-arbitragex-timestamp");
if (!(Math.abs(Date.now() / 1000 - Number(ts)) <= 300)) return false;
const encoder = new TextEncoder();
const key = await crypto.subtle.importKey(
"raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["verify"],
);
const given = (headers.get("x-arbitragex-signature") ?? "").replace("sha256=", "");
if (!/^[0-9a-f]{64}$/.test(given)) return false;
const bytes = Uint8Array.from(given.match(/../g), (pair) => parseInt(pair, 16));
return crypto.subtle.verify("HMAC", key, bytes, encoder.encode(`${ts}.${rawBody}`));
}
export default {
async fetch(request, env) {
const rawBody = await request.text();
if (!(await verify(rawBody, request.headers, env.ARBITRAGEX_SECRET))) {
return new Response("bad signature", { status: 401 });
}
const event = JSON.parse(rawBody);
if (event.type === "opportunity.alert" || event.type === "listing.alert") {
const { coin, buy, sell, netBps } = event.opportunity;
await fetch(env.SLACK_WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: `${coin}: ${buy.venue} to ${sell.venue}, net ${netBps.toFixed(1)} bps`,
}),
});
}
return new Response(null, { status: 204 });
},
};Bir tablo tutun
Yalnızca Python'un standart kütüphanesiyle, herhangi bir tablo programında açabileceğiniz bir CSV'ye alarm başına bir satır ekler. https arkasına koyun: yalnızca herkese açık https adreslerine gönderiyoruz.
import csv
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
import hashlib
import hmac
import time
def verify(raw_body: bytes, headers: dict, secret: str) -> bool:
ts = headers.get("x-arbitragex-timestamp", "")
try:
if abs(time.time() - int(ts)) > 300:
return False
except ValueError:
return False
signed = ts.encode() + b"." + raw_body
expected = "sha256=" + hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected.encode(), headers.get("x-arbitragex-signature", "").encode())
SECRET = "your signing secret"
seen = set()
class Receiver(BaseHTTPRequestHandler):
def do_POST(self):
raw_body = self.rfile.read(int(self.headers["Content-Length"]))
headers = {key.lower(): value for key, value in self.headers.items()}
if not verify(raw_body, headers, SECRET):
self.send_response(401)
self.end_headers()
return
self.send_response(204)
self.end_headers()
event = json.loads(raw_body)
if event["test"] or event["id"] in seen or "opportunity" not in event:
return
seen.add(event["id"])
row = event["opportunity"]
with open("alerts.csv", "a", newline="") as file:
csv.writer(file).writerow(
[event["sentAt"], event["type"], row["coin"], row["buy"]["venue"], row["sell"]["venue"], row["netBps"]]
)
if __name__ == "__main__":
HTTPServer(("127.0.0.1", 8000), Receiver).serve_forever()Kendi betiğinizi çalıştırın
Bağımlılığı olmayan, hemen yanıt veren ve her alarmı sizin bir fonksiyonunuza ileten bir alıcı. O fonksiyonun ne yaptığını yazmak da, sorumluluğunu üstlenmek de size aittir. Alarmlar piyasa verisinden tahminlerdir ve bir rota, başlattığınız herhangi bir şey ulaşmadan kapanabilir.
import { createServer } from "node:http";
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, headers, secret) {
const ts = headers["x-arbitragex-timestamp"];
if (!(Math.abs(Date.now() / 1000 - Number(ts)) <= 300)) return false;
const expected =
"sha256=" + createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const given = Buffer.from(String(headers["x-arbitragex-signature"]));
const wanted = Buffer.from(expected);
return given.length === wanted.length && timingSafeEqual(given, wanted);
}
const seen = new Set();
function onAlert(event) {
// Your code goes here. You decide what happens next, and we never see it.
console.log(event.type, event.opportunity.coin, event.opportunity.netBps);
}
export const server = createServer((req, res) => {
const parts = [];
req.on("data", (part) => parts.push(part));
req.on("end", () => {
const rawBody = Buffer.concat(parts).toString("utf8");
if (!verify(rawBody, req.headers, process.env.ARBITRAGEX_SECRET)) {
return res.writeHead(401).end();
}
const event = JSON.parse(rawBody);
// Answer first: anything slower than 8 seconds counts as a failed delivery.
res.writeHead(204).end();
if (event.test || seen.has(event.id)) return;
seen.add(event.id);
if (event.type === "opportunity.alert" || event.type === "listing.alert") onAlert(event);
});
});Zapier ve Make
Özel bir webhook düz bir JSON POST'tur, bu yüzden her ikisinden alınan bir catch webhook URL'si hedef olarak çalışır. type ve test üzerinde bir filtre adımı ekleyin, ardından opportunity.coin ve opportunity.netBps gibi alanları eşleyin. Bu adımlar imzamızı sizin için kontrol etmez, bu yüzden catch URL'sini bir parola gibi değerlendirin ve orada bir yabancının başlatmasına izin vermeyeceğiniz hiçbir şeyi başlatmayın.
Telegram
Yalnızca telefonunuzda alarm istiyorsanız bunların hepsini atlayın. Alarmlar sayfasında Telegram'ı Bağla'ya, ardından açılan sohbette Başlat'a basın. Alarm dokümanlarına bakın.