API Documentation

Everything you need to integrate the Summevo crypto signal API: real-time WebSocket streams, REST endpoints, and HMAC-signed webhook deliveries.

Authentication

Issue an API key from /dashboard/settings. Pass it as a Bearer token on REST requests and as the token query param on WebSocket connections.

WebSocket — subscribe to signals

Open a connection and subscribe to the symbols and minimum confluence threshold you care about. Signals are pushed as soon as they’re published.

// Real-time WebSocket crypto signals
const ws = new WebSocket(
  "wss://api.summevo.com/ws/signals?token=YOUR_API_KEY"
);

ws.addEventListener("open", () => {
  ws.send(JSON.stringify({
    op: "subscribe",
    symbols: ["BTCUSDT", "ETHUSDT"],
    minConfluence: 7.0,
  }));
});

ws.addEventListener("message", (event) => {
  const signal = JSON.parse(event.data);
  // { id, symbol, signalType, confluenceScore, price, indicators, timestamp }
  console.log(signal.symbol, signal.signalType, signal.confluenceScore);
});

REST — fetch signals

All REST endpoints are under https://api.summevo.com/api/v1. Responses are JSON.

# Fetch the latest signals for a symbol
curl -X GET "https://api.summevo.com/api/v1/signals/latest?symbol=BTCUSDT&limit=10" \
  -H "Authorization: Bearer $SUMMEVO_API_KEY" \
  -H "Accept: application/json"

WebSocket — reconnection

Connections may drop on network changes, idle timeouts or deploys. Reconnect with jittered exponential backoff and resume with a since cursor so you don’t miss signals.

// Reconnect with exponential backoff and a resume cursor
function connectSignals({ apiKey, onSignal }) {
  let attempt = 0;
  let lastEventId = null;

  function open() {
    const url = new URL("wss://api.summevo.com/ws/signals");
    url.searchParams.set("token", apiKey);
    if (lastEventId) url.searchParams.set("since", lastEventId);

    const ws = new WebSocket(url);

    ws.addEventListener("open", () => {
      attempt = 0;
      ws.send(JSON.stringify({
        op: "subscribe",
        symbols: ["BTCUSDT", "ETHUSDT"],
        minConfluence: 7.0,
      }));
    });

    ws.addEventListener("message", (e) => {
      const signal = JSON.parse(e.data);
      lastEventId = signal.id;
      onSignal(signal);
    });

    ws.addEventListener("close", () => {
      // Jittered exponential backoff, capped at 30s
      const delay = Math.min(30_000, 500 * 2 ** attempt++) +
        Math.random() * 250;
      setTimeout(open, delay);
    });

    ws.addEventListener("error", () => ws.close());
  }

  open();
}

Python example

The REST API is plain JSON — any language with an HTTP client works. Here’s a typical Python fetch:

# Python: fetch the latest signals (requests)
import os, requests

API_KEY = os.environ["SUMMEVO_API_KEY"]
resp = requests.get(
    "https://api.summevo.com/api/v1/signals/latest",
    params={"symbol": "BTCUSDT", "limit": 10},
    headers={"Authorization": f"Bearer {API_KEY}"},
    timeout=5,
)
resp.raise_for_status()
for s in resp.json():
    print(s["symbol"], s["signalType"], s["confluenceScore"])

Webhook payload

Outbound webhooks deliver the same signal envelope as the WebSocket stream, with headers for event type, timestamp and signature.

POST /your/endpoint HTTP/1.1
Content-Type: application/json
X-Summevo-Event: signal.strong_buy
X-Summevo-Signature: sha256=9f2a...e1
X-Summevo-Timestamp: 1716470400

{
  "id": "sig-01HQX...",
  "symbol": "BTCUSDT",
  "signalType": "STRONG_BUY",
  "confluenceScore": 8.6,
  "price": 67432.10,
  "indicators": {
    "rsi": 32.1,
    "macd": 142.3,
    "bb_position": "BELOW_LOWER",
    "ema_trend": "BULLISH"
  },
  "timestamp": "2026-05-23T08:00:00Z",
  "chainHash": "b14c...f7"
}

Verify the HMAC signature

Use the signing secret from your webhook’s settings to verify each delivery. Always compare with a constant-time comparison.

// HMAC-SHA256 webhook signature verification (Node.js)
import crypto from "node:crypto";

export function verifySummevoSignature(req, secret) {
  const signature = req.headers["x-summevo-signature"];   // "sha256=<hex>"
  const timestamp = req.headers["x-summevo-timestamp"];
  const rawBody = req.rawBody;                            // capture before JSON parsing

  // Reject if older than 5 minutes (replay protection)
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected =
    "sha256=" +
    crypto
      .createHmac("sha256", secret)
      .update(`${timestamp}.${rawBody}`)
      .digest("hex");

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

Verify webhook signatures (Java / Spring Boot)

Equivalent verification for JVM services. Use the same WEBHOOK_SECRET issued for the endpoint.

// HMAC-SHA256 webhook verification (Java / Spring Boot)
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public final class SummevoSignature {

    public static boolean verify(
        String signatureHeader,   // "sha256=<hex>"
        String timestampHeader,
        byte[] rawBody,
        String secret
    ) throws Exception {
        long ts = Long.parseLong(timestampHeader);
        long now = System.currentTimeMillis() / 1000L;
        if (Math.abs(now - ts) > 300) return false;       // replay window

        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(
            secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        mac.update((ts + ".").getBytes(StandardCharsets.UTF_8));
        byte[] digest = mac.doFinal(rawBody);

        StringBuilder hex = new StringBuilder("sha256=");
        for (byte b : digest) hex.append(String.format("%02x", b));

        return MessageDigest.isEqual(
            hex.toString().getBytes(StandardCharsets.UTF_8),
            signatureHeader.getBytes(StandardCharsets.UTF_8));
    }
}

Errors

All endpoints return a consistent JSON error envelope. Treat 4xx codes as caller errors and 5xx codes as transient — retry 5xx with exponential backoff.

// Error response shape (all error codes use the same envelope)
{
  "error": "rate_limited",
  "message": "Too many requests — retry after 12s.",
  "requestId": "req_01HQX..."
}
StatusWhen you see it
401 UnauthorizedInvalid, missing or expired API key.
403 ForbiddenYour plan does not include this feature. Upgrade required.
404 Not FoundResource not found — check the symbol or signal ID.
422 Unprocessable EntityValidation failed for one or more request parameters.
429 Too Many RequestsPer-tier rate limit exceeded. Honor the Retry-After header.
500 Internal Server ErrorUnexpected server error. Safe to retry with backoff.

Rate limits

Per-tier limits on the REST API. WebSocket connections have a separate concurrent-connection cap published in your account settings.

TierRequests / minuteWebSocketHistory retention
Free60Last 5 signals
Pro300Real-time30 days
Quant1,000Real-time365 days