Skip to content

GraphQL API

CDA ships full GraphQL bindings — query field definitions, query saved values, mutate cart values. Drop-in for Hyvä React storefronts, Magento PWA Studio, or any custom headless client.

The CDA fragments live in CustomFieldsGraphQl/etc/schema.graphqls. After install, they merge into your Magento GraphQL endpoint at /graphql.

What fields should this cart show on, say, the Shipping step? Use this:

{
cart(cart_id: "abc123") {
cda_applicable_fields(applies_to: "checkout_step:shipping") {
field_id
code
label
field_type
required
sort_order
placeholder
default_value
options {
value
label
}
validation_rules
conditional_logic
}
}
}

applies_to accepts any surface string: product_page, cart_page, checkout_step:shipping, checkout_step:payment, checkout_step:review, etc.

{
cart(cart_id: "abc123") {
cda_custom_field_values {
field_id
field_code
value
}
}
}
mutation {
setCartCustomFields(
input: {
cart_id: "abc123"
values: [
{ field_code: "engraving_text", value: "Veronica '26" }
{ field_code: "engraving_font", value: "script" }
{ field_code: "engraving_position", value: "front" }
]
}
) {
cart {
id
cda_custom_field_values {
field_code
value
}
}
}
}

The mutation overwrites any existing value for the same field_code on this cart and inserts new values. Values not in the input are NOT deleted — to clear a value, pass { field_code: "foo", value: "" }.

Excerpt from schema.graphqls:

type CdaCustomField {
field_id: Int!
code: String!
label: String!
field_type: String!
applies_to: String!
required: Boolean!
sort_order: Int!
placeholder: String
default_value: String
options: [CdaCustomFieldOption]
validation_rules: String
conditional_logic: String
}
type CdaCustomFieldOption {
value: String!
label: String!
}
type CdaCustomFieldValue {
field_id: Int!
field_code: String!
value: String
}
input CdaSetCartCustomFieldsInput {
cart_id: String!
values: [CdaCustomFieldValueInput!]!
}
input CdaCustomFieldValueInput {
field_code: String!
value: String
}
extend type Cart {
cda_custom_field_values: [CdaCustomFieldValue]
cda_applicable_fields(applies_to: String!): [CdaCustomField]
}
type Mutation {
setCartCustomFields(input: CdaSetCartCustomFieldsInput!): CartResult
}

Per-cart queries are tagged with cart_id cache identifiers so Magento’s GraphQL cache invalidates correctly when the cart is updated. Field-definition queries (cda_applicable_fields) are stable per surface and cache for the full Magento GraphQL TTL (default 1h).

GraphQL endpoint follows Magento’s standard rules:

  • Logged-in customer: pass Authorization: Bearer <customer-token>. The cart resolves to the customer’s bound cart automatically.
  • Guest cart: include cart_id in the query. The masked cart ID acts as the bearer — same model Magento uses for cart, addProductsToCart, etc.
  • Admin operations (creating field definitions): use the REST endpoints instead. GraphQL doesn’t expose admin field-management mutations.

GraphQL standard shape:

{
"errors": [
{
"message": "Field with code \"foo\" not found.",
"extensions": {
"category": "graphql-no-such-entity"
}
}
]
}

Common error categories:

  • graphql-no-such-entity — field or cart doesn’t exist
  • graphql-input — malformed input variables
  • graphql-authorization — missing or invalid token

For Hyvä React Checkout storefronts (or any TypeScript/React client), you’d typically use Apollo Client or urql with the generated TypeScript types. Generate types with graphql-codegen pointing at your store’s /graphql endpoint after CDA is installed — the CdaCustomField types will appear in the generated schema.