Appearance
Pagination
FreshThe RSS.app API uses offset-based pagination for list endpoints. This page explains how the pagination model works and how to iterate through large result sets correctly.
How Offset Pagination Works
Offset pagination works by specifying how many results to skip (offset) and how many to return (limit). The API returns a slice of the full result set starting at the offset position.
For example, if you have 25 feeds:
| Request | limit | offset | Results returned |
|---|---|---|---|
| Page 1 | 10 | 0 | Feeds 1-10 |
| Page 2 | 10 | 10 | Feeds 11-20 |
| Page 3 | 10 | 20 | Feeds 21-25 |
| Page 4 | 10 | 30 | Empty array (signals end) |
You know you've reached the last page when the API returns fewer results than your limit value.
Pagination Parameters
Both /v1/feeds and /v1/bundles accept these query parameters:
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
limit | integer | 10 | 100 | Number of results per page |
offset | integer | 0 | — | Number of results to skip |
Basic Pagination Example
js
const axios = require('axios');
const apiClient = axios.create({
baseURL: 'https://api.rss.app/v1',
headers: {
Authorization: `Bearer YOUR_API_KEY:YOUR_API_SECRET`,
},
});
// Get a single page of feeds
async function getFeedsPage(limit = 10, offset = 0) {
const response = await apiClient.get('/feeds', {
params: { limit, offset },
});
return response.data;
}
// Get the first page
const firstPage = await getFeedsPage(10, 0);
console.log(`Got ${firstPage.length} feeds`);
// Get the second page
const secondPage = await getFeedsPage(10, 10);
console.log(`Got ${secondPage.length} feeds`);Iterating Through All Results
To retrieve all feeds regardless of how many exist, loop until you get a response smaller than your page size:
js
async function getAllFeeds() {
const allFeeds = [];
const limit = 100; // Use max page size for efficiency
let offset = 0;
while (true) {
const page = await apiClient.get('/feeds', {
params: { limit, offset },
});
const feeds = page.data;
allFeeds.push(...feeds);
// Stop when we got fewer results than requested
if (feeds.length < limit) {
break;
}
offset += limit;
}
return allFeeds;
}
getAllFeeds().then((feeds) => {
console.log(`Total feeds: ${feeds.length}`);
});Iterating Through All Bundles
The same pattern works for bundles:
js
async function getAllBundles() {
const allBundles = [];
const limit = 100;
let offset = 0;
while (true) {
const page = await apiClient.get('/bundles', {
params: { limit, offset },
});
const bundles = page.data;
allBundles.push(...bundles);
if (bundles.length < limit) {
break;
}
offset += limit;
}
return allBundles;
}Paginating with a Callback
For large datasets, you may want to process each page as it arrives rather than loading everything into memory at once:
js
async function paginateFeeds(onPage, limit = 50) {
let offset = 0;
let totalProcessed = 0;
while (true) {
const feeds = await apiClient
.get('/feeds', { params: { limit, offset } })
.then((r) => r.data);
if (feeds.length === 0) break;
await onPage(feeds, offset);
totalProcessed += feeds.length;
if (feeds.length < limit) break;
offset += limit;
}
return totalProcessed;
}
// Usage: process each page
await paginateFeeds(async (feeds, offset) => {
console.log(`Processing page at offset ${offset}: ${feeds.length} feeds`);
for (const feed of feeds) {
await syncFeedToDatabase(feed);
}
});Rate Limiting and Delay
If you are iterating through a very large dataset, add a small delay between page requests to avoid hitting the rate limiter:
js
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function getAllFeedsSafely() {
const allFeeds = [];
const limit = 50;
let offset = 0;
while (true) {
const feeds = await apiClient
.get('/feeds', { params: { limit, offset } })
.then((r) => r.data);
allFeeds.push(...feeds);
if (feeds.length < limit) break;
offset += limit;
// 200ms pause between pages to be respectful of rate limits
await sleep(200);
}
return allFeeds;
}Handling Empty Results
When offset exceeds the total count of resources, the API returns an empty array rather than an error. Always check for this:
js
const page = await apiClient.get('/feeds', { params: { limit: 10, offset: 9999 } });
// page.data === [] (empty array, no error)Your pagination loop should handle this naturally since [].length < limit will be true and cause the loop to exit.
Choosing Your Page Size
- Use
limit=100when you need all results as fast as possible and memory is not a concern - Use
limit=10tolimit=25for UI pagination where you display one page at a time - Use
limit=50as a balanced default for background sync jobs
There is no cost difference between page sizes — the API charges per request, not per result returned.