XCREENER Docs
XQLHTTP API

Endpoints

/xql/validate, /xql/explain, /xql/run.

All three endpoints read the XQL query from the raw request body (plain text, not a JSON-wrapped field or query parameter) and all three require the Authorization header described in Authentication.

POST /xql/validate

Parses and plans the query without touching any data store. Use this to check a query is well-formed and within the lookback ceiling before running it. Works with any recognized API key, including free tier, and is never metered.

curl https://api.xcreener.com/xql/validate \
  -H "Authorization: Bearer <your-api-key>" \
  --data-raw 'market = "CRYPTO"
timeframe = h1
rsi(14) < 30'

Success (200):

{ "valid": true }

Failure (400):

{
  "valid": false,
  "error": {
    "type": "syntax",
    "message": "Unexpected end of input, expected ')'",
    "position": { "line": 3, "column": 12, "offset": 45 }
  }
}

error.type is "syntax" for a parse-time error (includes position) or "plan" for a plan-time error, such as exceeding the 300-bar lookback ceiling (no position).

POST /xql/explain

Parses and plans the query and, on success, returns both the data-requirements manifest and a human-readable description. Works with any recognized API key, including free tier, and is never metered.

curl https://api.xcreener.com/xql/explain \
  -H "Authorization: Bearer <your-api-key>" \
  --data-raw 'market = "CRYPTO"
timeframe = h1
columns = [close, rsi(14)]
sort = rsi(14) asc

rsi(14) < 30'

Success (200):

{
  "plan": {
    "market": "CRYPTO",
    "sources": [{ "timeframe": "h1", "series": ["close"], "minLookback": 15 }]
  },
  "explanation": "Matches when rsi(14) < 30. Returns close, rsi(14), sorted by rsi(14) ascending."
}

Failure (400): same shape as /xql/validate's failure response: no plan or explanation field is included.

explain() is mechanical, not paraphrased

The explanation string renders the query back in near-XQL prose (e.g. "Matches when rsi(14) < 30"): it does not translate to plain-English trading language. It's meant as a mechanical sanity check on what a query does, not a trader-facing summary.

POST /xql/run

Parses and plans the query; on success, fetches the OHLCV data the plan requires and executes the query against every instrument in the query's market/timeframe universe. Works with any recognized key, including free tier, metered against your subscription's daily quota: see Rate Limits.

curl https://api.xcreener.com/xql/run \
  -H "Authorization: Bearer <your-api-key>" \
  --data-raw 'market = "CRYPTO"
timeframe = h1
columns = [close, rsi(14)]
sort = rsi(14) asc
limit = 5

rsi(14) < 30'

/xql/run counts against your account's daily quota: every response carries X-RateLimit-Remaining and X-RateLimit-Reset headers so you can track it. See Rate Limits for per-tier quotas and how to make the most of them.

Success (200):

{
  "results": [
    {
      "symbol": "SOLUSD",
      "columns": { "close": 142.31, "rsi(14)": 24.8 }
    },
    {
      "symbol": "ADAUSD",
      "columns": { "close": 0.612, "rsi(14)": 27.1 }
    }
  ]
}

results reflects the query's sort ordering and limit truncation. An empty array ({ "results": [] }) means the query is valid but no instrument currently matches, not an error.

Failure modes:

StatusCause
400Parse or plan failure (same error shape as /xql/validate): no data fetch occurs
429Daily quota exhausted for your subscription tier: see Rate Limits
500The query parsed and planned successfully, but the underlying database connection failed

401 happens before any of this

A missing or unrecognized API key is rejected before parse/plan logic runs on all three endpoints: see Authentication.

On this page