GraphQL conventions
This guide explains how to use our GraphQL API: how to fetch data, filter and paginate lists, authenticate, and perform mutations. It’s written for developers integrating with the API.
How to read our GraphQL examples
Every example in these docs has two names, and only one of them matters to the API:
query Document($ticketNum: String!) {
document(ticketNum: $ticketNum) {
...
}
}Document(afterquery/mutation) is the operation name; a label you choose, like a function name in your own code. The API does not use it to decide what to run. You can rename it to anything (or omit it) and the request behaves identically.document(inside the braces) is the field (query) name; this is what the API actually executes. It must match the schema exactly.
To avoid any ambiguity, every example in these docs names the operation after the field it executes: query Document { document(...) }, mutation UpdateQuote { updateQuote(...) }. When comparing examples against the schema or your API explorer, always use the field name inside the braces.
Queries
- Singular queries fetch a single object by identifier(s).
- Example:
document(ticketNum: String, ticketId: Int): Document
- Example:
- Plural queries return collections and accept filters and pagination.
- Example:
documents(filter: DocumentFilter): [Document] - Some lists use
filterwhile others use<entity>Filter(e.g.,users(userFilter: UserFilter)).
- Example:
Filtering
Most list queries accept a structured filter input. Filters are composable via AND/OR and support a rich set of operators.
- Operators by type
- String:
_not,_in,_not_in,_contains,_not_contains,_startsWith,_not_startsWith,_endsWith,_not_endsWith - Int/Float/Date/DateTime:
_not,_in,_not_in,_lt,_lte,_gt,_gte - Boolean:
_not
- String:
- Relations
- One-to-one filters:
field_is - One-to-many filters:
field_every,field_some,field_none
- One-to-one filters:
Example query with filters and pagination:
query Documents($filter: DocumentFilter, $limit: Int = 25, $offset: Int = 0) {
documents(filter: $filter, limit: $limit, offset: $offset) {
pageInfo {
total
hasNextPage
hasPreviousPage
perPage
totalPages
}
edges {
cursor
node {
id
ticketNum
pnr
createdAt
}
}
}
}Example variables:
{
"filter": {
"ticketNum_contains": "123",
"createdAt_gte": "2024-01-01T00:00:00Z",
"createdAt_lte": "2024-12-31T23:59:59Z"
},
"limit": 25,
"offset": 0
}Pagination
Lists return a connection-style shape with two parts:
edges: each item contains acursorand thenode(the record).pageInfo: includestotal,hasNextPage,hasPreviousPage,perPage,totalPages.
Request the next page by increasing offset by limit when hasNextPage is true. limit defaults to 10 and accepts a maximum of 100 rows per page.
query Documents($filter: DocumentFilter, $limit: Int = 25, $offset: Int!) {
documents(filter: $filter, limit: $limit, offset: $offset) {
pageInfo {
total
hasNextPage
}
edges {
cursor
node {
id
}
}
}
}Mutations
Mutations start with a verb and return a success boolean, a resource, or a response object.
Examples:
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
accessToken
refreshToken
expiresIn
}
}
mutation CancelQuote($ticketNum: String!) {
cancelQuote(ticketNum: $ticketNum)
}
mutation CreateUploadUrl($input: UploadUrlInput!) {
createUploadUrl(input: $input) {
uploadUrl
objectKey
expiresAt
}
}Error Handling
- GraphQL errors are returned in the
errorsarray of the response. Partial successes may include bothdataanderrors. - Authentication failures typically return an error response; ensure the
Authorizationheader is present and valid. - Validate inputs against the schema types to avoid input errors.
Best Practices
- Use server-side filters to minimize payloads and to keep pagination counts accurate.
- Always pass
limitto control page size. - Paginate incrementally: derive the next
offsetfrompageInfoand your currentlimit. - Compose filters with
AND/ORfor advanced use cases instead of multiple round-trips.
Updated 13 days ago