Sorting & Searching
How to sort rows and filter by field value in SheetsAPI - sort direction, multi-column sort, search syntax, and combining both.
SheetsAPI provides two query parameters for controlling which rows you receive and how
they are ordered: sort and search.
Sorting
Use the sort parameter to order results by a column.
GET /api/spreadsheets/{userKey}/{sheet}?sort=price
Ascending (default)
Pass the column name:
?sort=name
?sort=price
?sort=created_at
Descending
Prefix the column name with -:
?sort=-price // highest price first
?sort=-created_at // newest first
Multi-column sort
Pass multiple columns separated by commas:
?sort=category,-price // by category A→Z, then by price high→low within each category
Column names are case-sensitive and must match the header row of your sheet exactly.
Searching (filtering)
Use the search parameter to return only rows where a field matches a value.
GET /api/spreadsheets/{userKey}/{sheet}?search=category:books
The format is field:value.
| Example | Returns |
|---|---|
search=category:books | Rows where category equals "books" |
search=status:active | Rows where status equals "active" |
search=name:widget | Rows where name contains "widget" (case-insensitive) |
Exact vs partial matching
- String columns: partial match (case-insensitive
includes) - Numeric columns: exact match (after stripping formatting)
?search=name:pro // matches "Widget Pro", "Pro Series", "Promo Item"
?search=price:49 // matches rows where price contains "49" - e.g. "49.99", "$49"
For an exact match on a string, include the full value:
?search=status:active // rows where status is exactly "active"
Combining search and sort
Both parameters compose freely:
# Books sorted by price, lowest first
curl "...?search=category:books&sort=price"
# Active products sorted by name, page 2
curl "...?search=status:active&sort=name&limit=20&offset=20"Code examples
JavaScript
async function getProducts(category: string, sort = "-price"): Promise<Product[]> {
const url = new URL(`https://sheetsapi.gkit.mreshank.com/api/spreadsheets/${USER_KEY}/Products`);
url.searchParams.set("search", `category:${category}`);
url.searchParams.set("sort", sort);
url.searchParams.set("limit", "100");
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data } = await resp.json();
return data as Product[];
}Python
import httpx
def get_active_users(sort: str = "name") -> list[dict]:
resp = httpx.get(
f"https://sheetsapi.gkit.mreshank.com/api/spreadsheets/{USER_KEY}/Users",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"search": "status:active", "sort": sort, "limit": 500}
)
resp.raise_for_status()
return resp.json()["data"]Pagination with search
meta.total always reflects the filtered row count, not the full sheet size. Use it to
paginate search results correctly:
const PAGE_SIZE = 20;
async function searchPage(query: string, page: number) {
const { data, meta } = await getSheet("Products", {
search: query,
sort: "name",
limit: PAGE_SIZE,
offset: (page - 1) * PAGE_SIZE,
});
return {
rows: data,
totalPages: Math.ceil(meta.total / PAGE_SIZE),
};
}Limitations
searchsupports onefield:valuepair per request. For multi-field filtering, fetch a broader result set and filter client-side, or make multiple requests.sortis applied beforelimit/offset, so the sort order is stable across pages.- Sorting is lexicographic for text columns. For numeric columns, wrap values in a consistent format (e.g. zero-padded integers) if you need numeric sort order.
Reference
| Parameter | Format | Example |
|---|---|---|
sort | column or -column | sort=-created_at |
sort (multi) | col1,col2 | sort=category,-price |
search | field:value | search=status:active |
See Query Parameters for the full parameter list.