API
Pagination
Collections return data, next_cursor and has_more. Pass next_cursor back as cursor, size pages with limit up to 100, and let the SDKs follow pages for you.
Every collection returns an object, never a bare array:
{
"data": [ { "id": "itm_invoiceextr2", "full_name": "acme/invoice-extractor" } ],
"next_cursor": "eyJlIjoxNzkzNzYxODYxLCJkIjpb...",
"has_more": true,
"total": 37
}| Field | Meaning |
|---|---|
data | The page of results, in the order the operation documents. |
next_cursor | An opaque string. Pass it back as cursor to get the next page. It is null on the last page. |
has_more | true while there is another page. Stop on has_more: false. |
total | The number of matches, present on search where it is cheap to count. Do not rely on it elsewhere. |
Parameters
| Parameter | Meaning |
|---|---|
limit | Page size from 1 to 100, default 30. The ledger feed (list_ledger_events) allows up to 500. A larger value answers 400 invalid_parameter with errors[0].code: "out_of_range". |
cursor | The next_cursor of the previous page. Send it with the same filters and sort. |
Cursors
- A cursor is opaque. Do not build, parse or store it for later: it encodes the sort position of the last row and a signature, and it expires after 24 hours.
- Because it encodes a position rather than an offset, rows inserted while you page do not cause duplicates or skipped rows.
- A cursor that is tampered with, expired, or used with different filters answers
400 invalid_cursor. Restart the listing from the first page. - The response also has a
Link: <...>; rel="next"header that mirrorsnext_cursor, for clients that follow links.
Walking every page
curl
cursor=""
while :; do
page=$(curl -sS -G https://reuseforge.com/api/v1/items --data-urlencode 'q=pdf' --data-urlencode 'limit=100' ${cursor:+--data-urlencode "cursor=$cursor"})
echo "$page" | jq -r '.data[].full_name'
[ "$(echo "$page" | jq -r .has_more)" = "true" ] || break
cursor=$(echo "$page" | jq -r .next_cursor)
donePython
import reuseforge
client = reuseforge.Client()
page = client.search_items(q="pdf", limit=100)
print(page.data[0]["full_name"], page.has_more, page.next_cursor)
for item in client.search_items(q="pdf"): # iterating fetches further pages lazily
print(item["full_name"])
for item in client.search_items(q="pdf", max_items=250): # stop after 250 rows
pass
for p in client.search_items(q="pdf").pages(): # page objects instead of rows
print(len(p.data))JavaScript
import { ReuseForge } from '@reuseforge/sdk';
const client = new ReuseForge();
const first = await client.searchItems({ q: 'pdf', limit: 100 }); // a Page: first.data, first.has_more, first.next_cursor
const next = await first.nextPage(); // null when there is none
for await (const item of client.searchItems({ q: 'pdf' })) console.log(item.full_name); // lazily, across pages
const some = await client.searchItems({ q: 'pdf', maxItems: 250 }).toArray();
for await (const page of client.searchItems({ q: 'pdf' }).pages()) console.log(page.data.length);CLI
rf search pdf --limit 100 # one page; the JSON output has next_cursor
rf search pdf --cursor eyJ... # the next page
rf search pdf --all # follow every page (up to 10000 rows)The SDKs stop if a cursor repeats, so a misbehaving server cannot make a loop run forever.
Which operations paginate
Every operation that returns a list: search_items, list_reviews, list_versions, list_tokens, list_orders, list_payouts, list_projects, list_webhooks, list_webhook_deliveries, list_ledger_events and the other list_* operations. Their pages are in the reference. The sort order is part of each operation's documentation; search_items takes sort (relevance, trending, stars, downloads, updated, newest, rating, price_asc, price_desc).
Last updated: