Schema
Every type the GraphQL API serves, generated from the code that answers it. Type names link to their definition. Tools read the plain file: /schema.graphql. To run a query, open the GraphQL explorer.
type Query { product(cprcode: ID!, branchCode: ID = null): Product products(filter: ProductFilter = null, branchCode: ID = null, first: Int! = 20, after: String = null): ProductConnection! categories: [CategoryCount!]! branches: [FulfilmentBranch!]! search(query: String!, mode: SearchMode! = SEMANTIC, limit: Int! = 20, branchCode: ID = null): [SearchHit!]! searchSuggest(query: String!, limit: Int! = 30): [String!]! inventory(branchCode: ID!, cprcodes: [ID!] = null): [InventoryLevel!]!
type Mutation { """ A personal key that lets the signed-in shopper's own AI client shop as them on Villa's direct channel. """ personalKeyCreate(label: String! = "Personal key"): PersonalKeyCreated! personalKeyRevoke(keyId: ID!): Boolean! basketAdd(input: BasketAddInput!): BasketPayload! basketRemove(input: BasketRemoveInput!): BasketPayload! basketSetQuantity(input: BasketSetQuantityInput!): BasketPayload! basketSetBranch(branchCode: ID!): BasketPayload! guestSession: GuestSessionPayload! basketEmpty: BasketPayload! orderCreate(input: OrderCreateInput = null): OrderPayload! quote(input: QuoteInput!): QuotePayload! quoteApplyCoupon(input: QuoteInput!): QuotePayload! paymentLinkCreate(orderId: ID!): PaymentLinkPayload! paymentStart(input: PaymentStartInput!): PaymentPayload! }
input AddressInput { lat: Float = null lon: Float = null postcode: String = null address: String = null firstName: String = null lastName: String = null phone: String = null email: String = null }
type Basket { basketId: ID! ownerId: ID! branchCode: ID! lines: [BasketLine!]! }
input BasketAddInput { cprcode: ID! quantity: Int! = 1 branchCode: ID = null attribution: BasketAttributionInput = null }
""" Which search put this product in the basket (the latest attributed add wins). """ type BasketAttribution { searchId: String! position: Int! source: String! }
""" Which search put the product in the basket. searchId is opaque, at most 128 characters; position is 1-based, 0 means unknown; source is search, suggestion (auto-complete picks too) or browse. """ input BasketAttributionInput { searchId: String! position: Int! = 0 source: String! = "search" }
""" One basket change or placed order line, without the shopper (vca-f9c.3). """ type BasketEvent { """add, quantity, remove or order""" type: String!
type BasketEventPage { nodes: [BasketEvent!]!
type BasketLine { cprcode: ID! quantity: Int! attribution: BasketAttribution product: Product }
type BasketPayload { basket: Basket userErrors: [UserError!]! }
input BasketRemoveInput { cprcode: ID! }
input BasketSetQuantityInput { cprcode: ID! quantity: Int! attribution: BasketAttributionInput = null }
type Category { l1: String l2: String l3: String }
type CategoryCount { name: String! count: Int! }
type FulfilmentBranch { branchCode: ID! name: String alcoholLicensed: Boolean deliveryAvailable: Boolean nameTh: String lat: Float lon: Float address: String province: String postcode: String phone: String distanceKm: Float }
input FulfilmentResolveInput { lat: Float = null lon: Float = null postcode: String = null }
enum FulfilmentType { DELIVERY PICKUP }
type GuestSessionPayload { token: String ownerId: String expiresAt: String userErrors: [UserError!]! }
type InventoryLevel { cprcode: ID! branchCode: ID! listable: Boolean! sellableQty: Int ibCfQty: Int qtySource: InventoryQtySource }
enum InventoryQtySource { NEW_IB_VS_STOCK_CV IB_CF_QTY }
""" The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf). """ scalar JSON @specifiedBy(url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf")
type MerchantEarnings { partnerId: ID! currency: String! royaltyRate: Float! orders: Int! paidOrders: Int! paidSales: Float! royaltyAccrued: Float! royaltyPending: Float! recent: [MerchantOrder!]! }
type MerchantOrder { orderId: ID! createdAt: String grandTotal: Float! paid: Boolean! royalty: Royalty lineCount: Int! orderSource: String }
type Money { amount: Float! currency: String! branchCode: ID source: PriceSource!
type Order { orderId: ID! ownerId: ID branchCode: ID grandTotal: Float isPaid: Boolean specialComment: String lines: [OrderLine!]! payment: OrderPayment shipping: OrderShipping status: String createdAt: String orderSource: String sandbox: Boolean subTotal: Float deliveryFee: Float totalDiscount: Float paymentLink: PaymentLink royalty: Royalty fulfilmentStatus: String deliveredAt: String }
type OrderConnection { nodes: [Order!]! pageInfo: PageInfo! }
input OrderCreateInput { branchCode: ID = null specialComment: String = null lines: [OrderLineInput!] = null shippingType: String! = "PICKUP" scheduleMode: String! = "REGULAR" address: AddressInput = null couponCodes: [String!] = null }
type OrderLine { cprcode: ID! productName: String quantity: Int! price: Float rowTotal: Float }
input OrderLineInput { cprcode: ID! quantity: Int! }
type OrderPayload { order: Order userErrors: [UserError!]! }
type OrderPayment { isPaid: Boolean status: String grandTotal: Float method: String }
type OrderSchedule { mode: String dateTime: String pickingStatus: String deliveryFee: Float }
type OrderShipping { fulfilmentType: FulfilmentType schedules: [OrderSchedule!] }
type PageInfo { hasNextPage: Boolean! endCursor: String }
type PaymentLink { url: String! expiresAt: Int! amount: Float! currency: String! provider: String! }
type PaymentLinkPayload { paymentLink: PaymentLink userErrors: [UserError!]! }
type PaymentPayload { payment: PaymentSession userErrors: [UserError!]! }
type PaymentSession { orderId: ID! amountThb: Float! currency: String! publicKey: String merchantId: String sdkUrl: String redirectUrl: String available: Boolean! }
input PaymentStartInput { orderId: ID! basketId: ID = null callbackUrl: String = null }
type PersonalKey { keyId: ID! label: String!
type PersonalKeyCreated { """the whole key — shown once, never again""" key: String personalKey: PersonalKey userErrors: [UserError!]! }
enum PriceSource { BRANCH_FEED DETAIL_FALLBACK }
type Product { cprcode: ID! nameEn: String nameTh: String brandEn: String sizeDesc: String countryEn: String barcode: String category: Category imageUrl: String availStore: [ID!] price: Money inventory: InventoryLevel }
type ProductConnection { nodes: [Product!]! pageInfo: PageInfo! totalCount: Int }
input ProductFilter { query: String = null l1: String = null l2: String = null l3: String = null alcoholOnly: Boolean! = false activeOnly: Boolean = null onlineOnly: Boolean! = true pricedOnly: Boolean! = false }
type Quote { quoteId: ID! grandTotal: Float! currency: String! branchCode: ID expiresInSeconds: Int! raw: JSON subTotal: Float deliveryFee: Float discountedDeliveryFee: Float shippingDiscount: Float expressShippingCost: Float totalDiscount: Float lines: [QuoteLine!]! couponCodes: [String!]! failedCoupons: JSON }
input QuoteInput { branchCode: ID = null lines: [OrderLineInput!] = null shippingType: String! = "PICKUP" couponCodes: [String!] = null scheduleMode: String! = "REGULAR" address: AddressInput = null }
type QuoteLine { cprcode: ID! productName: String quantity: Int! price: Float rowTotal: Float discountedRowTotal: Float }
type QuotePayload { quote: Quote userErrors: [UserError!]! }
type Royalty { rate: Float! base: Float! amount: Float! currency: String!
enum SearchMode { AUTOCOMPLETE SEMANTIC }
type UserError { code: String! message: String! field: String }