Saved Queries¶
Saved queries are reusable, named query definitions you store once and execute many times. They are the right tool when a filter, projection, or sort order belongs to your product logic rather than a single caller.
Use a saved query when:
- the same query runs from multiple clients
- you want a named report or reusable slice of data
- you need runtime variables such as dates, user IDs, or statuses
- you want query logic to live in Centrali instead of being rebuilt in every app
For one-off ad-hoc reads, use Query Records instead.
What a Saved Query Stores¶
A saved query stores:
- a
name - an optional
description - a canonical
query - optional typed
variables
Canonical Shape¶
{
"name": "High Value Paid Orders",
"description": "Paid orders over a configurable minimum amount",
"query": {
"resource": "orders",
"where": {
"and": [
{ "data.status": { "eq": "paid" } },
{ "data.amount": { "gte": "${minimumAmount}" } }
]
},
"sort": [
{ "field": "createdAt", "direction": "desc" }
],
"page": {
"limit": 50
},
"select": {
"fields": ["id", "data.amount", "data.customerId", "createdAt"]
}
},
"variables": {
"minimumAmount": {
"type": "number",
"required": true,
"description": "Minimum order amount"
}
}
}
Variable Syntax¶
Saved query variables use ${name} syntax.
{
"query": {
"resource": "orders",
"where": {
"and": [
{ "data.status": { "eq": "${status}" } },
{ "createdAt": { "gte": "${since}" } }
]
}
}
}
Variable Types¶
Common variable types include:
stringnumberbooleandatetimeid
Create and Manage in the Console¶
Create saved queries from the collection's query area in the Centrali console. Use them for curated product views such as:
- active subscriptions
- failed payments in the last 24 hours
- customers at renewal risk
- orders awaiting fulfillment
Keep them focused. A saved query should describe a meaningful product concept, not a vague implementation detail.
Execute With the SDK¶
Use centrali.savedQueries in new code.
List Saved Queries¶
const all = await centrali.savedQueries.listAll();
const orderQueries = await centrali.savedQueries.list('orders');
Get by Name¶
const query = await centrali.savedQueries.getByName('orders', 'High Value Paid Orders');
console.log(query.data.id);
Execute¶
const result = await centrali.savedQueries.execute('orders', 'query-uuid', {
variables: {
minimumAmount: 250,
},
});
console.log(result.data);
console.log(result.meta);
Execute Over HTTP¶
Use the canonical saved-query routes for write and execution flows:
POST /data/workspace/{workspaceSlug}/api/v1/saved-queriesPUT /data/workspace/{workspaceSlug}/api/v1/saved-queries/{id}POST /data/workspace/{workspaceSlug}/api/v1/saved-queries/testPOST /data/workspace/{workspaceSlug}/api/v1/saved-queries/{id}/execute
Create¶
curl -X POST "https://api.centrali.io/data/workspace/acme/api/v1/saved-queries" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Recent Failed Payments",
"query": {
"resource": "payments",
"where": {
"and": [
{ "data.status": { "eq": "failed" } },
{ "createdAt": { "gte": "${since}" } }
]
},
"sort": [
{ "field": "createdAt", "direction": "desc" }
],
"page": {
"limit": 100
}
},
"variables": {
"since": {
"type": "datetime",
"required": true
}
}
}'
Test Before Saving¶
curl -X POST "https://api.centrali.io/data/workspace/acme/api/v1/saved-queries/test" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": {
"resource": "payments",
"where": {
"data.status": { "eq": "${status}" }
},
"page": { "limit": 5 }
},
"variables": {
"status": "failed"
}
}'
Execute¶
curl -X POST "https://api.centrali.io/data/workspace/acme/api/v1/saved-queries/query-uuid/execute" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"variables": {
"since": "2026-04-01T00:00:00Z"
}
}'
Saved query execution returns the same { data, meta } style result envelope used by canonical record queries.
What to Put in a Saved Query¶
Good saved queries usually contain:
- stable business filters
- a clear sort order
- a sensible page limit
- an intentional field projection
- a small number of well-named variables
Avoid putting every possible option into one giant saved query. If two consumers want meaningfully different behavior, create two saved queries.
Best Practices¶
- Name queries after the business meaning, not the implementation.
- Use variables for values that change at runtime.
- Use
select.fieldsto keep result payloads focused. - Prefer saved queries for product reports, dashboards, and reusable backend reads.
- Keep ad-hoc exploration in
records.queryand move to a saved query only when the pattern proves useful.