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
}
| Field | Description |
|---|---|
totalCount | Total number of items matching your query, regardless of page size |
nodes | The items on the current page — use this when you just need the data |
edges | Each item wrapped with its cursor — use this when you need cursors for individual items |
pageInfo | Contains hasNextPage, hasPreviousPage, startCursor, and endCursor |
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:
| Argument | Type | Description |
|---|---|---|
first | Int | Return the first N items (forward pagination). Max: 100. |
after | String | Return items after this cursor (forward pagination). |
last | Int | Return the last N items (backward pagination). Max: 100. |
before | String | Return 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
firstandlastat 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
- Error Handling — Handle API errors and partial responses
- Full Query Reference — All available queries with their pagination arguments