GraphQL API

Mutation Patterns

How mutations work in the Viio GraphQL API — modifying data, input arguments, and handling responses.

Last updated

Mutations are used to create, update, or delete data. Unlike queries, mutations can have side effects and modify server-side state.

Structure

A mutation call looks similar to a query, but uses the mutation keyword:

mutation {
  createProcurementCase(input: { state: PRE, name: "Slack renewal" }) {
    case {
      id
      name
      state
    }
    errors {
      ... on ProcurementCaseCreationError {
        message
      }
    }
  }
}

Input Arguments

Mutations accept an input argument containing the fields to set. Some mutations also accept a where argument to scope the operation to matching records.

The exact input type for each mutation is documented with its product area in the schema reference.

Using Variables

For dynamic values, use GraphQL variables instead of inline arguments:

mutation CreateCase($input: CreateProcurementCaseInput!) {
  createProcurementCase(input: $input) {
    case {
      id
      name
      state
    }
    errors {
      ... on ProcurementCaseCreationError {
        message
      }
    }
  }
}

Variables are passed as a separate JSON object:

{
  "input": {
    "state": "PRE",
    "name": "Slack renewal",
    "deadline": "2025-06-01",
    "baselineType": "LAST_YEAR_COST",
    "baselinePrice": 12000.00
  }
}

Response Payloads

Mutations return a payload type that contains the result and an errors field. Always check errors in the response — a non-null payload does not guarantee the operation succeeded.

mutation UpdateCase($input: UpdateProcurementCaseInput!) {
  updateProcurementCase(input: $input) {
    case {
      id
      name
      state
      savingAmount
      savingPercentage
    }
    errors {
      ... on ProcurementCaseCompletedError {
        message
      }
      ... on ProcurementCaseNotFoundError {
        message
      }
    }
  }
}

Bulk Operations with Filters

Some mutations apply changes to multiple records at once using a where filter. For example, to change the state of vendors matching a filter:

mutation ChangeState($input: ChangeVendorsStateInput!, $where: VendorDiscoveryFilterInput) {
  changeVendorsState(input: $input, where: $where) {
    updatedCount
    errors {
      ... on ChangeVendorsStateError {
        message
      }
    }
  }
}
{
  "input": { "state": "SANCTIONED" },
  "where": { "vendor": { "name": { "contains": "Acme" } } }
}