Pagination

Pagination

Overview

The Finale GraphQL API uses cursor-based pagination following the Relay connection specification. This provides efficient navigation through large datasets.

Pagination Arguments

All ViewConnection queries support these arguments:

  • first: Int - Return the first N items
  • last: Int - Return the last N items
  • after: String - Return items after this cursor
  • before: String - Return items before this cursor

PageInfo Object

Every ViewConnection returns a pageInfo object with:

pageInfo {
  hasNextPage      # Boolean: Are there more items after this page?
  hasPreviousPage  # Boolean: Are there items before this page?
  startCursor      # String: Cursor for first item in results
  endCursor        # String: Cursor for last item in results
}

Forward Pagination Pattern

To paginate forward through results:

# Page 1
query {
  orderViewConnection(first: 50) {
    edges {
      node {
        orderId
        orderDate
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

# Page 2 - Use endCursor from previous page
query {
  orderViewConnection(first: 50, after: "cursor-value-from-page-1") {
    edges {
      node {
        orderId
        orderDate
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Backward Pagination Pattern

To paginate backward:

query {
  orderViewConnection(last: 50, before: "cursor-value") {
    edges {
      node {
        orderId
        orderDate
      }
    }
    pageInfo {
      hasPreviousPage
      startCursor
    }
  }
}

Cursor Format

Cursors are opaque strings that encode pagination position. They are:

  • Base64-encoded JSON objects
  • Should be treated as opaque by clients
  • Valid only within the same query context
  • Not guaranteed to be stable across different queries

Example cursor value: eyJpZHgiOjEwfQ==

Best Practices

  1. Always check hasNextPage before requesting more pages
  2. Store cursors from pageInfo to navigate between pages
  3. Use consistent page size for predictable performance
  4. Don't decode cursors - treat them as opaque strings
  5. Combine with sorting for predictable pagination order

Complete Example

query GetProducts($cursor: String) {
  productViewConnection(
    first: 100
    after: $cursor
    sort: [{ field: "productId", mode: "asc" }]
  ) {
    edges {
      node {
        productId
        sku
        description
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}