Skip to main content

Pagination

OpenMetadata uses both cursor-based and offset-based pagination, depending on the endpoint. Most top-level entity list endpoints use cursor-based pagination for stable traversal, while many sub-resource and specialized endpoints use limit plus offset.

Pagination Parameters

ParameterTypeDefaultDescription
limitintegerVaries by endpointPage size. Many top-level entity list endpoints default to 10 and allow up to 1,000,000, while offset-based sub-resource endpoints often use lower defaults and caps, such as 1,000 for table columns.
beforestring-Cursor for the previous page on cursor-paginated endpoints
afterstring-Cursor for the next page on cursor-paginated endpoints
offsetintegerWhen supportedRow offset on offset-paginated endpoints. If omitted, the endpoint starts from the first page.

Response Fields

The paging object varies by endpoint. Cursor-paginated responses usually include:
FieldTypeDescription
totalintegerTotal count of matching resources
beforestringCursor for the previous page (if available)
afterstringCursor for the next page (if available)
Offset-paginated endpoints also return total, and may include offset, limit, or cursor-style before/after fields depending on the resource. Check the endpoint schema for the exact response shape.

Examples

Basic Pagination

Basic Pagination
from metadata.ingestion.ometa.ometa_api import OpenMetadata
from metadata.generated.schema.entity.data.table import Table

metadata = OpenMetadata(config)

# Get first page
first_page = metadata.list_entities(
    entity=Table,
    limit=20
)

print(f"Total tables: {first_page.paging.total}")
for table in first_page.entities:
    print(table.fullyQualifiedName)

# Get next page using after cursor
if first_page.paging.after:
    next_page = metadata.list_entities(
        entity=Table,
        limit=20,
        after=first_page.paging.after
    )
    for table in next_page.entities:
        print(table.fullyQualifiedName)
import org.openmetadata.client.api.TablesApi;
import org.openmetadata.client.model.TableList;

TablesApi tablesApi = client.buildClient(TablesApi.class);

// Get first page
TableList firstPage = tablesApi.listTables(null, 20, null, null, null);

System.out.println("Total tables: " + firstPage.getPaging().getTotal());
for (Table table : firstPage.getData()) {
    System.out.println(table.getFullyQualifiedName());
}

// Get next page
if (firstPage.getPaging().getAfter() != null) {
    TableList nextPage = tablesApi.listTables(
        null, 20, null, firstPage.getPaging().getAfter(), null
    );
    for (Table table : nextPage.getData()) {
        System.out.println(table.getFullyQualifiedName());
    }
}
# Get first page
curl -X GET "https://your-company.open-metadata.org/api/v1/tables?limit=20" \
  -H "Authorization: Bearer $TOKEN"

# Response includes paging.after cursor
# {
#   "data": [...],
#   "paging": {
#     "total": 150,
#     "after": "eyJsYXN0SWQiOiIxMjM0NTY3ODkwIn0="
#   }
# }

# Get next page using after cursor
curl -X GET "https://your-company.open-metadata.org/api/v1/tables?limit=20&after=eyJsYXN0SWQiOiIxMjM0NTY3ODkwIn0=" \
  -H "Authorization: Bearer $TOKEN"

Offset-Based Pagination

Use offset on endpoints that document it, such as /v1/tables/{id}/columns:
# Get first 20 columns
curl "{base_url}/api/v1/tables/{id}/columns?limit=20&offset=0" \
  -H "Authorization: Bearer {access_token}"

# Get next 20 columns
curl "{base_url}/api/v1/tables/{id}/columns?limit=20&offset=20" \
  -H "Authorization: Bearer {access_token}"

Iterating Through All Results

Iterating Results
from metadata.ingestion.ometa.ometa_api import OpenMetadata
from metadata.generated.schema.entity.data.table import Table

metadata = OpenMetadata(config)

# Iterate through all tables
for table in metadata.list_all_entities(entity=Table, limit=100):
    print(table.fullyQualifiedName)
    # Process each table...
import org.openmetadata.client.api.TablesApi;

TablesApi tablesApi = client.buildClient(TablesApi.class);
String afterCursor = null;

do {
    TableList page = tablesApi.listTables(null, 100, null, afterCursor, null);

    for (Table table : page.getData()) {
        System.out.println(table.getFullyQualifiedName());
        // Process each table...
    }

    afterCursor = page.getPaging().getAfter();
} while (afterCursor != null);
#!/bin/bash

after_cursor=""

while true; do
  # Build URL with optional cursor
  url="https://your-company.open-metadata.org/api/v1/tables?limit=100"
  if [ -n "$after_cursor" ]; then
    url="${url}&after=${after_cursor}"
  fi

  # Fetch page
  response=$(curl -s -X GET "$url" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json")

  # Process results
  echo "$response" | jq -r '.data[].fullyQualifiedName'

  # Get next cursor
  after_cursor=$(echo "$response" | jq -r '.paging.after // empty')

  # Exit if no more pages
  if [ -z "$after_cursor" ]; then
    break
  fi
done

Filtering with Pagination

Combine pagination with filters for efficient data retrieval:
Filtering
from metadata.ingestion.ometa.ometa_api import OpenMetadata
from metadata.generated.schema.entity.data.table import Table

metadata = OpenMetadata(config)

# List tables from a specific database
tables = metadata.list_entities(
    entity=Table,
    params={"database": "prod.analytics"},
    limit=50
)

for table in tables.entities:
    print(table.fullyQualifiedName)
# Filter tables by database
curl -X GET "https://your-company.open-metadata.org/api/v1/tables?database=prod.analytics&limit=50" \
  -H "Authorization: Bearer $TOKEN"

Include Fields

Control which fields are returned in the response using the fields parameter:
# Request specific fields
curl -X GET "https://your-company.open-metadata.org/api/v1/tables?fields=owner,tags,columns&limit=20" \
  -H "Authorization: Bearer $TOKEN"
Common field options for tables:
  • owner - Include owner information
  • tags - Include tags and classifications
  • columns - Include column definitions
  • followers - Include followers
  • tableConstraints - Include constraints
  • usageSummary - Include usage statistics

Best Practices

1

Use reasonable page sizes

Start with limit=50-100. Larger pages reduce API calls but increase memory usage.
2

Follow cursor pages sequentially

On cursor-paginated endpoints, always use the returned before and after cursors. Don’t try to construct cursor values manually.
3

Keep offset paging stable

On offset-paginated endpoints, keep filters and sort order fixed while incrementing offset predictably from one page to the next.
4

Handle empty results

Use the endpoint’s pagination signal to detect the end of results, such as a missing after cursor or an empty page.
5

Request only needed fields

Use the fields parameter to reduce response size and improve performance.
6

Implement retry logic

Handle transient errors gracefully when paginating through large datasets.
For finding specific resources, consider using the Search API instead of paginating through all results:
# Search is faster for finding specific resources
curl -X GET "https://your-company.open-metadata.org/api/v1/search/query?q=customers&index=table_search_index" \
  -H "Authorization: Bearer $TOKEN"

Search API

Learn about searching and filtering metadata