Documentation
Querying
Query patterns and best practices
Querying
🔍 Query Patterns & Best Practices
Implemented by query_handler / get_by_id_handler in stackhouse/src/api/handlers.rs, routed at stackhouse/src/api/routes.rs:17-23.
REST API Queries
# Get all documents (default limit: 100, hard cap: 1000)
GET /v1/query/:collection
# Get specific document
GET /v1/query/:collection/:id
# With pagination
GET /v1/query/:collection?limit=100&offset=0
# With ordering — param is `order_dir`, not `order`
GET /v1/query/:collection?order_by=created_at&order_dir=descResponse shape: {"success": true, "data": [...], "count": N, "collection": "..."}.
Filtering
Equality filters are applied server-side via query-string parameters — any param that isn't one of limit, offset, order_by, order_dir is treated as a column = value filter, AND-ed together, with the column name validated as a safe SQL identifier before use:
# WHERE active = 'true'
GET /v1/query/users?active=true
# WHERE active = 'true' AND role = 'admin'
GET /v1/query/users?active=true&role=adminAll filter values are compared as text equality — there is no operator syntax (>, <, LIKE, etc.) via this endpoint. For anything beyond equality, use the raw SQL endpoint below.
// Client-side filtering is only needed for logic the query-string API
// doesn't support (e.g. non-equality comparisons):
const users = await fetch('/v1/query/users?active=true')
.then(r => r.json())
.then(data => data.data);Advanced Patterns
Raw SQL access
POST /v1/sql/query
{"query": "SELECT * FROM users WHERE age > 25"}Gated behind raw_sql_enabled (off by default) and admin auth — see API Reference for current restrictions on this endpoint (destructive-statement filtering, etc).
Performance Tips
Do
✅ Use specific ID lookups (GET /v1/query/:collection/:id)
✅ Use the built-in limit/offset (max 1000 rows per request)
✅ Create indexes on frequently queried fields
Avoid
❌ Large result sets — 1000 rows is a hard server-side cap
Next: Indexing