Skip to content
LogoLogo

Pagination

The Picked API paginates every list field that can return a large result. It uses a cursor, in the Relay-style pattern. This guide covers the connection pattern and shows how to move through a result.

Connection pattern

A paginated field returns a connection object with this shape:

type ExampleConnection {
  edges: [ExampleEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}
 
type ExampleEdge {
  cursor: String!
  node: Example!
}
 
type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}
FieldDescription
edgesAn ordered list of edges. Each edge holds a cursor and a node, and the node holds the data.
pageInfo.hasNextPagetrue when more results come after the last edge
pageInfo.hasPreviousPagetrue when results come before the first edge
pageInfo.startCursorThe cursor of the first edge on the current page
pageInfo.endCursorThe cursor of the last edge on the current page
totalCountThe number of items on every page together

Forward pagination with first and after

To move forward through the results, use two arguments. The first argument gives the page size. The after argument gives the cursor to start after.

First page

Leave the after argument out to read the first page:

query {
  organizations(input: { first: 10 }) {
    edges {
      cursor
      node {
        id
        name
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Next page

Pass the endCursor from the previous response as the after argument:

query {
  organizations(input: { first: 10, after: "cursor_from_previous_page" }) {
    edges {
      cursor
      node {
        id
        name
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

Check for more pages

Read the hasNextPage field before you ask for the next page:

  • hasNextPage: true — more results are available. Pass endCursor as the after argument of the next request.
  • hasNextPage: false — you read every result. Stop here.

Full paginated query example

This example reads every member of an organization, one page at a time:

# Page 1
query {
  organization(input: { slug: "my-company" }) {
    members(first: 20) {
      edges {
        cursor
        node {
          id
          userEmail
          role
          joinedAt
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
      totalCount
    }
  }
}

If pageInfo.hasNextPage is true, fetch the next page:

# Page 2
query {
  organization(input: { slug: "my-company" }) {
    members(first: 20, after: "cursor_from_page_1") {
      edges {
        cursor
        node {
          id
          userEmail
          role
          joinedAt
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
      totalCount
    }
  }
}

Continue until hasNextPage returns false.

Paginated fields

These fields in the schema return a connection type. They all take the first and after arguments:

Parent TypeFieldConnection Type
QueryorganizationsOrganizationConnection
UserorganizationsOrganizationConnection
UserinvitationsViewerInvitationConnection
OrganizationmembersOrganizationMemberConnection
OrganizationinvitationsOrganizationInvitationConnection
OrganizationprojectsProjectConnection
ProjectreportsProjectReportConnection

All of these fields accept the same first and after arguments and return the standard edges, pageInfo, and totalCount structure.

Tips

  • The default page size — the API applies a default limit when you leave first out. Set first yourself to make sure that each page has the size you expect.
  • A cursor is opaque — treat a cursor string as an opaque token. Do not parse it, build it, or change it. Pass it back exactly as the API gave it.
  • The order is stable — a connection returns its results in a stable order. The same cursor always points at the same position in the result.
  • Use them with other fields — you can use the pagination arguments together with other query fields. One request that reads an organization and the first page of its members is common, and it is efficient.