Sorting & Pagination
Control the order and page size of SheetsAPI results using sort, limit, and offset query parameters.
SheetsAPI returns rows in the order they appear in your sheet by default. Use the sort,
limit, and offset query parameters to control ordering and fetch results in manageable
pages.
Overview
Endpoint
GET https://api.gkit.io/api/spreadsheets/{userKey}/{sheetName}
Defaults
| Parameter | Default | Maximum |
|---|---|---|
sort | none (sheet row order) | - |
limit | 100 | 1000 |
offset | 0 | - |
Every response wraps rows in a data array and includes a meta object:
{
"data": [ ... ],
"meta": {
"total": 1500,
"limit": 100,
"offset": 0
}
}| Field | Meaning |
|---|---|
total | Total number of rows matching the current request (respects any active filters) |
limit | The limit value applied to this response |
offset | The offset value applied to this response |
Use meta.total - not a hard-coded row count - to drive pagination UI and loop termination.
Sorting
Pass the sort query parameter to order results by a column.
Direction
| Syntax | Direction | Example |
|---|---|---|
sort=field | Ascending (A → Z, 0 → 9) | sort=name |
sort=-field | Descending (Z → A, 9 → 0) | sort=-price |
# Cheapest products first
curl "https://api.gkit.io/api/spreadsheets/YOUR_USER_KEY/Products?sort=price" \
-H "Authorization: Bearer sk_your_api_key"
# Newest entries first
curl "https://api.gkit.io/api/spreadsheets/YOUR_USER_KEY/Products?sort=-created_at" \
-H "Authorization: Bearer sk_your_api_key"Column names are case-sensitive and must match the header row of your sheet exactly.
Sort behaviour by type
- Text columns - lexicographic (alphabetical) order.
"10"sorts before"9". - Numeric columns - numeric order. Zero-pad values in your sheet if you need consistent sort order on mixed text/number columns.
Multi-column sort
Pass multiple sort parameters to sort by more than one column. The API applies them
left to right:
?sort=category&sort=-price
This returns rows sorted by category A → Z, then by price highest to lowest within
each category.
curl "https://api.gkit.io/api/spreadsheets/YOUR_USER_KEY/Products?sort=category&sort=-price" \
-H "Authorization: Bearer sk_your_api_key"Pagination
Parameters
| Parameter | Type | Default | Maximum | Description |
|---|---|---|---|---|
limit | integer | 100 | 1000 | Number of rows to return |
offset | integer | 0 | - | Number of rows to skip before returning results |
Calculating pages
To map a 1-based page number to an offset:
offset = (page - 1) * limit
Or in JavaScript:
const page = Math.floor(offset / limit) + 1;Fetching all pages - TypeScript
This loop fetches every row in a sheet, requesting the maximum limit per call to
minimise round trips:
const USER_KEY = process.env.GKIT_USER_KEY!;
const API_KEY = process.env.GKIT_API_KEY!;
const BASE_URL = "https://api.gkit.io/api/spreadsheets";
async function fetchAllRows<T>(sheetName: string): Promise<T[]> {
const all: T[] = [];
const limit = 1000;
let offset = 0;
while (true) {
const url = new URL(`${BASE_URL}/${USER_KEY}/${sheetName}`);
url.searchParams.set("limit", String(limit));
url.searchParams.set("offset", String(offset));
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
if (!resp.ok) throw new Error(`SheetsAPI error ${resp.status}`);
const { data, meta }: { data: T[]; meta: { total: number } } = await resp.json();
all.push(...data);
offset += limit;
if (all.length >= meta.total) break;
}
return all;
}Common page sizes
| Use case | Recommended limit |
|---|---|
| Table with scroll | 25 – 50 |
| Standard paginated table | 100 (default) |
| Export / background job | 1000 (maximum) |
| Typeahead / autocomplete | 10 – 20 |
Combining sort, filter, and pagination
sort and limit/offset compose with the search filter. Sorting is applied before
slicing, so sort order is stable across pages.
# Page 2 of "category:books", sorted cheapest first, 20 rows per page
curl "https://api.gkit.io/api/spreadsheets/YOUR_USER_KEY/Products?search=category:books&sort=price&limit=20&offset=20" \
-H "Authorization: Bearer sk_your_api_key"When a search filter is active, meta.total reflects the number of filtered rows -
not the full sheet size. Use it to calculate total pages:
const totalPages = Math.ceil(meta.total / limit);Notes
-
Offset-based pagination and concurrent edits - SheetsAPI uses offset pagination. If rows are inserted or deleted in the middle of the sheet while you are iterating, your offsets shift and you may receive duplicate or skipped rows. For append-only sheets (new rows always added at the bottom) this is not an issue. If your sheet is actively edited during iteration, consider fetching all rows in a single large request or scheduling exports during low-activity windows.
-
Sorting happens server-side -
sortis applied to the full matching dataset beforelimit/offsetis applied, guaranteeing consistent ordering across pages. -
meta.totalrespects filters - always derive total page counts frommeta.total, not from a cached row count.
Reference
| Parameter | Format | Example |
|---|---|---|
sort | column | sort=name |
sort (descending) | -column | sort=-created_at |
sort (multi) | repeated params | sort=category&sort=-price |
limit | integer 1 – 1000 | limit=50 |
offset | integer ≥ 0 | offset=200 |
See Query Parameters for the full parameter reference,
and Filtering for search syntax.