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.

Queries

  • Singular queries fetch a single object by identifier(s).
    • Example: document(ticketNum: String, ticketId: Int): Document
  • Plural queries return collections and accept filters and pagination.
    • Example: documents(filter: DocumentFilter): [Document]
    • Some lists use filter while others use <entity>Filter (e.g., users(userFilter: UserFilter)).

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
  • Relations
    • One-to-one filters: field_is
    • One-to-many filters: field_every, field_some, field_none

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 a cursor and the node (the record).
  • pageInfo — includes total, hasNextPage, hasPreviousPage, perPage, totalPages.

Request the next page by increasing offset by limit when hasNextPage is true.

query MoreDocuments($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 errors array of the response. Partial successes may include both data and errors.
  • Authentication failures typically return an error response; ensure the Authorization header 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 limit to control page size.
  • Paginate incrementally: derive the next offset from pageInfo and your current limit.
  • Compose filters with AND/OR for advanced use cases instead of multiple round-trips.