API reference

The Sigmate API is an authenticated Server-Sent Events stream. Open one long-lived connection, receive every premium signal the moment it fires. Alpha tier only.

Base URL#

Production: https://api.sigmate.xyz

All endpoints in this reference are relative to that base URL.

Authentication#

Every API request is authenticated with a Bearer API key. Keys start with the prefix sig_ and are generated on the API keys dashboard.

  • Send the key in the Authorization header as Bearer sig_....
  • Keys are SHA-256 hashed server-side. Plaintext is shown once at creation and never again, store it in a secret manager.
  • One concurrent connection per key. Revoke drops any active connections within a tick.
  • If your Alpha subscription lapses, active connections terminate with a 403 on the next read and new connections are refused.

GET /api/signals/stream#

Opens a Server-Sent Events stream. The server keeps the connection open indefinitely, sending frames as signals fire.

Request

curl -N "https://api.sigmate.xyz/api/signals/stream" \
  -H "Authorization: Bearer sig_YOUR_KEY_HERE"

Events

  • hello. First frame after connect. Carries your user id in JSON as a sanity check.
  • signal. Full signal payload JSON. Fires once per premium signal.
  • : ping. Comment line every 25 seconds. Keeps load balancers and proxies from closing the connection on idle.

Example signal frame

{
  "id": "f3c7a1d2-8b4e-4d5f-9f2a-6e1c0d7a8b9f",
  "detected_at": "2026-04-24T09:32:14.117Z",
  "signal_type": "consensus_buy",
  "rank": "S",
  "rank_score": 94.2,
  "token": {
    "address": "7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr",
    "symbol": "WIF",
    "name": "dogwifhat",
    "image_url": "https://cdn.sigmate.xyz/token/WIF.png",
    "dex": "Raydium",
    "age_minutes": 12,
    "market_cap_usd": 412000,
    "liquidity_usd": 88300,
    "price_sol": 0.0000412,
    "price_usd": 0.0069
  },
  "wallet_count": 7,
  "pool_wallet_count": 5,
  "other_buyer_count": 2,
  "wallet_score_sum": 612.4,
  "triggering_wallets": [
    {
      "address": "HN7Wk...z9Aa",
      "score": 128.1,
      "rank": "S",
      "win_rate": 0.71,
      "realized_pnl_usd": 184220
    }
  ],
  "rug_check": {
    "mint_renounced": true,
    "freeze_renounced": true,
    "top10_holders_pct": 18.4,
    "lp_locked": true,
    "risk": "low"
  },
  "latency_ms": 412
}

Reconnect behaviour

Server-Sent Events clients (including the browser EventSource and Node's eventsource package) reconnect automatically on network errors. Sigmate does not resume missed frames on reconnect: assume the stream starts fresh. For critical systems that must not miss a signal, also enable webhook delivery as a redundant channel.

Example client (Node.js)#

import { EventSource } from "eventsource";

const es = new EventSource("https://api.sigmate.xyz/api/signals/stream", {
  fetch: (url, init) =>
    fetch(url, {
      ...init,
      headers: { ...init?.headers, Authorization: `Bearer ${process.env.SIGMATE_KEY}` },
    }),
});

es.addEventListener("hello", (e) => console.log("connected", e.data));

es.addEventListener("signal", (e) => {
  const signal = JSON.parse(e.data);
  // signal.rank, signal.token, signal.triggering_wallets, ...
  handleSignal(signal);
});

es.addEventListener("error", (e) => {
  // EventSource reconnects automatically on network errors.
  // 401 or 403 means the key is invalid or the subscription lapsed.
  console.error("stream error", e);
});

Install the package with npm install eventsource. The browser's native EventSource works too, though you will need a proxy to attach the Authorization header since the browser API does not support custom headers.

Errors#

  • 401. Missing, malformed, or unknown API key.
  • 403. Key is valid but the subscription is not Alpha or has expired.
  • 429. More than one concurrent connection per key. Close the other connection before reconnecting.
  • 5xx. Transient server issue. Retry with exponential backoff.

Stability guarantees

The event names (signal, hello) are stable. New fields may be added to the JSON payload at any time, so parse loosely and ignore unknown keys. We will avoid removing or renaming existing fields without warning.