Skip to main content

Pagination

Most list queries in the Certificate Manager GraphQL API return paginated results using the Connection pattern — a standard GraphQL approach for cursor-based pagination. This page explains how it works and how to page through results.


The Connection Pattern

Every paginated query returns a Connection type (e.g., CertificateConnection, CloudProviderConnection). Connection types always have the same structure:

type CertificateConnection {
totalCount: Int # Total number of items across all pages
nodes: [Certificate!] # The items on this page
edges: [CertificateEdge!] # Items with their cursors
pageInfo: PageInfo # Pagination metadata
}
FieldDescription
totalCountTotal number of items matching your query, regardless of page size
nodesThe items on the current page — use this when you just need the data
edgesEach item wrapped with its cursor — use this when you need cursors for individual items
pageInfoContains hasNextPage, hasPreviousPage, startCursor, and endCursor
nodes vs edges

Use nodes for simplicity. Use edges when you need the cursor for a specific item (e.g., to start pagination from that exact position).


Pagination Arguments

All paginated queries accept four arguments:

ArgumentTypeDescription
firstIntReturn the first N items (forward pagination). Max: 100.
afterStringReturn items after this cursor (forward pagination).
lastIntReturn the last N items (backward pagination). Max: 100.
beforeStringReturn items before this cursor (backward pagination).

Defaults: If you don't provide any pagination arguments, most queries return the first 10 items.


Forward Pagination

To page forward through results, use first and after:

Page 1 — Get the first 10 items

query Page1 {
certificates(first: 10) {
totalCount
nodes {
name
fingerprint
}
pageInfo {
hasNextPage
endCursor
}
}
}

Response:

{
"data": {
"certificates": {
"totalCount": 142,
"nodes": [ "... first 10 certificates ..." ],
"pageInfo": {
"hasNextPage": true,
"endCursor": "Y3Vyc29yOjk="
}
}
}
}

Page 2 — Pass the endCursor from page 1

query Page2 {
certificates(first: 10, after: "Y3Vyc29yOjk=") {
totalCount
nodes {
name
fingerprint
}
pageInfo {
hasNextPage
endCursor
}
}
}

Continue until hasNextPage is false.


Backward Pagination

To page backward from the end, use last and before:

query LastPage {
certificates(last: 10) {
nodes {
name
fingerprint
}
pageInfo {
hasPreviousPage
startCursor
}
}
}

Then pass startCursor as the before argument to go to the previous page.


Complete Pagination Loop

Here's a full example in JavaScript that pages through all certificates:

async function getAllCertificates(apiKey) {
const certificates = [];
let hasNextPage = true;
let cursor = null;

while (hasNextPage) {
const query = `
query ListCerts($after: String) {
certificates(first: 100, after: $after) {
nodes {
id
name
fingerprint
status
}
pageInfo {
hasNextPage
endCursor
}
}
}
`;

const response = await fetch('https://api.venafi.cloud/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'tppl-api-key': apiKey,
},
body: JSON.stringify({
query,
variables: { after: cursor },
}),
});

const { data } = await response.json();
certificates.push(...data.certificates.nodes);
hasNextPage = data.certificates.pageInfo.hasNextPage;
cursor = data.certificates.pageInfo.endCursor;
}

return certificates;
}

Combining Pagination with Filters

Many queries support both pagination and filtering. Pagination arguments always work alongside filters:

query FilteredCertificates {
searchCertificates(
first: 20
filter: { status: ACTIVE }
) {
totalCount
nodes {
name
status
validity { notAfter }
}
pageInfo {
hasNextPage
endCursor
}
}
}

The totalCount reflects the filtered total, not all certificates.


Important Details

  • Max page size: Most queries cap first and last at 100. Requesting more than the max returns an error.
  • Default page size: If you omit first/last, most queries default to 10 items.
  • Forward wins: If you supply both forward (first/after) and backward (last/before) arguments, forward pagination is used.
  • Cursors are opaque: Cursor strings are implementation details — don't parse or construct them. Just pass them back as-is.
  • Cursors are stable: A cursor always points to the same position in the result set, even if items are added or removed.

Next Steps