@spindlecommerce/storefront-client 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/schema.graphql ADDED
@@ -0,0 +1,1453 @@
1
+ """
2
+ Run the operation in a channel, locale and currency. Overrides the X-Channel, Accept-Language and X-Currency headers.
3
+ """
4
+ directive @inContext(
5
+ """Channel code, e.g. eu."""
6
+ channel: String
7
+
8
+ """ISO 4217 code, e.g. GBP."""
9
+ currency: String
10
+
11
+ """BCP 47 locale, e.g. de-DE."""
12
+ locale: String
13
+ ) on MUTATION | QUERY | SUBSCRIPTION
14
+
15
+ type AcceptedPayload {
16
+ accepted: Boolean
17
+ }
18
+
19
+ type Address {
20
+ city: String
21
+ company: String
22
+ countryCode: CountryCode
23
+ firstName: String
24
+ lastName: String
25
+ line1: String
26
+ line2: String
27
+ phone: String
28
+ postalCode: String
29
+ region: String
30
+ regionCode: String
31
+ }
32
+
33
+ """
34
+ An address as far as it is filled in: the country, and any of the rest. Blank fields are left out.
35
+ """
36
+ input AddressDraftInput {
37
+ city: String
38
+ company: String
39
+ countryCode: CountryCode!
40
+ firstName: String
41
+ lastName: String
42
+ line1: String
43
+ line2: String
44
+ phone: String
45
+ postalCode: String
46
+ region: String
47
+ regionCode: String
48
+ }
49
+
50
+ input AddressInput {
51
+ city: String!
52
+ company: String
53
+ countryCode: CountryCode!
54
+ firstName: String!
55
+ lastName: String!
56
+ line1: String!
57
+ line2: String
58
+ phone: String
59
+ postalCode: String!
60
+ region: String
61
+ regionCode: String
62
+ }
63
+
64
+ type AppliedDiscount {
65
+ amount: Money
66
+ couponCode: String
67
+ name: String
68
+ }
69
+
70
+ type AttributeDefinition implements Node {
71
+ code: String
72
+ id: ID!
73
+ isFilterable: Boolean
74
+ isLocalized: Boolean
75
+ isRequired: Boolean
76
+ isSearchable: Boolean
77
+ label: String
78
+ options: [AttributeOption!]
79
+ position: Int
80
+ type: AttributeType
81
+ unit: String
82
+ }
83
+
84
+ input AttributeFilterInput {
85
+ code: String!
86
+ values: [String!]!
87
+ }
88
+
89
+ type AttributeOption {
90
+ code: String
91
+ label: String
92
+ swatch: String
93
+ }
94
+
95
+ enum AttributeType {
96
+ BOOLEAN
97
+ DATE
98
+ MULTISELECT
99
+ NUMBER
100
+ RICH_TEXT
101
+ SELECT
102
+ TEXT
103
+ }
104
+
105
+ type AuthenticationError implements Error {
106
+ code: ErrorCode
107
+ message: String
108
+ }
109
+
110
+ """
111
+ Guest carts are addressed by their unguessable id; a customer's cart is visible only to that customer.
112
+ """
113
+ type Cart implements Node {
114
+ availablePaymentMethods: [PaymentMethodOption!]
115
+
116
+ """
117
+ Rates for the current contents, once the shipping address has a country and postal code. Carriers' rates need the whole address.
118
+ """
119
+ availableShippingMethods: [ShippingRate!]
120
+
121
+ """
122
+ The cart's own billing address, or else the shipping address (billingSameAsShipping). As far as it is filled in.
123
+ """
124
+ billingAddress: Address
125
+
126
+ """
127
+ True while the cart has no billing address of its own and bills to the shipping address, the default.
128
+ """
129
+ billingSameAsShipping: Boolean
130
+ checkoutReady: Boolean
131
+ cost: CartCost
132
+ coupons: [CartCoupon!]
133
+ createdAt: DateTime
134
+ currencyCode: CurrencyCode
135
+ customer: Customer
136
+ discounts: [AppliedDiscount!]
137
+ email: EmailAddress
138
+ id: ID!
139
+
140
+ """False once the cart became an order."""
141
+ isOpen: Boolean
142
+ lines: [CartLine!]
143
+ locale: LocaleCode
144
+
145
+ """Empty when the cart can be checked out."""
146
+ missing: [CartRequirement!]
147
+ order: Order
148
+ requiresShipping: Boolean
149
+ selectedPaymentMethod: PaymentMethodOption
150
+
151
+ """The shopper's choice while it is available, else the cheapest rate."""
152
+ selectedShippingMethod: ShippingRate
153
+
154
+ """As far as it is filled in."""
155
+ shippingAddress: Address
156
+ totalQuantity: Int
157
+ updatedAt: DateTime
158
+
159
+ """Increments on every change."""
160
+ version: Int
161
+ }
162
+
163
+ """Exactly one: an address, or a saved address of the signed-in customer."""
164
+ input CartAddressInput @oneOf {
165
+ address: AddressInput
166
+ customerAddressId: ID
167
+ }
168
+
169
+ union CartAssignToCustomerResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
170
+
171
+ input CartBillingAddressInput @oneOf {
172
+ address: AddressInput
173
+ customerAddressId: ID
174
+ sameAsShipping: Boolean
175
+ }
176
+
177
+ union CartBillingAddressSetResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
178
+
179
+ """
180
+ Totals from the pricing pipeline: subtotal → discounts → shipping → shipping discount → tax → total.
181
+ """
182
+ type CartCost {
183
+ """Line discounts plus shipping discount."""
184
+ discountTotal: Money
185
+ pricesIncludeTax: Boolean
186
+
187
+ """After shipping discounts."""
188
+ shipping: Money
189
+ shippingDiscount: Money
190
+ subtotal: Money
191
+ tax: Money
192
+ taxLines: [TaxLine!]
193
+ total: Money
194
+ }
195
+
196
+ type CartCoupon {
197
+ applied: Boolean
198
+ code: String
199
+
200
+ """Why the coupon currently gives no discount."""
201
+ reason: String
202
+ }
203
+
204
+ union CartCouponApplyResult = AuthenticationError | CartPayload | CouponNotApplicableError | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
205
+
206
+ union CartCouponRemoveResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
207
+
208
+ input CartCreateInput {
209
+ email: EmailAddress
210
+ lines: [CartLineInput!]
211
+ }
212
+
213
+ union CartCreateResult = AuthenticationError | CartPayload | InsufficientStockError | NotFoundError | PermissionDeniedError | ValidationError
214
+
215
+ union CartEmailUpdateResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
216
+
217
+ type CartLine {
218
+ compareAtUnitPrice: Money
219
+ discount: Money
220
+ id: ID
221
+ issue: CartLineIssue
222
+ name: String
223
+ product: Product
224
+ quantity: Int
225
+ quantityAvailable: Int
226
+ subtotal: Money
227
+ tax: Money
228
+ total: Money
229
+ unitPrice: Money
230
+ variant: ProductVariant
231
+ }
232
+
233
+ """
234
+ One product variant, by id or SKU. Works the same for every product type.
235
+ """
236
+ input CartLineInput {
237
+ quantity: Int!
238
+ sku: String
239
+ variantId: ID
240
+ }
241
+
242
+ type CartLineIssue {
243
+ code: CartLineIssueCode
244
+ message: String
245
+ }
246
+
247
+ enum CartLineIssueCode {
248
+ INSUFFICIENT_STOCK
249
+ NO_PRICE
250
+ OUT_OF_STOCK
251
+ UNAVAILABLE
252
+ }
253
+
254
+ input CartLineUpdateInput {
255
+ lineId: ID!
256
+
257
+ """0 removes the line."""
258
+ quantity: Int!
259
+ }
260
+
261
+ union CartLinesAddResult = AuthenticationError | CartPayload | InsufficientStockError | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
262
+
263
+ union CartLinesRemoveResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
264
+
265
+ union CartLinesUpdateResult = AuthenticationError | CartPayload | InsufficientStockError | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
266
+
267
+ type CartNotReadyError implements Error {
268
+ code: ErrorCode
269
+
270
+ """
271
+ The same, field by field. Paths follow the storefront's cartUpdate input: ["shippingAddress", "address", "postalCode"] is a postal code still to give.
272
+ """
273
+ fieldErrors: [FieldError!]
274
+ message: String
275
+ missing: [CartRequirement!]
276
+ }
277
+
278
+ type CartPayload {
279
+ cart: Cart
280
+ }
281
+
282
+ union CartPaymentMethodSetResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
283
+
284
+ """
285
+ The payment the cart's provider prepared for its current total, for the provider's own payment form in the browser.
286
+ """
287
+ type CartPaymentSession {
288
+ amount: Money
289
+
290
+ """
291
+ Provider data for the browser, e.g. Stripe's { clientSecret, publishableKey }.
292
+ """
293
+ clientData: JSON
294
+ methodCode: String
295
+ provider: String
296
+ }
297
+
298
+ union CartPaymentSessionCreateResult = AuthenticationError | CartNotReadyError | CartPaymentSessionPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
299
+
300
+ type CartPaymentSessionPayload {
301
+ session: CartPaymentSession
302
+ }
303
+
304
+ """Something a cart still needs before it can be checked out."""
305
+ enum CartRequirement {
306
+ BILLING_ADDRESS
307
+ EMAIL
308
+ LINES
309
+
310
+ """A line is unavailable, unpriced or short on stock."""
311
+ LINE_ISSUES
312
+ PAYMENT_METHOD
313
+ SHIPPING_ADDRESS
314
+ SHIPPING_METHOD
315
+ }
316
+
317
+ union CartShippingAddressSetResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
318
+
319
+ union CartShippingMethodSetResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
320
+
321
+ """
322
+ Exactly one: an address, complete or not, or a saved address of the signed-in customer.
323
+ """
324
+ input CartUpdateAddressInput @oneOf {
325
+ address: AddressDraftInput
326
+ customerAddressId: ID
327
+ }
328
+
329
+ """
330
+ Exactly one: an address, complete or not, a saved address of the signed-in customer, or sameAsShipping: true to bill to the shipping address.
331
+ """
332
+ input CartUpdateBillingAddressInput @oneOf {
333
+ address: AddressDraftInput
334
+ customerAddressId: ID
335
+ sameAsShipping: Boolean
336
+ }
337
+
338
+ """
339
+ Checkout details to set, in any combination. Omitted fields stay as they are; null clears one.
340
+ """
341
+ input CartUpdateInput {
342
+ billingAddress: CartUpdateBillingAddressInput
343
+
344
+ """
345
+ Switch to another of the channel's currencies (Channel.currencies). Prices, shipping and tax follow; a chosen shipping or payment method no longer offered is dropped.
346
+ """
347
+ currencyCode: CurrencyCode
348
+ email: EmailAddress
349
+
350
+ """
351
+ Move the cart to another of its channel's languages (Channel.locales): line names, and the emails for its order.
352
+ """
353
+ locale: LocaleCode
354
+
355
+ """A code from availablePaymentMethods."""
356
+ paymentMethodCode: String
357
+ shippingAddress: CartUpdateAddressInput
358
+
359
+ """
360
+ A code from availableShippingMethods. Null goes back to the cheapest rate.
361
+ """
362
+ shippingMethodCode: String
363
+ }
364
+
365
+ union CartUpdateResult = AuthenticationError | CartPayload | InvalidStateError | NotFoundError | PermissionDeniedError | ValidationError
366
+
367
+ type Category implements Node {
368
+ """Root first, for breadcrumbs. Excludes this category."""
369
+ ancestors: [Category!]
370
+ children: [Category!]
371
+ depth: Int
372
+ description: String
373
+ id: ID!
374
+ name: String
375
+ parent: Category
376
+
377
+ """Slugs from the root, e.g. "men/mens-shirts"."""
378
+ path: String
379
+ position: Int
380
+ products(
381
+ after: String
382
+ before: String
383
+ filter: ProductFilter
384
+ first: Int
385
+ last: Int
386
+
387
+ """Full-text search with prefix matching, e.g. "trail run"."""
388
+ query: String
389
+
390
+ """
391
+ Defaults to RELEVANCE with a query, then to FEATURED in a category's listing, otherwise NEWEST.
392
+ """
393
+ sort: ProductSortInput
394
+ ): ProductConnection
395
+
396
+ """
397
+ This category's own sections, to render with the category as data where its template places the category sections component. Null when it has none. Drafts appear only with a preview token.
398
+ """
399
+ sections: Page
400
+ slug: String
401
+
402
+ """
403
+ The page builder template for this category's page: the one assigned to the category, else the default. Render its content with the category as data. Null means none: use your built-in layout. Drafts appear only with a preview token.
404
+ """
405
+ template: Page
406
+ }
407
+
408
+ type Channel implements Node {
409
+ code: String
410
+
411
+ """Countries this channel sells to."""
412
+ countries: [Country!]
413
+ currencies: [CurrencyCode!]
414
+ defaultCurrency: CurrencyCode
415
+ defaultLocale: LocaleCode
416
+ id: ID!
417
+ locales: [LocaleCode!]
418
+ name: String
419
+ pricesIncludeTax: Boolean
420
+ }
421
+
422
+ type CheckoutPayload {
423
+ order: Order
424
+ }
425
+
426
+ union CheckoutPlaceOrderResult = AuthenticationError | CartNotReadyError | CheckoutPayload | InsufficientStockError | InvalidStateError | NotFoundError | PaymentDeclinedError | PermissionDeniedError | ValidationError
427
+
428
+ type Country {
429
+ code: CountryCode
430
+
431
+ """In the request locale."""
432
+ name: String
433
+ }
434
+
435
+ """ISO 3166-1 alpha-2 country code, e.g. DE."""
436
+ scalar CountryCode
437
+
438
+ type CouponNotApplicableError implements Error {
439
+ code: ErrorCode
440
+ couponCode: String
441
+ message: String
442
+ reason: String
443
+ }
444
+
445
+ """ISO 4217 currency code, e.g. USD."""
446
+ scalar CurrencyCode
447
+
448
+ type Customer implements Node {
449
+ acceptsMarketing: Boolean
450
+
451
+ """The customer's open cart in the current channel."""
452
+ activeCart: Cart
453
+ addresses: [CustomerAddress!]
454
+ createdAt: DateTime
455
+
456
+ """YYYY-MM-DD."""
457
+ dateOfBirth: String
458
+ defaultBillingAddress: CustomerAddress
459
+ defaultShippingAddress: CustomerAddress
460
+ email: EmailAddress
461
+ firstName: String
462
+ id: ID!
463
+ lastName: String
464
+
465
+ """Newest first."""
466
+ orders(after: String, before: String, first: Int, last: Int, status: OrderStatus): CustomerOrdersConnection
467
+ phone: String
468
+ }
469
+
470
+ type CustomerAddress implements Node {
471
+ address: Address
472
+ id: ID!
473
+ isDefaultBilling: Boolean
474
+ isDefaultShipping: Boolean
475
+ }
476
+
477
+ union CustomerAddressCreateResult = AuthenticationError | CustomerAddressPayload | NotFoundError | PermissionDeniedError | ValidationError
478
+
479
+ union CustomerAddressDeleteResult = AuthenticationError | DeletePayload | NotFoundError | PermissionDeniedError | ValidationError
480
+
481
+ input CustomerAddressInput {
482
+ address: AddressInput!
483
+ isDefaultBilling: Boolean
484
+ isDefaultShipping: Boolean
485
+ }
486
+
487
+ type CustomerAddressPayload {
488
+ address: CustomerAddress
489
+ customer: Customer
490
+ }
491
+
492
+ union CustomerAddressUpdateResult = AuthenticationError | CustomerAddressPayload | NotFoundError | PermissionDeniedError | ValidationError
493
+
494
+ type CustomerAuthPayload {
495
+ """Set when a guest cartId was passed: the merged customer cart."""
496
+ cart: Cart
497
+ customer: Customer
498
+ session: Session
499
+ }
500
+
501
+ union CustomerLoginResult = AuthenticationError | CustomerAuthPayload | NotFoundError | PermissionDeniedError | ValidationError
502
+
503
+ type CustomerOrdersConnection {
504
+ edges: [CustomerOrdersConnectionEdge]
505
+ pageInfo: PageInfo!
506
+
507
+ """Total matching items across all pages."""
508
+ totalCount: Int
509
+ }
510
+
511
+ type CustomerOrdersConnectionEdge {
512
+ cursor: String!
513
+ node: Order
514
+ }
515
+
516
+ union CustomerPasswordChangeResult = AuthenticationError | CustomerPayload | NotFoundError | PermissionDeniedError | ValidationError
517
+
518
+ union CustomerPasswordResetRequestResult = AcceptedPayload | AuthenticationError | NotFoundError | PermissionDeniedError | ValidationError
519
+
520
+ union CustomerPasswordResetResult = AuthenticationError | CustomerPayload | NotFoundError | PermissionDeniedError | ValidationError
521
+
522
+ type CustomerPayload {
523
+ customer: Customer
524
+ }
525
+
526
+ input CustomerRegisterInput {
527
+ acceptsMarketing: Boolean
528
+ dateOfBirth: String
529
+ email: EmailAddress!
530
+ firstName: String!
531
+ lastName: String!
532
+ password: String!
533
+ phone: String
534
+ }
535
+
536
+ union CustomerRegisterResult = AuthenticationError | CustomerAuthPayload | NotFoundError | PermissionDeniedError | ValidationError
537
+
538
+ input CustomerUpdateInput {
539
+ acceptsMarketing: Boolean
540
+ dateOfBirth: String
541
+ firstName: String
542
+ lastName: String
543
+ phone: String
544
+ }
545
+
546
+ union CustomerUpdateResult = AuthenticationError | CustomerPayload | NotFoundError | PermissionDeniedError | ValidationError
547
+
548
+ """ISO 8601 date-time in UTC."""
549
+ scalar DateTime
550
+
551
+ """
552
+ Exact decimal amount as a string, e.g. "19.99". Money never uses floats.
553
+ """
554
+ scalar Decimal
555
+
556
+ type DeletePayload {
557
+ deletedId: ID
558
+ }
559
+
560
+ type DocumentLine {
561
+ orderLine: OrderLine
562
+ quantity: Int
563
+ }
564
+
565
+ """An email address."""
566
+ scalar EmailAddress
567
+
568
+ """
569
+ Implemented by every expected failure. Query `... on Error { code message }` to handle any of them.
570
+ """
571
+ interface Error {
572
+ code: ErrorCode
573
+ message: String
574
+ }
575
+
576
+ """Stable machine-readable error codes."""
577
+ enum ErrorCode {
578
+ CART_NOT_READY
579
+ CONFLICT
580
+ COUPON_NOT_APPLICABLE
581
+ INSUFFICIENT_STOCK
582
+ INVALID_STATE
583
+ NOT_FOUND
584
+ PAYMENT_DECLINED
585
+ PERMISSION_DENIED
586
+ UNAUTHENTICATED
587
+ VALIDATION_FAILED
588
+ }
589
+
590
+ type Facet {
591
+ attribute: AttributeDefinition
592
+ values: [FacetValue!]
593
+ }
594
+
595
+ type FacetValue {
596
+ """Products matching if this value were (also) selected."""
597
+ count: Int
598
+ label: String
599
+ selected: Boolean
600
+ swatch: String
601
+
602
+ """Pass this in `filter.attributes` to select it."""
603
+ value: String
604
+ }
605
+
606
+ """One invalid input field, addressed by its path from the argument root."""
607
+ type FieldError {
608
+ message: String
609
+ path: [String!]
610
+ }
611
+
612
+ """A shipment of some or all of an order's items."""
613
+ type Fulfillment {
614
+ createdAt: DateTime
615
+ id: ID
616
+ lines: [DocumentLine!]
617
+ number: String
618
+ status: String
619
+ tracking: [TrackingNumber!]
620
+ }
621
+
622
+ enum FulfillmentStatus {
623
+ FULFILLED
624
+ PARTIALLY_FULFILLED
625
+ UNFULFILLED
626
+ }
627
+
628
+ type InsufficientStockError implements Error {
629
+ available: Int
630
+ code: ErrorCode
631
+ message: String
632
+ requested: Int
633
+ sku: String
634
+ variantId: ID
635
+ }
636
+
637
+ type InvalidStateError implements Error {
638
+ code: ErrorCode
639
+ message: String
640
+ }
641
+
642
+ """An invoice: a captured payment."""
643
+ type Invoice {
644
+ amount: Money
645
+ createdAt: DateTime
646
+ id: ID
647
+ number: String
648
+ }
649
+
650
+ """Arbitrary JSON value."""
651
+ scalar JSON
652
+
653
+ """BCP 47 locale, e.g. de-DE."""
654
+ scalar LocaleCode
655
+
656
+ """
657
+ The scope this request runs in, set with @inContext or the X-Channel / Accept-Language / X-Currency headers.
658
+ """
659
+ type Localization {
660
+ channel: Channel
661
+ currencyCode: CurrencyCode
662
+ locale: LocaleCode
663
+ }
664
+
665
+ union LogoutResult = AcceptedPayload | AuthenticationError | NotFoundError | PermissionDeniedError | ValidationError
666
+
667
+ type Media implements Node {
668
+ alt: String
669
+ id: ID!
670
+ kind: MediaKind
671
+ position: Int
672
+ url: String
673
+ variant: ProductVariant
674
+ }
675
+
676
+ enum MediaKind {
677
+ IMAGE
678
+ VIDEO
679
+ }
680
+
681
+ """An exact amount in a currency."""
682
+ type Money {
683
+ amount: Decimal
684
+ currencyCode: CurrencyCode
685
+
686
+ """Formatted for the request locale, e.g. "19,99 €"."""
687
+ formatted: String
688
+ }
689
+
690
+ """
691
+ Entry point for writes. Every mutation returns a result union: the payload or a typed error.
692
+ """
693
+ type Mutation {
694
+ """
695
+ Adopt a guest cart after sign-in, merging it into the customer's open cart if there is one.
696
+ """
697
+ cartAssignToCustomer(cartId: ID!): CartAssignToCustomerResult
698
+ cartBillingAddressSet(address: CartBillingAddressInput!, cartId: ID!): CartBillingAddressSetResult @deprecated(reason: "Use cartUpdate, which sets any checkout details in one call and takes incomplete addresses.")
699
+
700
+ """
701
+ Fails with CouponNotApplicableError (and a reason) unless the coupon is valid and its promotion applies to the cart.
702
+ """
703
+ cartCouponApply(cartId: ID!, code: String!): CartCouponApplyResult
704
+ cartCouponRemove(cartId: ID!, code: String!): CartCouponRemoveResult
705
+
706
+ """
707
+ Create a cart in the request's channel and currency; signed-in customers own it.
708
+ """
709
+ cartCreate(input: CartCreateInput): CartCreateResult
710
+ cartEmailUpdate(cartId: ID!, email: EmailAddress!): CartEmailUpdateResult @deprecated(reason: "Use cartUpdate, which sets any checkout details in one call and takes incomplete addresses.")
711
+
712
+ """
713
+ Add variants; quantities add up for variants already in the cart. Checked against salable stock.
714
+ """
715
+ cartLinesAdd(cartId: ID!, lines: [CartLineInput!]!): CartLinesAddResult
716
+ cartLinesRemove(cartId: ID!, lineIds: [ID!]!): CartLinesRemoveResult
717
+ cartLinesUpdate(cartId: ID!, lines: [CartLineUpdateInput!]!): CartLinesUpdateResult
718
+ cartPaymentMethodSet(cartId: ID!, paymentMethodCode: String!): CartPaymentMethodSetResult @deprecated(reason: "Use cartUpdate, which sets any checkout details in one call and takes incomplete addresses.")
719
+
720
+ """
721
+ Start the payment with the selected method's provider for the cart's total (e.g. a Stripe PaymentIntent) when its sessionRequired is true. Call again after the total changes to update the same payment. See docs/payments.md.
722
+ """
723
+ cartPaymentSessionCreate(cartId: ID!): CartPaymentSessionCreateResult
724
+ cartShippingAddressSet(address: CartAddressInput!, cartId: ID!): CartShippingAddressSetResult @deprecated(reason: "Use cartUpdate, which sets any checkout details in one call and takes incomplete addresses.")
725
+ cartShippingMethodSet(cartId: ID!, shippingMethodCode: String!): CartShippingMethodSetResult @deprecated(reason: "Use cartUpdate, which sets any checkout details in one call and takes incomplete addresses.")
726
+
727
+ """
728
+ Set any checkout details, in any order and as often as the shopper changes them. Addresses may be incomplete: rates and tax follow once the shipping address has a country and postal code, and checkout reports the rest (CartNotReadyError.fieldErrors). The cheapest rate is selected until the shopper picks one; billing follows shipping unless the cart has its own. Every invalid field is reported at once; nothing is saved unless all are valid.
729
+ """
730
+ cartUpdate(cartId: ID!, input: CartUpdateInput!): CartUpdateResult
731
+
732
+ """
733
+ Turn a ready cart into an order: re-price, reserve stock, authorize payment. `input` is saved first, as cartUpdate saves it, so one call can do everything. Retries return the same order: with the same idempotencyKey, or any key once the cart is an order. A declined payment releases stock and reopens the cart. With a payment session, confirm the payment in the browser first and pass an empty payment.
734
+ """
735
+ checkoutPlaceOrder(
736
+ cartId: ID!
737
+
738
+ """Client-generated, e.g. a UUID per checkout attempt."""
739
+ idempotencyKey: String!
740
+
741
+ """Checkout details to save before placing the order."""
742
+ input: CartUpdateInput
743
+ payment: PaymentDataInput
744
+ ): CheckoutPlaceOrderResult
745
+
746
+ """
747
+ Storefront: the signed-in customer's address book. Admin: any customer's, by customerId.
748
+ """
749
+ customerAddressCreate(input: CustomerAddressInput!): CustomerAddressCreateResult
750
+ customerAddressDelete(id: ID!): CustomerAddressDeleteResult
751
+ customerAddressUpdate(id: ID!, input: CustomerAddressInput!): CustomerAddressUpdateResult
752
+
753
+ """Sign in. A guest cartId is merged into the customer's open cart."""
754
+ customerLogin(cartId: ID, email: EmailAddress!, password: String!): CustomerLoginResult
755
+ customerPasswordChange(currentPassword: String!, newPassword: String!): CustomerPasswordChangeResult
756
+
757
+ """
758
+ Set a new password with a reset token. Signs the customer out everywhere.
759
+ """
760
+ customerPasswordReset(newPassword: String!, token: String!): CustomerPasswordResetResult
761
+
762
+ """
763
+ Always accepted, never revealing whether the account exists. Emits customer.password_reset_requested to plugins (the email plugin sends the link), not webhooks.
764
+ """
765
+ customerPasswordResetRequest(email: EmailAddress!): CustomerPasswordResetRequestResult
766
+
767
+ """Create an account and sign in. Pass a guest cartId to keep the cart."""
768
+ customerRegister(cartId: ID, input: CustomerRegisterInput!): CustomerRegisterResult
769
+
770
+ """
771
+ Storefront: update the signed-in customer. Admin: update any customer by id.
772
+ """
773
+ customerUpdate(input: CustomerUpdateInput!): CustomerUpdateResult
774
+
775
+ """Revoke the refresh token and every token rotated from it."""
776
+ logout(refreshToken: String!): LogoutResult
777
+
778
+ """
779
+ Cancel an unshipped, uncaptured order (customers: their own). Voids the authorization and releases reserved stock.
780
+ """
781
+ orderCancel(orderId: ID!, reason: String): OrderCancelResult
782
+
783
+ """
784
+ Exchange a refresh token for a new session. Refresh tokens are single use; replaying one revokes the whole session family.
785
+ """
786
+ tokenRefresh(refreshToken: String!): TokenRefreshResult
787
+ }
788
+
789
+ interface Node {
790
+ id: ID!
791
+ }
792
+
793
+ type NotFoundError implements Error {
794
+ code: ErrorCode
795
+ message: String
796
+ resource: String
797
+ }
798
+
799
+ type Order implements Node {
800
+ billingAddress: Address
801
+
802
+ """Open, unshipped and not yet charged."""
803
+ canCancel: Boolean
804
+ canceledAt: DateTime
805
+ completedAt: DateTime
806
+ couponCodes: [String!]
807
+ currencyCode: CurrencyCode
808
+ email: EmailAddress
809
+ fulfillmentStatus: FulfillmentStatus
810
+ fulfillments: [Fulfillment!]
811
+ id: ID!
812
+ invoices: [Invoice!]
813
+ lines: [OrderLine!]
814
+ locale: LocaleCode
815
+ number: String
816
+ paymentMethodCode: String
817
+ paymentStatus: PaymentStatus
818
+ placedAt: DateTime
819
+ refunds: [Refund!]
820
+ shippingAddress: Address
821
+ shippingMethod: OrderShippingMethod
822
+ status: OrderStatus
823
+ totals: OrderTotals
824
+ }
825
+
826
+ union OrderCancelResult = AuthenticationError | InvalidStateError | NotFoundError | OrderPayload | PermissionDeniedError | ValidationError
827
+
828
+ type OrderDiscount {
829
+ amount: Money
830
+ couponCode: String
831
+ name: String
832
+ }
833
+
834
+ type OrderLine {
835
+ discount: Money
836
+ id: ID
837
+ name: String
838
+ product: Product
839
+ quantity: Int
840
+ quantityCanceled: Int
841
+ quantityFulfilled: Int
842
+ quantityRefunded: Int
843
+ sku: String
844
+ subtotal: Money
845
+ tax: Money
846
+ taxRate: Float
847
+ total: Money
848
+ unitPrice: Money
849
+
850
+ """Null if the variant was deleted since."""
851
+ variant: ProductVariant
852
+
853
+ """Snapshot of the variant's options when ordered."""
854
+ variantAttributes: JSON
855
+ }
856
+
857
+ type OrderPayload {
858
+ order: Order
859
+ }
860
+
861
+ type OrderShippingMethod {
862
+ carrier: String
863
+ code: String
864
+ name: String
865
+ price: Money
866
+ }
867
+
868
+ enum OrderStatus {
869
+ CANCELED
870
+ COMPLETED
871
+ OPEN
872
+ }
873
+
874
+ type OrderTaxLine {
875
+ amount: Money
876
+ name: String
877
+ rate: Float
878
+ }
879
+
880
+ type OrderTotals {
881
+ discountTotal: Money
882
+ discounts: [OrderDiscount!]
883
+ paid: Money
884
+ pricesIncludeTax: Boolean
885
+ refunded: Money
886
+ shipping: Money
887
+ subtotal: Money
888
+ tax: Money
889
+ taxLines: [OrderTaxLine!]
890
+ total: Money
891
+ }
892
+
893
+ type OrderUpdate {
894
+ """e.g. order.fulfilled"""
895
+ eventType: String
896
+
897
+ """As of this event."""
898
+ fulfillmentStatus: FulfillmentStatus
899
+ occurredAt: DateTime
900
+
901
+ """The order now."""
902
+ order: Order
903
+
904
+ """As of this event."""
905
+ paymentStatus: PaymentStatus
906
+
907
+ """As of this event."""
908
+ status: OrderStatus
909
+ }
910
+
911
+ """
912
+ A page built from components. Storefronts get the published version, or the draft with a preview token.
913
+ """
914
+ type Page implements Node {
915
+ """
916
+ The component tree in the request locale: { id, component, variation, fields }, with blocks fields holding child nodes and list fields holding { id, fields } items. Hidden components and those not targeted at this channel, locale or time are left out. Links are { kind, href, id, newTab }; products and categories are global ids, resolved in references.
917
+ """
918
+ content: JSON
919
+ id: ID!
920
+
921
+ """
922
+ True when this is unpublished draft content, served for a preview token.
923
+ """
924
+ isPreview: Boolean
925
+
926
+ """
927
+ Where the page is served; null for content types without paths (header, footer, templates).
928
+ """
929
+ path: String
930
+ publishedAt: DateTime
931
+ references: PageReferences
932
+
933
+ """
934
+ Set for a product's or category's own sections (Product.sections, Category.sections): which of the two they belong to.
935
+ """
936
+ sectionsFor: TemplateFor
937
+ seo: PageSeo
938
+
939
+ """
940
+ Set for templates: product or category pages render with this page, with the product or category as data for its components.
941
+ """
942
+ templateFor: TemplateFor
943
+ title: String
944
+
945
+ """The content type's code, e.g. landing_page."""
946
+ type: String
947
+ updatedAt: DateTime
948
+ }
949
+
950
+ type PageImage {
951
+ alt: String
952
+ height: Int
953
+ url: String
954
+ width: Int
955
+ }
956
+
957
+ type PageInfo {
958
+ endCursor: String
959
+ hasNextPage: Boolean!
960
+ hasPreviousPage: Boolean!
961
+ startCursor: String
962
+ }
963
+
964
+ """A page linked from content: where it is served and its title."""
965
+ type PageLink {
966
+ id: ID
967
+ path: String
968
+ title: String
969
+ }
970
+
971
+ """
972
+ Objects the content refers to by id, so one request renders the whole page.
973
+ """
974
+ type PageReferences {
975
+ categories: [Category!]
976
+ pages: [PageLink!]
977
+
978
+ """
979
+ Products the storefront may show; unpublished ones are left out (render nothing for them).
980
+ """
981
+ products: [Product!]
982
+ }
983
+
984
+ """Search and sharing metadata, in the request locale."""
985
+ type PageSeo {
986
+ description: String
987
+ image: PageImage
988
+ noIndex: Boolean
989
+
990
+ """Falls back to nothing; frontends usually use the page title."""
991
+ title: String
992
+ }
993
+
994
+ enum PageSort {
995
+ """By path (the site's structure)."""
996
+ PATH
997
+
998
+ """
999
+ Most recently changed first (admin: draft saves; storefront: publishes).
1000
+ """
1001
+ UPDATED
1002
+ }
1003
+
1004
+ enum PageStatus {
1005
+ """Live, with draft changes not yet published."""
1006
+ CHANGED
1007
+
1008
+ """Never published."""
1009
+ DRAFT
1010
+
1011
+ """Live, with no unpublished changes."""
1012
+ PUBLISHED
1013
+
1014
+ """Will publish at scheduledAt."""
1015
+ SCHEDULED
1016
+ }
1017
+
1018
+ """
1019
+ Provider-specific payment data, e.g. a tokenized card from the PSP's client SDK. Never raw card numbers.
1020
+ """
1021
+ input PaymentDataInput {
1022
+ token: String
1023
+ }
1024
+
1025
+ type PaymentDeclinedError implements Error {
1026
+ code: ErrorCode
1027
+ declineCode: String
1028
+ message: String
1029
+ }
1030
+
1031
+ type PaymentMethodOption {
1032
+ code: String
1033
+ instructions: String
1034
+ name: String
1035
+
1036
+ """The payment provider behind the method, e.g. stripe, offline."""
1037
+ provider: String
1038
+
1039
+ """
1040
+ Start a payment session (cartPaymentSessionCreate) and confirm the payment in the browser before placing the order.
1041
+ """
1042
+ sessionRequired: Boolean
1043
+ }
1044
+
1045
+ enum PaymentStatus {
1046
+ AUTHORIZED
1047
+ PAID
1048
+ PARTIALLY_PAID
1049
+ PARTIALLY_REFUNDED
1050
+
1051
+ """Awaiting payment (e.g. bank transfer)."""
1052
+ PENDING
1053
+ REFUNDED
1054
+ VOIDED
1055
+ }
1056
+
1057
+ type PermissionDeniedError implements Error {
1058
+ code: ErrorCode
1059
+ message: String
1060
+ permission: String
1061
+ }
1062
+
1063
+ """
1064
+ A preview of draft content. In the storefront API this describes the request's x-preview-token.
1065
+ """
1066
+ type PreviewSession {
1067
+ """
1068
+ The admin's origin: the only window the visual editing bridge talks to.
1069
+ """
1070
+ adminOrigin: String
1071
+
1072
+ """Scheduled content is shown as of this time."""
1073
+ at: String
1074
+ expiresAt: DateTime
1075
+ }
1076
+
1077
+ """Inclusive bounds in the request currency."""
1078
+ input PriceFilterInput {
1079
+ max: Decimal
1080
+ min: Decimal
1081
+ }
1082
+
1083
+ type PriceRange {
1084
+ maximum: Money
1085
+ minimum: Money
1086
+ }
1087
+
1088
+ type Product implements Node {
1089
+ """Product-level attributes (variant axes are under `options`)."""
1090
+ attributes: [ProductAttribute!]
1091
+ categories: [Category!]
1092
+ createdAt: DateTime
1093
+
1094
+ """HTML."""
1095
+ description: String
1096
+ id: ID!
1097
+
1098
+ """Whether any variant can be bought now."""
1099
+ isAvailable: Boolean
1100
+ media: [Media!]
1101
+ name: String
1102
+ options: [ProductOption!]
1103
+ priceRange: ProductPriceRange
1104
+
1105
+ """
1106
+ This product's own sections, to render with the product as data where its template places the product sections component. Null when it has none. Drafts appear only with a preview token.
1107
+ """
1108
+ sections: Page
1109
+ seo: Seo
1110
+ slug: String
1111
+
1112
+ """
1113
+ The page builder template for this product's page: the one assigned to the product, else its nearest category's, else the default. Render its content with the product as data. Null means none: use your built-in layout. Drafts appear only with a preview token.
1114
+ """
1115
+ template: Page
1116
+
1117
+ """
1118
+ The variant matching every selected option, e.g. color=blue and size=m.
1119
+ """
1120
+ variant(selectedOptions: [SelectedOptionInput!]!): ProductVariant
1121
+ variants: [ProductVariant!]
1122
+ }
1123
+
1124
+ """A typed attribute value, already formatted for the request locale."""
1125
+ type ProductAttribute {
1126
+ attribute: AttributeDefinition
1127
+
1128
+ """Selected options for select and multiselect attributes."""
1129
+ options: [AttributeOption!]
1130
+ raw: JSON
1131
+
1132
+ """Display value, e.g. "Organic cotton" or "Blue, Green"."""
1133
+ value: String
1134
+ }
1135
+
1136
+ type ProductConnection {
1137
+ edges: [ProductEdge]
1138
+
1139
+ """
1140
+ Counts per filterable attribute value. Disjunctive: selecting a value keeps its siblings' counts.
1141
+ """
1142
+ facets: [Facet!]
1143
+ pageInfo: PageInfo!
1144
+
1145
+ """
1146
+ Price span of all matches, ignoring the price filter (for range sliders).
1147
+ """
1148
+ priceRange: PriceRange
1149
+
1150
+ """Total matching items across all pages."""
1151
+ totalCount: Int
1152
+ }
1153
+
1154
+ type ProductEdge {
1155
+ cursor: String!
1156
+ node: Product
1157
+ }
1158
+
1159
+ input ProductFilter {
1160
+ """Values within one attribute are ORed; attributes are ANDed."""
1161
+ attributes: [AttributeFilterInput!]
1162
+
1163
+ """Includes products in descendant categories."""
1164
+ categoryId: ID
1165
+ ids: [ID!]
1166
+ inStock: Boolean
1167
+ price: PriceFilterInput
1168
+ }
1169
+
1170
+ """
1171
+ A variant axis (e.g. Size) with the values that exist among the product's variants.
1172
+ """
1173
+ type ProductOption {
1174
+ attribute: AttributeDefinition
1175
+ values: [AttributeOption!]
1176
+ }
1177
+
1178
+ """Prices for the request's channel, currency and customer group."""
1179
+ type ProductPriceRange {
1180
+ compareAtMinVariantPrice: Money
1181
+ maxVariantPrice: Money
1182
+ minVariantPrice: Money
1183
+ }
1184
+
1185
+ enum ProductSortField {
1186
+ """
1187
+ A category's merchandised listing: its pinned products in order, then the rest newest first. Elsewhere, newest first. Storefront only.
1188
+ """
1189
+ FEATURED
1190
+ NAME
1191
+ NEWEST
1192
+ PRICE
1193
+ RELEVANCE
1194
+ }
1195
+
1196
+ input ProductSortInput {
1197
+ """
1198
+ Defaults to DESC for NEWEST and RELEVANCE (newest, best match first) and ASC for NAME and PRICE. FEATURED ignores it.
1199
+ """
1200
+ direction: SortDirection
1201
+ field: ProductSortField!
1202
+ }
1203
+
1204
+ type ProductVariant implements Node {
1205
+ compareAtPrice: Money
1206
+ id: ID!
1207
+ isAvailable: Boolean
1208
+ media: [Media!]
1209
+
1210
+ """
1211
+ Product name with the variant's options, e.g. "Oxford Shirt – Blue / M".
1212
+ """
1213
+ name: String
1214
+ price: Money
1215
+ product: Product
1216
+
1217
+ """
1218
+ Salable quantity in the channel's stock; null when the variant does not track inventory.
1219
+ """
1220
+ quantityAvailable: Int
1221
+ selectedOptions: [SelectedOption!]
1222
+ sku: String
1223
+ tierPrices: [TierPrice!]
1224
+ weightGrams: Int
1225
+ }
1226
+
1227
+ """Entry point for reads."""
1228
+ type Query {
1229
+ """All attribute definitions, e.g. to render filters."""
1230
+ attributeDefinitions: [AttributeDefinition!]
1231
+ cart(id: ID!): Cart
1232
+ category(id: ID, slug: String): Category
1233
+
1234
+ """Root categories; walk `children` for the tree."""
1235
+ categoryTree: [Category!]
1236
+
1237
+ """Order status for guests: all three values must match."""
1238
+ guestOrder(email: EmailAddress!, number: String!, postalCode: String!): Order
1239
+ localization: Localization
1240
+
1241
+ """The signed-in customer, or null for anonymous requests."""
1242
+ me: Customer
1243
+
1244
+ """Refetch any object by its global id."""
1245
+ node(id: ID!): Node
1246
+
1247
+ """Refetch several objects by global id, in order."""
1248
+ nodes(ids: [ID!]!): [Node]!
1249
+
1250
+ """By number. Storefront: the signed-in customer's orders only."""
1251
+ order(number: String!): Order
1252
+
1253
+ """
1254
+ Storefront: the page served at a path (draft content with a preview token). Admin: by id or path.
1255
+ """
1256
+ page(id: ID, path: String): Page
1257
+
1258
+ """
1259
+ Pages by path. Storefront: published pages served in the channel (e.g. for a sitemap or a journal index). Admin: every page; status filters the admin list.
1260
+ """
1261
+ pages(
1262
+ after: String
1263
+ before: String
1264
+ first: Int
1265
+ last: Int
1266
+
1267
+ """Part of the path or title."""
1268
+ query: String
1269
+
1270
+ """Defaults to PATH."""
1271
+ sort: PageSort
1272
+
1273
+ """Admin only; the storefront lists published pages."""
1274
+ status: PageStatus
1275
+
1276
+ """A content type's code."""
1277
+ type: String
1278
+ ): QueryPagesConnection
1279
+
1280
+ """
1281
+ The request's preview, from its x-preview-token header; null without one. Frontends call it to validate a token before enabling draft mode.
1282
+ """
1283
+ previewSession: PreviewSession
1284
+
1285
+ """
1286
+ Look up a product by exactly one of id, slug (in the request locale) or a variant SKU.
1287
+ """
1288
+ product(id: ID, sku: String, slug: String): Product
1289
+
1290
+ """
1291
+ Storefront: full-text search with facets over the channel's published catalog. Admin: every product, newest first, or by name or lowest base price with `sort`.
1292
+ """
1293
+ products(
1294
+ after: String
1295
+ before: String
1296
+ filter: ProductFilter
1297
+ first: Int
1298
+ last: Int
1299
+
1300
+ """Full-text search with prefix matching, e.g. "trail run"."""
1301
+ query: String
1302
+
1303
+ """
1304
+ Defaults to RELEVANCE with a query, then to FEATURED in a category's listing, otherwise NEWEST.
1305
+ """
1306
+ sort: ProductSortInput
1307
+ ): ProductConnection
1308
+
1309
+ """
1310
+ What a storefront path serves: a builder page at exactly that path; a product at /products/<slug> or a category at /categories/<slug path>, redirecting when a slug moved or the parents differ; otherwise a product or category by the last segment, else a redirect.
1311
+ """
1312
+ route(path: String!): RouteResult
1313
+
1314
+ """
1315
+ The one page of a singleton content type, e.g. site_header or site_footer.
1316
+ """
1317
+ singletonPage(type: String!): Page
1318
+ }
1319
+
1320
+ type QueryPagesConnection {
1321
+ edges: [QueryPagesConnectionEdge]
1322
+ pageInfo: PageInfo!
1323
+
1324
+ """Total matching items across all pages."""
1325
+ totalCount: Int
1326
+ }
1327
+
1328
+ type QueryPagesConnectionEdge {
1329
+ cursor: String!
1330
+ node: Page
1331
+ }
1332
+
1333
+ """The path moved; send the shopper to `location`."""
1334
+ type Redirect {
1335
+ location: String
1336
+ statusCode: Int
1337
+ }
1338
+
1339
+ """A refund: money returned to the customer."""
1340
+ type Refund {
1341
+ amount: Money
1342
+ createdAt: DateTime
1343
+ id: ID
1344
+ lines: [RefundLine!]
1345
+ number: String
1346
+ reason: String
1347
+ shippingAmount: Money
1348
+ }
1349
+
1350
+ type RefundLine {
1351
+ amount: Money
1352
+ orderLine: OrderLine
1353
+ quantity: Int
1354
+ restocked: Boolean
1355
+ }
1356
+
1357
+ union RouteResult = Category | Page | Product | Redirect
1358
+
1359
+ """One variant axis value, e.g. Color: Blue."""
1360
+ type SelectedOption {
1361
+ """Attribute code, e.g. color."""
1362
+ attribute: String
1363
+
1364
+ """Option label in the request locale."""
1365
+ label: String
1366
+
1367
+ """Attribute label in the request locale."""
1368
+ name: String
1369
+ swatch: String
1370
+
1371
+ """Option code, e.g. blue."""
1372
+ value: String
1373
+ }
1374
+
1375
+ input SelectedOptionInput {
1376
+ attribute: String!
1377
+ value: String!
1378
+ }
1379
+
1380
+ type Seo {
1381
+ description: String
1382
+ title: String
1383
+ }
1384
+
1385
+ """
1386
+ A signed-in session: a short-lived access token and a single-use refresh token.
1387
+ """
1388
+ type Session {
1389
+ accessToken: String
1390
+ accessTokenExpiresAt: DateTime
1391
+ refreshToken: String
1392
+ refreshTokenExpiresAt: DateTime
1393
+ }
1394
+
1395
+ type SessionPayload {
1396
+ session: Session
1397
+ }
1398
+
1399
+ type ShippingRate {
1400
+ carrier: String
1401
+ code: String
1402
+ description: String
1403
+ maxDeliveryDays: Int
1404
+ minDeliveryDays: Int
1405
+ name: String
1406
+ price: Money
1407
+ }
1408
+
1409
+ enum SortDirection {
1410
+ ASC
1411
+ DESC
1412
+ }
1413
+
1414
+ """Live updates over Server-Sent Events."""
1415
+ type Subscription {
1416
+ """
1417
+ Status changes of one of the signed-in customer's orders, after they commit.
1418
+ """
1419
+ orderUpdated(orderId: ID!): OrderUpdate
1420
+ }
1421
+
1422
+ type TaxLine {
1423
+ amount: Money
1424
+ name: String
1425
+
1426
+ """Percent."""
1427
+ rate: Float
1428
+ }
1429
+
1430
+ """What a template renders: product pages or category pages."""
1431
+ enum TemplateFor {
1432
+ CATEGORY
1433
+ PRODUCT
1434
+ }
1435
+
1436
+ type TierPrice {
1437
+ minQuantity: Int
1438
+ price: Money
1439
+ }
1440
+
1441
+ union TokenRefreshResult = AuthenticationError | NotFoundError | PermissionDeniedError | SessionPayload | ValidationError
1442
+
1443
+ type TrackingNumber {
1444
+ carrier: String
1445
+ number: String
1446
+ url: String
1447
+ }
1448
+
1449
+ type ValidationError implements Error {
1450
+ code: ErrorCode
1451
+ fieldErrors: [FieldError!]
1452
+ message: String
1453
+ }