Skip to main content

Overview

The Garnet API supports two pagination styles:
  1. Offset-based pagination - Traditional page numbers (used in most endpoints)
  2. Cursor-based pagination - Efficient pagination for large datasets (used in agent and profile listings)

Offset-Based Pagination

PageArgs

Request parameters for offset-based pagination.
type PageArgs struct {
    Page    *int `json:"page,omitempty"`    // Page number (1-based)
    PerPage *int `json:"perPage,omitempty"` // Items per page
}

Paginator

Generic paginated response wrapper.
type Paginator[T any] struct {
    Data          []T           `json:"data"`
    PaginatorInfo PaginatorInfo `json:"paginatorInfo"`
}
data
T[]
required
Array of items for the current page
paginatorInfo
PaginatorInfo
required
Pagination metadata

PaginatorInfo

Pagination metadata for offset-based pagination.
type PaginatorInfo struct {
    Total       int  `json:"total"`       // Total number of items
    PerPage     int  `json:"perPage"`     // Items per page
    CurrentPage int  `json:"currentPage"` // Current page (1-based)
    LastPage    int  `json:"lastPage"`    // Last page number
    From        *int `json:"from,omitempty"` // First item index (1-based)
    To          *int `json:"to,omitempty"`   // Last item index (1-based)
}
total
int
required
Total number of items across all pages
perPage
int
required
Number of items per page
currentPage
int
required
Current page number (1-based)
lastPage
int
required
Last available page number
from
int
Index of first item on current page (1-based). Null if page is empty.
to
int
Index of last item on current page (1-based). Null if page is empty.

Example Usage

// Request second page with 50 items per page
page := 2
perPage := 50
args := types.PageArgs{
    Page:    &page,
    PerPage: &perPage,
}

// Response example
response := types.Paginator[types.Issue]{
    Data: []types.Issue{
        // 50 issues...
    },
    PaginatorInfo: types.PaginatorInfo{
        Total:       250,
        PerPage:     50,
        CurrentPage: 2,
        LastPage:    5,
        From:        intPtr(51),
        To:          intPtr(100),
    },
}

Helper Functions

// DecodePageArgs extracts PageArgs from URL query parameters
func DecodePageArgs(v url.Values) PageArgs

// Example: ?page=2&perPage=50

// CalculatePaginatorInfo calculates pagination metadata
func CalculatePaginatorInfo(dataLen, total int, page, perPage *int) PaginatorInfo

Cursor-Based Pagination

CursorPageArgs

Request parameters for cursor-based pagination.
type CursorPageArgs struct {
    First  *uint   // Get first N items
    After  *string // Cursor to start after
    
    Last   *uint   // Get last N items
    Before *string // Cursor to end before
}
Note: Cannot specify both first and last in the same request.

Methods

  • IsBackwards() bool - Returns true if paginating backwards (using last or before)
  • Validator() *validator.Validator - Returns validator for the args

CursorPage

Generic cursor-based paginated response.
type CursorPage[T any] struct {
    Items    []T            `json:"items"`
    PageInfo CursorPageInfo `json:"pageInfo"`
}
items
T[]
required
Array of items for the current page
pageInfo
CursorPageInfo
required
Cursor pagination metadata

CursorPageInfo

Metadata for cursor-based pagination.
type CursorPageInfo struct {
    TotalCount      uint    `json:"totalCount"`
    EndCursor       *string `json:"endCursor"`
    HasNextPage     bool    `json:"hasNextPage"`
    StartCursor     *string `json:"startCursor"`
    HasPreviousPage bool    `json:"hasPreviousPage"`
}
totalCount
uint
required
Total number of items available
endCursor
string
Cursor for the last item on this page. Use with after to get the next page.
hasNextPage
bool
required
Whether there are more items after this page
startCursor
string
Cursor for the first item on this page. Use with before to get the previous page.
hasPreviousPage
bool
required
Whether there are items before this page

Example Usage

// First page: get first 50 agents
first := uint(50)
args := types.CursorPageArgs{
    First: &first,
}

// Response
response := types.CursorPage[types.Agent]{
    Items: []types.Agent{
        // 50 agents...
    },
    PageInfo: types.CursorPageInfo{
        TotalCount:      250,
        EndCursor:       stringPtr("cursor_abc123"),
        HasNextPage:     true,
        StartCursor:     stringPtr("cursor_xyz789"),
        HasPreviousPage: false,
    },
}

// Next page: use endCursor as after
args = types.CursorPageArgs{
    First: &first,
    After: response.PageInfo.EndCursor,
}

Validation Rules

Cursor pagination has built-in validation:
  • first must be greater than 0 and not exceed 200
  • last must be greater than 0 and not exceed 200
  • Cannot specify both first and last in the same request

Sorting

Sort

Sorting parameters for paginated results.
type Sort struct {
    Field string `json:"field"` // Field to sort by
    Order Order  `json:"order"` // Sort order
}

Order

Sort order direction.
type Order string

const (
    OrderAsc  Order = "asc"  // Ascending order
    OrderDesc Order = "desc" // Descending order
)

Methods

  • String() string - Returns string representation
  • Validate() error - Validates the order is valid

Helper Functions

// DecodeSort extracts Sort from URL query parameters
func DecodeSort(v url.Values) *Sort

// Example: ?sort.field=created_at&sort.order=desc

Example Usage

// Sort by creation date, newest first
sort := types.Sort{
    Field: "created_at",
    Order: types.OrderDesc,
}

if err := sort.Order.Validate(); err != nil {
    // Handle invalid order
}

When to Use Each Style

Use Offset-Based Pagination When:

  • Users need to jump to specific pages
  • Total count and page numbers are important
  • Dataset is relatively small (< 10,000 items)
  • Used in: Issues, Events, Webhooks, Project Settings

Use Cursor-Based Pagination When:

  • Dataset is very large
  • Real-time data with frequent inserts
  • Only need forward/backward navigation
  • Better performance for deep pagination
  • Used in: Agents, Profiles

Constants

const (
    DefaultPageSize = 20  // Default items per page for offset pagination
    maxPageSize     = 200 // Maximum items per page for cursor pagination
)

Build docs developers (and LLMs) love