Developer documentation

CQS Public Signals API

This guide explains how to pull live trading signals from Crypto Quality Signals into your own bot, spreadsheet, or custom integration. If you already use Cornix, 3Commas, or similar, you can skip most of this — those platforms connect with your subscription ID through their own settings.

Production base URL: https://api.cryptoqualitysignals.com

Quick start

The public API does one main thing: return open trading signals published by CQS within a time window you choose. You send your API key, read the JSON, and process the signals array.

  1. Choose your key: FREE for public signals, or your premium subscription ID from the CQS dashboard.
  2. Call GET or POST on https://api.cryptoqualitysignals.com/getSignal/ with that key.
  3. Parse the signals array. Each item includes entry zone, targets, stop loss, exchange, and direction.

Minimal request (free tier, last 5 minutes):

curl -s "https://api.cryptoqualitysignals.com/getSignal/?api_key=FREE&interval=5"

Authentication

Every request needs api_key. There is no separate Bearer token — pass the key as a query parameter (GET) or form field (POST).

Free access

Use the literal string FREE. You receive signals from the free and freemium channels. Volume and types are more limited than premium.

Premium access

After subscribing, your account gets a unique subscription ID — a long alphanumeric string. That value is your API key. Copy it exactly from the premium dashboard.

Premium keys unlock VIP signals. Wrong, expired, or inactive keys return error code 5.

Keep your key private. Anyone with your subscription ID can pull VIP signals. Contact support if you suspect a leak so we can rotate it.

The getSignal endpoint

URLhttps://api.cryptoqualitysignals.com/getSignal/
MethodsGET, POST
Responseapplication/json, UTF-8

GET and POST behave the same. GET is handy for quick tests; POST works if you prefer form bodies.

Alternate path (same handler): https://api.cryptoqualitysignals.com/api/v1/getSignal

Request parameters

Parameter Required Default Description
api_key Yes FREE or your premium subscription ID.
interval No 5 Look-back window in minutes (1–20). Only signals opened inside this window are returned.
exchange No Filter by exchange, e.g. binance, BINANCE_FUTURES, kucoin.
currency No Quote currency filter, e.g. USDT, BTC.
type No Signal horizon filter. Must match one of the valid types below. Empty = all types allowed for your tier.

POST uses the same field names: api_key, interval, exchange, currency, type.

Response format

Every response uses the same envelope:

{
  "error": 0,
  "message": "Success",
  "count": 2,
  "signals": [ ... ]
}
  • error — Numeric status (0 = OK). See error codes.
  • message — Human-readable status for logs.
  • count — Length of the signals array.
  • signals — List of signal objects; empty when nothing matched.

Example (one signal, fields may vary):

{
  "error": 0,
  "message": "Success",
  "count": 1,
  "signals": [
    {
      "id": "1847291",
      "timestamp": "2026-05-24 14:32:05",
      "exchange": "binance",
      "currency": "USDT",
      "coin": "BTC",
      "direction": "LONG",
      "buy_start": "94250.5",
      "buy_end": "94400",
      "target1": "95500",
      "target2": "96200",
      "target3": "97000",
      "stop_loss": "93100",
      "type": "SHORT TERM",
      "ask": "94325",
      "risk_level": "3"
    }
  ]
}

When nothing is available: error 0, message "No new signals available", count 0, signals [].

Signal fields explained

Prices are returned as strings to avoid floating-point surprises. Parse them as decimals in your language.

id

Unique signal ID. Track it locally so you do not process the same open signal twice on the next poll.

timestamp

Publish time on our servers (YYYY-MM-DD HH:MM:SS).

exchange, currency, coin

Where to trade. Pair = coin/currency (example: BTC/USDT).

direction

LONG = buy expecting a rise. SHORT = sell or short (common on futures).

buy_start, buy_end

Suggested entry zone. Many traders scale in between these prices instead of market-buying at ask.

ask

Reference price at publish time. Bots often map this to their signal price field.

target1, target2, target3

Take-profit levels. Not every signal uses three — unused targets may be empty. Partial exits at each level are common.

stop_loss

Invalidation price. For LONG, exit if price reaches or crosses below this level.

type

Horizon bucket (see signal types).

risk_level

Internal risk score, usually 1–5. Higher = more aggressive setup.

leverage (futures only)

Suggested leverage on futures exchanges. Omitted on spot pairs.

Signal types

Pass one of these exact strings in the type parameter (spaces and slashes included):

  • SHORT TERM
  • SHORT/MID TERM
  • SCALPING
  • MID TERM
  • LONG TERM

Unknown type → error 1 with a descriptive message.

Free vs premium access

FREE Premium subscription ID
Signal poolFREE + FREEMIUM servicesVIP service
VolumeSubset of public signalsFull VIP feed
Scalping tableYes (type=SCALPING)Main signals table

Scalping (free tier)

Free scalping signals use a separate table. Request them with api_key=FREE and type=SCALPING.

  • Only target1 is set (single take-profit).
  • buy_start / buy_end are ±0.1% around ask.
  • risk_level is always 3.
  • BitMEX scalps are excluded from the free feed.
curl -s "https://api.cryptoqualitysignals.com/getSignal/?api_key=FREE&type=SCALPING&interval=10"

Futures exchanges & leverage

Futures signals use the exchange codes listed below. Use the exact value from the exchange field when filtering with the exchange parameter.

Supported futures exchange codes

Most rows use lowercase (e.g. binance_futures). The filter must match the stored value exactly.

  • binance_futures Binance Futures
  • bitget_futures Bitget Futures
  • bitmex BitMEX
  • bybit Bybit
  • deribit Deribit
  • htx_futures HTX Futures
  • kucoin_futures Kucoin Futures
  • okx_futures OKX Futures

Leverage field

When you filter by any futures exchange code listed above, the response includes leverage — typically the midpoint of our min/max range. Without an exchange filter, leverage is omitted even for futures signals.

Confirm contract type and max leverage on your exchange before auto-trading.

Error codes

Code Typical message What to do
0 Success / No new signals Normal. Check count.
1 Missing key / Invalid type / Bad parameter Fix the request.
4 Unable to validate API Key Billing DB unreachable — retry later.
5 Invalid API Key / System unavailable Wrong key, inactive subscription, or signals DB down.
6 Rate limit exceeded Slow down polling (limit may return in the future).

How often to poll

There is no webhook for public delivery — you pull on a schedule.

  • Every 30–60 seconds for scalping; 2–5 minutes is usually enough for swing signals.
  • Set interval slightly wider than your poll period so you do not miss signals between requests.
  • Deduplicate by id. The API returns all matching open signals in the window, not only brand-new ones.
  • On error 4 or 5 with "unavailable", back off before retrying.

Trading bots & platforms

CQS premium works natively with 3Commas, Cornix, Zignaly, AnnyDeCrypto, Le-Trader, Nefertiti, 3C.exchange, and others. Those tools ask for your subscription ID in their UI — no JSON parsing required unless you want a custom setup.

Building your own bot? Map coin + currency to the exchange symbol, respect direction, enter between buy_start and buy_end, set stop at stop_loss, and scale out at target1–target3. Paper-trade first.

Code examples

GET — premium, Binance USDT, short term

curl -G "https://api.cryptoqualitysignals.com/getSignal/" \
  --data-urlencode "api_key=YOUR_SUBSCRIPTION_ID" \
  --data-urlencode "interval=15" \
  --data-urlencode "exchange=binance" \
  --data-urlencode "currency=USDT" \
  --data-urlencode "type=SHORT TERM"

POST — form body

curl -s -X POST "https://api.cryptoqualitysignals.com/getSignal/" \
  -d "api_key=FREE" \
  -d "interval=5" \
  -d "type=SCALPING"

Python

import requests

API_KEY = "YOUR_SUBSCRIPTION_ID"  # or "FREE"
url = "https://api.cryptoqualitysignals.com/getSignal/"
params = {"api_key": API_KEY, "interval": 10, "exchange": "binance", "currency": "USDT"}

resp = requests.get(url, params=params, timeout=30)
data = resp.json()
if data["error"] != 0:
    raise RuntimeError(f"API error {data['error']}: {data['message']}")

seen = set()
for sig in data["signals"]:
    if sig["id"] in seen:
        continue
    seen.add(sig["id"])
    print(sig["coin"], sig["direction"], sig["ask"])

JavaScript (Node 18+)

const params = new URLSearchParams({ api_key: "FREE", interval: "5" });
const res = await fetch(`https://api.cryptoqualitysignals.com/getSignal/?${params}`);
const data = await res.json();
if (data.error !== 0) throw new Error(`${data.error}: ${data.message}`);
for (const s of data.signals) console.log(s.id, s.coin);

PHP

$q = http_build_query(['api_key' => 'FREE', 'interval' => 5]);
$json = file_get_contents('https://api.cryptoqualitysignals.com/getSignal/?' . $q);
$data = json_decode($json, true);
if ($data['error'] !== 0) throw new Exception($data['message']);
foreach ($data['signals'] as $s) echo $s['id'], ' ', $s['coin'], PHP_EOL;

FAQ

Where do I find my subscription ID?
Log in to the CQS premium dashboard after purchase. Copy the subscription ID exactly into api_key.
Why do I see the same signal twice?
Open signals stay in the feed until we close them. Track id values you already handled.
Are closed or hit-target signals returned?
No. Only open signals within the time window are included.
Is HTTPS required?
Yes. Always use https://. Never send a premium key over plain HTTP.
Need help?
Premium members: use the support channel included in your plan. For outages, test a FREE request before opening a ticket.

Last updated: May 2026 · Applies to https://api.cryptoqualitysignals.com/getSignal/