GunSpec
Pagination

Pagination

How a list is walked, what each plan may read of it, and every operation that pages. Read from the OpenAPI spec and the API's own limits, so the figures here are the ones the API enforces.

  • 30Operations with page + per_page
  • 6Capped lists with limit
  • 100Max per_page
  • 10,000Highest page number

Every list takes the same two query parameters, declared once in the spec and shared by every operation. Anything outside the bounds is a 400 with INVALID_PARAMETER; an unknown parameter is ignored, not refused.

pageinteger

Page number, from 1 to 10,000

Min
1
Max
10,000
Default
1
per_pageinteger

Items per page (max 100)

Min
1
Max
100
Default
20

per_page tops out at 100 almost everywhere. A larger ceiling (1000) applies to the bulk lists: /v1/firearms/media.

6 operations are rankings rather than lists: they take a single limit, return the top rows and carry no pagination object: /v1/firearms/top, /v1/popular/firearms, /v1/stats/calibers/popular, /v1/stats/manufacturers/prolific, /v1/stats/feature-frequency, /v1/data/tasks.

A paged response wraps the page in the same object every time. The sample below is built from the schema's own examples, so it cannot drift from what the API sends.

Paged response
json
{  "success": true,  "data": [    /* one page of records */  ],  "pagination": {    "page": 1,    "per_page": 20,    "limit": 20,    "total": 42,    "totalPages": 3  }}
  • pagination.pageintegerrequired

    The page this response is, 1-based.

  • pagination.per_pageintegerrequired

    Page size. Same value as limit.

  • pagination.limitintegerrequired

    Page size. Alias of per_page.

  • pagination.totalintegeroptional

    Total records matching the query across every page.

  • pagination.totalPagesintegeroptional

    How many pages the result set spans at the current per_page.

Page-size is reported under both per_page (matching the request parameter) and limit (retained for existing integrations). They always carry the same value. total and totalPages are omitted for Explorer and anonymous callers.

The loop that works on every plan drives itself from the page it just received, not from totalPages. Four rules and the code in three languages.

  1. 1Stop when a page comes back short. Fewer rows than per_page means it was the last page, on every plan.
  2. 2Treat total and totalPages as optional extras. They are absent on Explorer and anonymous calls, so a loop that tests page < totalPages stops after one page there.
  3. 3Ask for the largest page you can use. per_page=100 is 100× fewer requests against your per-minute limit and your daily allowance, and reaches the same rows.
  4. 4Walk once, then stay current by other means. Each page carries an ETag and answers 304 when unchanged, and data webhooks push catalog changes so a mirror never re-walks the list. More than 10 sequential pages inside 90 seconds is refused.
Read every rifle
cURL
# Page 1, then keep going while a page comes back fullcurl -H "X-API-Key: your_api_key" \  "https://api.gunspec.io/v1/firearms?category=rifle&per_page=100&page=1" curl -H "X-API-Key: your_api_key" \  "https://api.gunspec.io/v1/firearms?category=rifle&per_page=100&page=2"

Paging is where the plans differ most, and each rule below is enforced by the API rather than by convention. The figures come from the same configuration the middleware reads.

Page depth

The deepest page number a plan may request on the firearm lists. Past it the response is a 403; narrow the list with filters or upgrade.

Explorer
5 pages
Builder
25 pages
Studio
Enterprise

Total counts

Whether the envelope carries total and totalPages. Hidden on the free plan, so the size of the catalog cannot be read off a list.

Explorer
Builder
Studio
Enterprise

Sequential-page burst

10 or more consecutive pages inside 90 seconds is a 429, per key or per address.

Aimed at crawlers. A reader paging a UI never reaches it; a script that wants the catalog should use per_page at its ceiling, filters, or webhooks.

Hard ceilings

page stops at 10,000 and per_page at 100 on every plan, including Enterprise.

A value above the ceiling is a 400, not a clamp: per_page=500 is refused rather than silently served as 100.

How a refused page request reads

  • The plan does not page this deep into a list. Narrow the list with filters, or upgrade for deeper paging.

  • Too many sequential pages in a short time. Slow the walk down, or use a larger per_page.

Where a list can be ordered it declares a sort vocabulary and an order direction; the default order is the one the reference shows for each. Every other list has a fixed order the operation's description states.

    • name
    • weight
    • year
    • caliber
    • created_at
    • favorites

    order: asc | desc

    • created_at
    • updated_at
    • status
    • priority

    order: asc | desc

30 operations take page and per_page and answer with the envelope; 6 take a single limit. Each row links to its reference page.

RowEndpointStyleDefaultMaxPlan
01/v1/firearmsList firearmspage + per_page20100Explorer
02/v1/firearms/searchFull-text searchpage + per_page20100Builder
03/v1/firearms/mediaIndex every firearm that has imagerypage + per_page2501000Explorer
04/v1/firearms/topRank firearms by a superlativelimit1025Builder
05/v1/firearms/by-featureFilter by featurepage + per_page20100Builder
06/v1/firearms/by-actionFilter by action typepage + per_page20100Explorer
07/v1/firearms/by-materialFilter by construction materialpage + per_page20100Builder
08/v1/firearms/by-designerFilter by designerpage + per_page20100Builder
09/v1/firearms/by-conflictFilter by conflictpage + per_page20100Studio
10/v1/firearms/power-ratingRank by composite power ratingpage + per_page20100Builder
11/v1/firearms/timelineBrowse the catalog chronologicallypage + per_page50100Builder
12/v1/popular/firearmsList the most viewed firearmslimit1020Explorer
13/v1/manufacturersList manufacturerspage + per_page20100Explorer
14/v1/manufacturers/{id}/firearmsList a manufacturer firearmspage + per_page20100Explorer
15/v1/calibersList caliberspage + per_page20100Explorer
16/v1/calibers/{id}/firearmsList firearms in a caliberpage + per_page20100Explorer
17/v1/calibers/{id}/ammunitionList ammunition for a caliberpage + per_page20100Builder
18/v1/ammunitionList ammunition loadspage + per_page20100Builder
19/v1/categories/{slug}/firearmsList firearms in a categorypage + per_page20100Explorer
20/v1/stats/calibers/popularRank calibers by adoptionlimit20100Explorer
21/v1/stats/manufacturers/prolificRank manufacturers by outputlimit20100Explorer
22/v1/stats/feature-frequencyRank features by frequencylimit50100Builder
23/v1/data/tasksList data remediation taskslimit50200Explorer
24/v1/data/gaps/recordsList records missing a fieldpage + per_page20100Enterprise
25/v1/data/confidenceGet per-record confidence scorespage + per_page20100Enterprise
26/v1/me/favoritesList your favoritespage + per_page20100Explorer
27/v1/me/reportsList your data reportspage + per_page20100Explorer
28/v1/me/supportList your support ticketspage + per_page20100Explorer
29/v1/me/webhooksList your webhook endpointspage + per_page20100Explorer
30/v1/game-stats/versions/{version}/firearmsList firearms in a snapshotpage + per_page20100Builder
31/v1/changelogList changelog entriespage + per_page20100Explorer
32/v1/blogList blog postspage + per_page20100Explorer
33/v1/attachmentsList attachmentspage + per_page20100Explorer
34/v1/attachments/{id}/firearmsList firearms an attachment fitspage + per_page20100Studio
35/v1/vendor/offersRead back your listingspage + per_page20100Enterprise
36/v1/interfaces/{id}/firearmsList firearms exposing a standardpage + per_page20100Studio

The official SDKs expose an auto-paging iterator that applies every rule on this page: it fetches pages on demand, stops on a short page and never reads totalPages.

TypeScript
typescript
for await (const firearm of client.firearms.listAutoPaging({ category: 'rifle' })) {  console.log(firearm.name); // pages are fetched on demand}
Python
python
for firearm in client.firearms.list_auto_paging({"category": "rifle"}):    print(firearm["name"])  # pages are fetched on demand

Handing this to a coding agent? The agent packs and llms.txt carry the same rules in a form a model can act on: page from the short-page signal, cap per_page, and read error.reason on a 403 or 429 before retrying.