How to Handle Paginated API Responses in TableCrafter

Updated July 2026 • 7 min read • By Fahad Murtaza

TableCrafter table builder, connect Gravity Forms, Google Sheets, Airtable, CSV, or JSON data sources
TableCrafter table builder, connect Gravity Forms, Google Sheets, Airtable, CSV, or JSON data sources

Most production APIs do not return all records in a single response. They paginate: 50 records per page, and you request additional pages with a page number or cursor parameter. TableCrafter's REST API source has native pagination support that maps API pagination to the table's built-in page controls, here is how to configure it. WordPress powers 43% of all websites globally (W3Techs, July 2026), and TableCrafter bridges the gap between the data you collect and the tables your users need to see, no custom PHP, no dashboard access required for viewers, and no per-row limits on the free tier. The free version on WordPress.org supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV/PDF, role-based column visibility, and auto-refresh. Every table embeds on any page with a [tablecrafter] shortcode or the native Gutenberg block. Bulk export features reduce administrative processing time by an average of 3.2 hours per week per team (HubSpot Operations Report, 2024).

Why API Pagination Matters for Table Display?

Without pagination handling, TableCrafter can only display the records in the first API response. For an API that returns 50 records per page and has 1,000 total records, a naive integration would show only 50 rows, and the user would have no indication that 950 records exist.

With pagination configured, TableCrafter fetches the correct page of results from the API as the user navigates between pages in the table. The total record count is communicated to the pagination UI so that the correct number of page buttons is displayed.

The configuration you set here applies to every visitor who loads a page containing this table, regardless of whether they are logged in. Role-specific overrides for columns and rows are a separate layer and do not replace these global display settings. Apply global settings first, then add role restrictions as needed for tables that serve multiple user types.

What Is the Two Pagination Patterns?

Offset-Based Pagination

The most common pattern for public REST APIs. The API accepts parameters like page=1&per_page=50 or offset=0&limit=50. The page number or offset is the variable that changes with each request, while the page size stays fixed. Many offset-based APIs also emit a RFC 5988 Link header in the response, which contains the full URL for the next page in the format Link: <https://api.example.com/items?page=2>; rel="next". This header is the primary signal that TableCrafter's fetch_paginated() looks for, and it covers a wide range of popular APIs without any additional configuration beyond the starting endpoint URL.

Examples of offset-based APIs that emit Link headers (compatible with TableCrafter auto-follow):

Cursor-Based Pagination

Instead of a page number, cursor-based APIs return a token in the response that encodes the position of the last returned record. The caller passes this token back to receive the next page. This pattern is used by high-throughput APIs where offset arithmetic is expensive (counting all prior records on each request) or where the dataset changes frequently enough that numeric offsets become unreliable. Cursor-based pagination avoids the "page drift" problem where newly inserted records cause items to shift onto different page numbers between requests.

TableCrafter can auto-follow cursor-based APIs only when the API expresses the next page as a complete, absolute URL in either the RFC 5988 Link header or a body field like next or links.next. APIs that return only an opaque token that the caller must compose into a URL (for example, Stripe's starting_after pattern or Twitter/X v2's next_token) are not compatible with the auto-follow mechanism. For those APIs, point the endpoint URL at the first page with the largest allowed page size and accept that only that page is fetched.

Examples of cursor-based APIs:

How Do I Configure Offset-Based Pagination?

TableCrafter handles paginated JSON sources through its fetch_paginated() method, which automatically detects and follows pagination without any user-configurable page parameter fields. You do not select a pagination mode or enter page parameter names in the admin UI. Instead, you set the endpoint URL for the first page of results, and TableCrafter follows subsequent pages automatically using two detection strategies.

Page parameter settings

TableCrafter detects the next page URL by inspecting two locations in each API response, in this order. Strategy 1: the HTTP Link response header following RFC 5988, for example Link: <https://api.example.com/items?page=2>; rel="next". Many popular offset-based APIs emit this header, including the WordPress REST API (which uses X-WP-TotalPages and Link headers together) and GitHub's API. Strategy 2: a next URL field in the response body, matching the keys next, next_url, nextUrl, next_page_url, links.next, pagination.next, and meta.next. If either strategy finds a valid next URL, TableCrafter fetches it immediately and merges the records into the accumulating result set. This continues until no next URL is found or the safety ceiling of 50 pages is reached. An infinite-loop guard also stops fetching if the next URL equals the current URL.

Total count settings

Because TableCrafter merges all pages into a single flat result set before rendering, the total row count is always the actual count of merged records rather than a number read from a response header. The full merged set is then paginated within the TableCrafter table UI using the rows-per-page setting you configure in the table builder. This means the TableCrafter pagination controls operate over the complete merged dataset, not over the API's raw pages. For APIs that return a very large number of pages, be mindful that all pages are fetched on every table load. The 50-page ceiling with a typical 25-to-100 records-per-page API means a maximum of 2,500 to 5,000 rows per table load.

Example: WordPress REST API posts

The WordPress REST API endpoint /wp-json/wp/v2/posts uses RFC 5988 Link header pagination. Set the endpoint URL in the JSON source configuration and TableCrafter automatically follows the Link header through every page of results:

https://example.com/wp-json/wp/v2/posts?per_page=100

With per_page=100, TableCrafter follows up to 50 Link header pagination cycles, merging up to 5,000 posts into the table. The WordPress REST API returns the total post count in the X-WP-Total header, but TableCrafter counts the merged rows directly. No page parameter name, page size field, or total-count path needs to be configured. A streaming preview during the configuration step fetches only the first 128 KB of the response via a Range header so the column mapper loads quickly even for large multi-page datasets.

How Do I Configure Cursor-Based Pagination?

TableCrafter does not have a separate cursor-based pagination mode in the admin UI. There are no fields for cursor parameter name, cursor path in response, or "has more" path. The same fetch_paginated() auto-follow mechanism handles cursor-based APIs transparently, provided the API expresses the next page as a complete, resolvable URL rather than an opaque token that must be composed into a URL by the caller.

Specifically: if a cursor-based API includes the full URL for the next page in a RFC 5988 Link: <URL>; rel="next" header, or as a full URL in a body field such as next, next_url, or links.next, TableCrafter will follow it without any additional configuration. The same 50-page ceiling and infinite-loop guard apply.

Current limitations of cursor-based pagination

Cursor-based APIs that return only an opaque token (not a full URL) in the response are not supported by the auto-follow mechanism. For example, Stripe returns has_more: true and the last object's id, expecting callers to compose the next request as ?starting_after={last_id}. Twitter/X v2 returns a next_token string that must be appended as ?pagination_token={token}. These patterns require caller-side URL construction that fetch_paginated() does not perform. For such APIs, fetch only the first page by setting the endpoint URL with a large limit parameter (if the API allows it), and accept the constraint that only the first page is available. Airtable's pagination works differently: Airtable uses an offset field in the response body that is a string token, not a full URL, so it also falls outside the auto-follow scope unless the Airtable source type (which has its own pagination handler) is used instead of the generic JSON source.

How Do How Pagination Interacts with Sorting and Filtering Work?

Because fetch_paginated() merges all pages into a flat array on the server before returning data to the table, sorting and filtering are applied to the complete merged dataset rather than relayed as query parameters to the API. This means all records across all fetched pages are available for client-side sorting and filtering within the table UI, regardless of whether the API itself supports sort or filter parameters.

The practical consequence is that a sort or filter operation does not trigger a new API fetch. TableCrafter holds the full merged result in its response and TableCrafter's table engine applies sorting and filtering over those rows. The table's pagination controls then operate over the sorted or filtered subset. This design works well for datasets up to a few thousand rows. For APIs with very large datasets where fetching all pages on every page load would be slow, consider pointing the endpoint URL at a pre-filtered API endpoint (for example, using the API's own query parameters to reduce the result set before TableCrafter fetches it) rather than relying on post-fetch filtering to narrow down a large dataset.

How Does Debugging Pagination Issues Work?

Common problems and how to diagnose them:

Auto-follow requirement: fetch_paginated() requires the API to express the next page as a complete, absolute URL in either the RFC 5988 Link header or a recognized body field. APIs that express pagination as an opaque cursor token requiring caller-side URL construction (Stripe, Twitter v2) are not compatible with the auto-follow mechanism. For those APIs, use a large page size in the endpoint URL to fetch as many records as possible in a single response.

Frequently Asked Questions

How Does Why API Pagination Matters for Table Display Work?

Without pagination handling, TableCrafter can only display the records in the first API response. For an API that returns 50 records per page and has 1,000 total records, a naive integration would show only 50 rows, and the user would have no indication that 950 records exist.

What Is TableCrafter?

TableCrafter is a WordPress plugin that turns data from Gravity Forms, Google Sheets, Airtable, Notion, REST APIs, CSV files, and WooCommerce into interactive, sortable, filterable frontend tables. Embed any table on any WordPress page with the [tablecrafter] shortcode or the native Gutenberg block. No PHP or custom development required. The free version supports CSV, JSON, Google Sheets, and Excel. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST APIs, inline cell editing, export to CSV and PDF, role-based column visibility, and auto-refresh.

Does this require PHP or developer skills?

No. TableCrafter is configured entirely through the WordPress admin interface. You choose your data source, map fields to columns, and set display preferences using point-and-click controls. Embedding uses the [tablecrafter] shortcode or the native Gutenberg block.

Is the free version sufficient or do I need Pro?

The free plugin on WordPress.org supports CSV, JSON, Google Sheets, and Excel sources with unlimited tables, rows, and columns. Pro adds Gravity Forms, Airtable, Notion, WooCommerce, REST API sources, inline cell editing, bulk row actions, export to CSV and PDF, role-based column visibility, and auto-refresh every N seconds.

Ready to try it?

TableCrafter is free on WordPress.org. Pro unlocks inline editing, role-based permissions, and advanced data sources.

The permission check runs server-side on every request. Frontend users cannot bypass column restrictions by modifying the HTML or disabling JavaScript, because TableCrafter evaluates the current user's role before the data leaves the server.

This step completes the connection between your data source and the TableCrafter table engine. Once saved, the plugin caches the connection credentials in the WordPress options table and uses them on every subsequent page load. If you update the source configuration later — for example, rotating an API key or changing a sheet URL — return to this step, enter the new value, and save again. The table updates immediately on next load without any shortcode changes.