Skip to main content
The SQL Query API allows you to execute read-only SQL SELECT queries directly against the SolixDB ClickHouse database. Queries automatically get a default LIMIT of 1000 if not specified, making it safe and convenient to query data.

Endpoint

POST /v1/query
Base URL: https://api.solixdb.xyz/v1/query

Authentication

All requests require an API key. Include it in the x-api-key header or as an api-key query parameter.
For details on authentication, see our Authentication guide.

Request Format

{
  "query": "SELECT * FROM transactions LIMIT 10",
  "format": "json"
}

Request Fields

  • query (required): SQL SELECT query string
  • format (optional): Response format - "json" (default) or "csv"

Automatic LIMIT Injection

If your query doesn’t include a LIMIT clause, a default LIMIT of 1000 is automatically added:
-- Your query
SELECT * FROM transactions WHERE protocol_name = 'jupiter_v6'

-- Automatically becomes
SELECT * FROM transactions WHERE protocol_name = 'jupiter_v6' LIMIT 1000
Maximum LIMIT: 10,000 rows
You can specify your own LIMIT (up to 10,000). If you specify a LIMIT greater than 10,000, the query will be rejected.

Response Format

JSON Format (default)

{
  "data": [
    {
      "signature": "5VERv8NMxzbPDohNpJhHopN2C9R4G5GaPevYf5hLJ8Z7",
      "protocol_name": "jupiter_v6",
      "fee": "5000",
      "compute_units": "200000"
    }
  ],
  "count": 10,
  "query": "SELECT signature, protocol_name, fee FROM transactions WHERE protocol_name = 'jupiter_v6' LIMIT 10"
}

CSV Format

When format: "csv" is specified, the response is a CSV string:
signature,protocol_name,fee
5VERv8NMxzbPDohNpJhHopN2C9R4G5GaPevYf5hLJ8Z7,jupiter_v6,5000

Query Restrictions

For security, only read-only queries are allowed:

Allowed Operations

  • SELECT statements
  • WITH (CTEs - Common Table Expressions)
  • JOIN operations
  • Aggregations (COUNT, SUM, AVG, etc.)
  • GROUP BY, ORDER BY, HAVING
  • LIMIT, OFFSET
  • Subqueries

Blocked Operations

The following operations are not allowed:
  • INSERT, UPDATE, DELETE
  • DROP, CREATE, ALTER
  • TRUNCATE, REPLACE
  • GRANT, REVOKE
  • KILL, OPTIMIZE
  • Multiple statements (semicolons)

Examples

Basic Query

curl -X POST "https://api.solixdb.xyz/v1/query" \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "query": "SELECT * FROM transactions WHERE protocol_name = '\''jupiter_v6'\'' LIMIT 10",
    "format": "json"
  }'

Aggregation Query

SELECT 
  protocol_name,
  COUNT(*) as count,
  AVG(fee) as avg_fee,
  MIN(fee) as min_fee,
  MAX(fee) as max_fee
FROM transactions
WHERE date >= '2025-01-01'
  AND date <= '2025-01-31'
  AND protocol_name IN ('jupiter_v6', 'pump_fun')
GROUP BY protocol_name
ORDER BY count DESC
This query will automatically get LIMIT 1000 appended if you don’t specify one.

Query with Date Range

SELECT 
  signature,
  slot,
  block_time,
  protocol_name,
  fee,
  compute_units,
  success
FROM transactions
WHERE date >= '2025-01-01'
  AND date <= '2025-01-31'
  AND protocol_name = 'jupiter_v6'
  AND success = 1
ORDER BY block_time DESC
LIMIT 100

Complex Query with CTE

WITH protocol_stats AS (
  SELECT 
    protocol_name,
    COUNT(*) as tx_count,
    AVG(fee) as avg_fee
  FROM transactions
  WHERE date >= '2025-01-01'
    AND date <= '2025-01-31'
  GROUP BY protocol_name
)
SELECT 
  protocol_name,
  tx_count,
  avg_fee,
  CASE 
    WHEN avg_fee > 10000 THEN 'High'
    WHEN avg_fee > 5000 THEN 'Medium'
    ELSE 'Low'
  END as fee_tier
FROM protocol_stats
ORDER BY tx_count DESC
LIMIT 50

Export to CSV

const response = await fetch('https://api.solixdb.xyz/v1/query', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    query: "SELECT signature, protocol_name, fee FROM transactions WHERE protocol_name = 'jupiter_v6'",
    format: 'csv'
  })
});

const csv = await response.text();
console.log(csv);

Error Responses

Invalid Query

{
  "error": "Invalid query",
  "message": "Only SELECT queries are allowed"
}

Missing LIMIT (if you try to query without one)

Actually, LIMIT is automatically added, so this won’t happen. But if you specify a LIMIT > 10,000:
{
  "error": "Invalid query",
  "message": "LIMIT value cannot exceed 10,000 rows. Please reduce the limit."
}

Query Too Long

{
  "error": "Invalid query",
  "message": "Query is too long. Maximum length is 100,000 characters."
}

Best Practices

Specify a reasonable LIMIT for your use case. The default is 1000, but you can go up to 10,000.
Use WHERE clauses to filter data early in the query to reduce processing time.
Filter by indexed columns (date, protocol_name, program_id) for better performance.
Select only the columns you need to reduce response size and improve performance.
Use aggregations (COUNT, SUM, AVG) to reduce result set size when you only need statistics.

Performance Tips

  1. Use date filters: Always filter by date when possible for partition pruning
  2. Limit result sets: Use LIMIT to avoid large result sets
  3. Index usage: Filter by protocol_name, program_id, or signature for indexed lookups
  4. Avoid full table scans: Always include WHERE clauses

Next Steps