@waffo/pancake-ts 0.1.7 → 0.1.9
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/CHANGELOG.md +31 -2
- package/README.md +202 -370
- package/dist/index.cjs +121 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +266 -52
- package/dist/index.d.ts +266 -52
- package/dist/index.js +121 -33
- package/dist/index.js.map +1 -1
- package/docs/api-reference.md +786 -0
- package/docs/graphql-guide.md +664 -0
- package/docs/webhook-guide.md +456 -0
- package/package.json +2 -1
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
# GraphQL Guide
|
|
2
|
+
|
|
3
|
+
The Waffo Pancake GraphQL API is **query-only** — Mutations are not supported and return a 403 error. All queries go through `client.graphql.query<T>()`.
|
|
4
|
+
|
|
5
|
+
## Introspection
|
|
6
|
+
|
|
7
|
+
Introspection is **enabled by default**. Use it during development to explore the full schema, discover available types, fields, and filter conditions.
|
|
8
|
+
|
|
9
|
+
> **Recommended**: Always use introspection to stay in sync with the server — this guide covers common queries, but the schema is the source of truth.
|
|
10
|
+
|
|
11
|
+
### Discover All Query Fields
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const schema = await client.graphql.query({
|
|
15
|
+
query: `{
|
|
16
|
+
__schema {
|
|
17
|
+
queryType {
|
|
18
|
+
fields {
|
|
19
|
+
name
|
|
20
|
+
description
|
|
21
|
+
args { name type { name kind ofType { name } } }
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}`,
|
|
26
|
+
});
|
|
27
|
+
console.log(schema.data?.__schema.queryType.fields);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Inspect a Specific Type
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const orderType = await client.graphql.query({
|
|
34
|
+
query: `{
|
|
35
|
+
__type(name: "OnetimeOrder") {
|
|
36
|
+
fields {
|
|
37
|
+
name
|
|
38
|
+
type { name kind ofType { name } }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}`,
|
|
42
|
+
});
|
|
43
|
+
console.log(orderType.data?.__type.fields);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Interactive Schema Browsers
|
|
47
|
+
|
|
48
|
+
You can also connect [GraphiQL](https://github.com/graphql/graphiql) or [Apollo Sandbox](https://studio.apollographql.com/sandbox) to `https://api.waffo.ai/v1/graphql` for interactive schema browsing with auto-complete.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Practical Examples
|
|
53
|
+
|
|
54
|
+
### 1. Store Queries
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
interface StoresQuery {
|
|
58
|
+
stores: Array<{
|
|
59
|
+
id: string;
|
|
60
|
+
name: string;
|
|
61
|
+
slug: string;
|
|
62
|
+
status: string;
|
|
63
|
+
supportEmail: string | null;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
const { data } = await client.graphql.query<StoresQuery>({
|
|
68
|
+
query: `query { stores { id name slug status supportEmail createdAt } }`,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Single store by ID
|
|
72
|
+
const store = await client.graphql.query({
|
|
73
|
+
query: `query ($id: ID!) {
|
|
74
|
+
store(id: $id) { id name slug status }
|
|
75
|
+
}`,
|
|
76
|
+
variables: { id: "STO_xxx" },
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Product Queries
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// One-time products with prices
|
|
84
|
+
interface ProductsQuery {
|
|
85
|
+
onetimeProducts: Array<{
|
|
86
|
+
id: string;
|
|
87
|
+
name: string;
|
|
88
|
+
status: string;
|
|
89
|
+
prices: Array<{ currency: string; priceInfo: { amount: string; taxCategory: string } }>;
|
|
90
|
+
hasProdVersion: boolean;
|
|
91
|
+
}>;
|
|
92
|
+
}
|
|
93
|
+
const products = await client.graphql.query<ProductsQuery>({
|
|
94
|
+
query: `query ($storeId: String!) {
|
|
95
|
+
onetimeProducts(storeId: $storeId, filter: { status: { eq: "active" } }) {
|
|
96
|
+
id name status
|
|
97
|
+
prices { currency priceInfo { amount taxCategory } }
|
|
98
|
+
hasProdVersion
|
|
99
|
+
}
|
|
100
|
+
}`,
|
|
101
|
+
variables: { storeId: "STO_xxx" },
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Subscription products
|
|
105
|
+
const subProducts = await client.graphql.query({
|
|
106
|
+
query: `query ($storeId: String!) {
|
|
107
|
+
subscriptionProducts(storeId: $storeId) {
|
|
108
|
+
id name billingPeriod status
|
|
109
|
+
prices { currency priceInfo { amount taxCategory } }
|
|
110
|
+
}
|
|
111
|
+
}`,
|
|
112
|
+
variables: { storeId: "STO_xxx" },
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 3. Order Queries
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// One-time orders with price snapshot
|
|
120
|
+
interface OnetimeOrdersQuery {
|
|
121
|
+
onetimeOrders: Array<{
|
|
122
|
+
id: string;
|
|
123
|
+
buyerEmail: string;
|
|
124
|
+
currency: string;
|
|
125
|
+
status: string;
|
|
126
|
+
priceSnapshot: {
|
|
127
|
+
currency: string;
|
|
128
|
+
subtotal: string;
|
|
129
|
+
taxAmount: string;
|
|
130
|
+
total: string;
|
|
131
|
+
taxCategory: string;
|
|
132
|
+
};
|
|
133
|
+
onetimeProduct: { name: string };
|
|
134
|
+
createdAt: string;
|
|
135
|
+
}>;
|
|
136
|
+
}
|
|
137
|
+
const orders = await client.graphql.query<OnetimeOrdersQuery>({
|
|
138
|
+
query: `query ($storeId: String!) {
|
|
139
|
+
onetimeOrders(storeId: $storeId) {
|
|
140
|
+
id buyerEmail currency status
|
|
141
|
+
priceSnapshot { currency subtotal taxAmount total taxCategory }
|
|
142
|
+
onetimeProduct { name }
|
|
143
|
+
createdAt
|
|
144
|
+
}
|
|
145
|
+
}`,
|
|
146
|
+
variables: { storeId: "STO_xxx" },
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Subscription orders
|
|
150
|
+
const subOrders = await client.graphql.query({
|
|
151
|
+
query: `query ($storeId: String!) {
|
|
152
|
+
subscriptionOrders(storeId: $storeId) {
|
|
153
|
+
id buyerEmail status billingPeriod
|
|
154
|
+
priceSnapshot {
|
|
155
|
+
currency
|
|
156
|
+
regularPhase { subtotal taxAmount total taxCategory }
|
|
157
|
+
specialPhase { subtotal taxAmount total taxCategory }
|
|
158
|
+
specialPhaseDays
|
|
159
|
+
}
|
|
160
|
+
currentPeriodEnd canceledAt
|
|
161
|
+
}
|
|
162
|
+
}`,
|
|
163
|
+
variables: { storeId: "STO_xxx" },
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 4. Order Details (with Payment History)
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// One-time order with payments and refunds
|
|
171
|
+
const orderDetail = await client.graphql.query({
|
|
172
|
+
query: `query ($id: ID!) {
|
|
173
|
+
onetimeOrder(id: $id) {
|
|
174
|
+
id buyerEmail currency status testMode
|
|
175
|
+
priceSnapshot { currency subtotal taxAmount total taxCategory }
|
|
176
|
+
billingDetail { country isBusiness postcode state businessName taxId }
|
|
177
|
+
onetimeProduct { id name }
|
|
178
|
+
productVersion { id versionNumber name }
|
|
179
|
+
payments {
|
|
180
|
+
id status refundStatus
|
|
181
|
+
snapshotAmountDetails { currency subtotal taxAmount total taxCategory phase }
|
|
182
|
+
cardInfo { brand last4 expMonth expYear }
|
|
183
|
+
failureReason createdAt
|
|
184
|
+
refunds { id status requestedAmountDetails { currency amount } createdAt }
|
|
185
|
+
}
|
|
186
|
+
createdAt updatedAt
|
|
187
|
+
}
|
|
188
|
+
}`,
|
|
189
|
+
variables: { id: "ORD_xxx" },
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Subscription order with renewal status
|
|
193
|
+
const subDetail = await client.graphql.query({
|
|
194
|
+
query: `query ($id: ID!) {
|
|
195
|
+
subscriptionOrder(id: $id) {
|
|
196
|
+
id buyerEmail status billingPeriod
|
|
197
|
+
priceSnapshot {
|
|
198
|
+
currency specialPhaseDays
|
|
199
|
+
specialPhase { subtotal taxAmount total taxCategory }
|
|
200
|
+
regularPhase { subtotal taxAmount total taxCategory }
|
|
201
|
+
}
|
|
202
|
+
billingDetail { country isBusiness }
|
|
203
|
+
currentPeriodStart currentPeriodEnd canceledAt
|
|
204
|
+
subscriptionProduct { id name }
|
|
205
|
+
productVersion { id versionNumber name }
|
|
206
|
+
payments {
|
|
207
|
+
id status refundStatus
|
|
208
|
+
snapshotAmountDetails { currency subtotal taxAmount total taxCategory phase }
|
|
209
|
+
createdAt
|
|
210
|
+
}
|
|
211
|
+
createdAt
|
|
212
|
+
}
|
|
213
|
+
}`,
|
|
214
|
+
variables: { id: "ORD_xxx" },
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 5. Payment and Refund Queries
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// Payments with filters
|
|
222
|
+
const payments = await client.graphql.query({
|
|
223
|
+
query: `query {
|
|
224
|
+
payments(filter: { status: { eq: "succeeded" } }) {
|
|
225
|
+
id
|
|
226
|
+
onetimeOrder { id }
|
|
227
|
+
subscriptionOrder { id }
|
|
228
|
+
snapshotAmountDetails { currency subtotal taxAmount total taxCategory phase }
|
|
229
|
+
cardInfo { brand last4 }
|
|
230
|
+
status createdAt
|
|
231
|
+
}
|
|
232
|
+
}`,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Refund tickets
|
|
236
|
+
const tickets = await client.graphql.query({
|
|
237
|
+
query: `query {
|
|
238
|
+
refundTickets(limit: 20, filter: { status: { eq: "pending" } }) {
|
|
239
|
+
id status reason
|
|
240
|
+
requestedAmountDetails { currency amount }
|
|
241
|
+
payment {
|
|
242
|
+
id status
|
|
243
|
+
snapshotAmountDetails { currency subtotal taxAmount total taxCategory phase }
|
|
244
|
+
onetimeOrder { id buyerEmail store { name } }
|
|
245
|
+
subscriptionOrder { id buyerEmail store { name } }
|
|
246
|
+
}
|
|
247
|
+
createdAt updatedAt
|
|
248
|
+
}
|
|
249
|
+
refundTicketsCount(filter: { status: { eq: "pending" } })
|
|
250
|
+
}`,
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### 6. Merchant Info and Store Associations
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
const merchant = await client.graphql.query({
|
|
258
|
+
query: `query ($id: ID!) {
|
|
259
|
+
merchant(id: $id) {
|
|
260
|
+
id email name status
|
|
261
|
+
storeMerchants {
|
|
262
|
+
role
|
|
263
|
+
store { id name slug status }
|
|
264
|
+
}
|
|
265
|
+
apiKeys { id nickname environment recentlyUsed createdAt }
|
|
266
|
+
}
|
|
267
|
+
}`,
|
|
268
|
+
variables: { id: "MER_xxx" },
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### 7. Product Versions
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// One-time product version history
|
|
276
|
+
const versions = await client.graphql.query({
|
|
277
|
+
query: `query ($productId: String!) {
|
|
278
|
+
onetimeProductVersions(productId: $productId) {
|
|
279
|
+
id versionNumber name description
|
|
280
|
+
prices { currency priceInfo { amount taxCategory } }
|
|
281
|
+
media { type url alt thumbnail }
|
|
282
|
+
metadata isTestVersion isProdVersion createdAt
|
|
283
|
+
}
|
|
284
|
+
}`,
|
|
285
|
+
variables: { productId: "PROD_xxx" },
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Subscription product versions
|
|
289
|
+
const subVersions = await client.graphql.query({
|
|
290
|
+
query: `query ($productId: String!) {
|
|
291
|
+
subscriptionProductVersions(productId: $productId) {
|
|
292
|
+
id versionNumber name description billingPeriod
|
|
293
|
+
prices { currency priceInfo { amount taxCategory } }
|
|
294
|
+
metadata isTestVersion isProdVersion createdAt
|
|
295
|
+
}
|
|
296
|
+
}`,
|
|
297
|
+
variables: { productId: "PROD_xxx" },
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 8. Subscription Product Groups
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
const groups = await client.graphql.query({
|
|
305
|
+
query: `query ($storeId: String!) {
|
|
306
|
+
subscriptionProductGroups(storeId: $storeId) {
|
|
307
|
+
id name description
|
|
308
|
+
rules { sharedTrial }
|
|
309
|
+
environment
|
|
310
|
+
products {
|
|
311
|
+
id name billingPeriod
|
|
312
|
+
prices { currency priceInfo { amount taxCategory } }
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}`,
|
|
316
|
+
variables: { storeId: "STO_xxx" },
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 9. Exchange Rate Query
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const rate = await client.graphql.query({
|
|
324
|
+
query: `query {
|
|
325
|
+
rate(fromCurrency: USD, toCurrency: EUR) {
|
|
326
|
+
fromCurrency toCurrency standardRate rateRefId expiryTime
|
|
327
|
+
}
|
|
328
|
+
}`,
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
> `CurrencyCode` is an enum type supporting 40+ ISO 4217 currency codes (e.g. `USD`, `EUR`, `GBP`, `JPY`, `CNY`). Use introspection to get the full list.
|
|
333
|
+
|
|
334
|
+
### 10. Webhook and Email Delivery Logs
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
// Webhook delivery logs (auto-filtered by environment)
|
|
338
|
+
const webhookLogs = await client.graphql.query({
|
|
339
|
+
query: `query ($storeId: String!) {
|
|
340
|
+
webhookDeliveries(storeId: $storeId, limit: 20, filter: { status: { eq: "failed" } }) {
|
|
341
|
+
id storeId eventType eventId
|
|
342
|
+
payload webhookUrl status httpStatus responseBody
|
|
343
|
+
attemptCount lastAttemptedAt createdAt
|
|
344
|
+
}
|
|
345
|
+
webhookDeliveriesCount(storeId: $storeId, filter: { status: { eq: "failed" } })
|
|
346
|
+
}`,
|
|
347
|
+
variables: { storeId: "STO_xxx" },
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Email delivery logs
|
|
351
|
+
const emailLogs = await client.graphql.query({
|
|
352
|
+
query: `query ($storeId: String!) {
|
|
353
|
+
emailDeliveries(storeId: $storeId, limit: 20, filter: { status: { eq: "failed" } }) {
|
|
354
|
+
id storeId eventType eventId
|
|
355
|
+
recipientType toAddress subject testMode
|
|
356
|
+
status attemptCount lastAttemptedAt errorMessage createdAt
|
|
357
|
+
}
|
|
358
|
+
emailDeliveriesCount(storeId: $storeId, filter: { status: { eq: "failed" } })
|
|
359
|
+
}`,
|
|
360
|
+
variables: { storeId: "STO_xxx" },
|
|
361
|
+
});
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 11. Dashboard Overview (Combined Query)
|
|
365
|
+
|
|
366
|
+
Combine multiple queries in a single request to reduce network round trips.
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
interface DashboardQuery {
|
|
370
|
+
store: { name: string; slug: string; status: string } | null;
|
|
371
|
+
onetimeOrdersCount: number;
|
|
372
|
+
subscriptionOrdersCount: number;
|
|
373
|
+
onetimeOrders: Array<{
|
|
374
|
+
id: string;
|
|
375
|
+
buyerEmail: string;
|
|
376
|
+
priceSnapshot: { currency: string; total: string };
|
|
377
|
+
createdAt: string;
|
|
378
|
+
}>;
|
|
379
|
+
refundTickets: Array<{
|
|
380
|
+
id: string;
|
|
381
|
+
requestedAmountDetails: { currency: string; amount: string };
|
|
382
|
+
reason: string;
|
|
383
|
+
createdAt: string;
|
|
384
|
+
}>;
|
|
385
|
+
onetimeProductsCount: number;
|
|
386
|
+
subscriptionProductsCount: number;
|
|
387
|
+
}
|
|
388
|
+
const dashboard = await client.graphql.query<DashboardQuery>({
|
|
389
|
+
query: `query Dashboard($storeId: String!) {
|
|
390
|
+
store(id: $storeId) { name slug status }
|
|
391
|
+
onetimeOrdersCount(storeId: $storeId)
|
|
392
|
+
subscriptionOrdersCount(storeId: $storeId)
|
|
393
|
+
onetimeOrders(storeId: $storeId, limit: 5, filter: { status: { eq: "pending" } }) {
|
|
394
|
+
id buyerEmail priceSnapshot { currency total } createdAt
|
|
395
|
+
}
|
|
396
|
+
refundTickets(limit: 5, filter: { status: { eq: "pending" } }) {
|
|
397
|
+
id requestedAmountDetails { currency amount } reason createdAt
|
|
398
|
+
}
|
|
399
|
+
onetimeProductsCount(storeId: $storeId)
|
|
400
|
+
subscriptionProductsCount(storeId: $storeId)
|
|
401
|
+
}`,
|
|
402
|
+
variables: { storeId: "STO_xxx" },
|
|
403
|
+
});
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Count Queries
|
|
409
|
+
|
|
410
|
+
All list queries have corresponding `*Count` queries that return the total matching a filter — useful for pagination.
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
const counts = await client.graphql.query({
|
|
414
|
+
query: `query ($storeId: String!) {
|
|
415
|
+
storesCount
|
|
416
|
+
storeMerchantsCount
|
|
417
|
+
apiKeysCount
|
|
418
|
+
onetimeProductsCount(storeId: $storeId, filter: { status: { eq: "active" } })
|
|
419
|
+
subscriptionProductsCount(storeId: $storeId)
|
|
420
|
+
subscriptionProductGroupsCount(storeId: $storeId)
|
|
421
|
+
onetimeOrdersCount(storeId: $storeId)
|
|
422
|
+
subscriptionOrdersCount(storeId: $storeId)
|
|
423
|
+
paymentsCount
|
|
424
|
+
refundsCount
|
|
425
|
+
refundTicketsCount
|
|
426
|
+
webhookDeliveriesCount(storeId: $storeId)
|
|
427
|
+
emailDeliveriesCount(storeId: $storeId)
|
|
428
|
+
}`,
|
|
429
|
+
variables: { storeId: "STO_xxx" },
|
|
430
|
+
});
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
> Count queries accept the same `filter` parameter as their corresponding list queries.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Filter Types
|
|
438
|
+
|
|
439
|
+
| Filter Type | Operations | Example Fields |
|
|
440
|
+
|-------------|------------|----------------|
|
|
441
|
+
| `StringFilter` | `eq`, `ne`, `contains`, `startsWith`, `endsWith`, `in` | `status`, `name`, `email`, `currency` |
|
|
442
|
+
| `DateTimeFilter` | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `createdAt`, `updatedAt`, `expiresAt` |
|
|
443
|
+
| `IntFilter` | `eq`, `ne`, `gt`, `gte`, `lt`, `lte` | `amount`, `totalAmount` |
|
|
444
|
+
| `BooleanFilter` | `eq` | `prodEnabled`, `testMode` |
|
|
445
|
+
|
|
446
|
+
> To see which filter fields are available for a specific entity, use introspection:
|
|
447
|
+
> `__type(name: "OnetimeOrderFilter") { fields { name type { name } } }`
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## Analytics Queries
|
|
452
|
+
|
|
453
|
+
Analytics queries provide aggregated statistics, trends, and insights. All analytics queries accept `storeId` (or `storeSlug`) and an `AnalyticsFilterInput` parameter.
|
|
454
|
+
|
|
455
|
+
### AnalyticsFilterInput
|
|
456
|
+
|
|
457
|
+
| Field | Type | Required | Description |
|
|
458
|
+
|-------|------|----------|-------------|
|
|
459
|
+
| `filter.timeRange.startDate` | `String` | Yes | Start time (ISO 8601) |
|
|
460
|
+
| `filter.timeRange.endDate` | `String` | Yes | End time (ISO 8601) |
|
|
461
|
+
| `filter.currency` | `String` | No | Currency filter (ISO 4217) |
|
|
462
|
+
| `filter.status` | `String` | No | Status filter |
|
|
463
|
+
|
|
464
|
+
### TimePeriodGranularity
|
|
465
|
+
|
|
466
|
+
`DAY`, `WEEK`, `MONTH`, `QUARTER`, `YEAR`, `ALL_TIME`
|
|
467
|
+
|
|
468
|
+
### orderStatistics — Order Aggregation
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
const orderStats = await client.graphql.query({
|
|
472
|
+
query: `query ($storeId: String!) {
|
|
473
|
+
orderStatistics(
|
|
474
|
+
storeId: $storeId,
|
|
475
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
476
|
+
) {
|
|
477
|
+
totalCount
|
|
478
|
+
countsByStatus { status count }
|
|
479
|
+
countsByPeriod(granularity: MONTH) { period count }
|
|
480
|
+
revenueByCurrency { currency totalAmount paymentCount }
|
|
481
|
+
revenueByPeriod(granularity: MONTH, currency: "usd") { period currency totalAmount paymentCount }
|
|
482
|
+
buyerMetrics { totalBuyers newBuyers returningBuyers }
|
|
483
|
+
revenueByCountry(currency: "usd") { country totalAmount paymentCount }
|
|
484
|
+
ordersByCountry { country count }
|
|
485
|
+
b2bVsB2cBreakdown(currency: "usd") { isBusiness label totalAmount orderCount }
|
|
486
|
+
revenueByState(country: "US", currency: "usd") { state totalAmount paymentCount }
|
|
487
|
+
}
|
|
488
|
+
}`,
|
|
489
|
+
variables: { storeId: "STO_xxx" },
|
|
490
|
+
});
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### paymentStatistics — Payment Success Rates & Refunds
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
const paymentStats = await client.graphql.query({
|
|
497
|
+
query: `query ($storeId: String!) {
|
|
498
|
+
paymentStatistics(
|
|
499
|
+
storeId: $storeId,
|
|
500
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
501
|
+
) {
|
|
502
|
+
successRate { totalAttempts succeeded failed pending successRate }
|
|
503
|
+
failedReasons { reason count percentage }
|
|
504
|
+
refunds { totalCount succeededCount pendingCount failedCount amountByCurrency { currency totalAmount paymentCount } refundRate }
|
|
505
|
+
methodDistribution { methodType count totalAmount percentage }
|
|
506
|
+
cardBrandDistribution { brand count totalAmount percentage }
|
|
507
|
+
taxSummary { currency totalTax totalPreTax totalAmount paymentCount }
|
|
508
|
+
preTaxRevenueByCurrency { currency totalAmount paymentCount }
|
|
509
|
+
settlementRevenueByCurrency { currency totalAmount paymentCount }
|
|
510
|
+
}
|
|
511
|
+
}`,
|
|
512
|
+
variables: { storeId: "STO_xxx" },
|
|
513
|
+
});
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### productStatistics — Product Rankings & Revenue
|
|
517
|
+
|
|
518
|
+
```typescript
|
|
519
|
+
const productStats = await client.graphql.query({
|
|
520
|
+
query: `query ($storeId: String!) {
|
|
521
|
+
productStatistics(
|
|
522
|
+
storeId: $storeId,
|
|
523
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
524
|
+
) {
|
|
525
|
+
onetimeCountsByStatus { status count }
|
|
526
|
+
subscriptionCountsByStatus { status count }
|
|
527
|
+
onetimeTotalCount
|
|
528
|
+
subscriptionTotalCount
|
|
529
|
+
topByOrderCount(limit: 10) { productId productType productName orderCount totalRevenue currency }
|
|
530
|
+
topByRevenue(limit: 10, currency: "usd") { productId productType productName orderCount totalRevenue currency }
|
|
531
|
+
revenueContribution(currency: "usd") { productId productType productName revenue contributionPercentage cumulativePercentage }
|
|
532
|
+
}
|
|
533
|
+
}`,
|
|
534
|
+
variables: { storeId: "STO_xxx" },
|
|
535
|
+
});
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### trendAnalysis — Growth Trends
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
const trends = await client.graphql.query({
|
|
542
|
+
query: `query ($storeId: String!) {
|
|
543
|
+
trendAnalysis(
|
|
544
|
+
storeId: $storeId,
|
|
545
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
546
|
+
) {
|
|
547
|
+
orderGrowth(granularity: MONTH) { period currentValue previousValue growthRate }
|
|
548
|
+
revenueGrowth(granularity: MONTH, currency: "usd") { period currentValue previousValue growthRate }
|
|
549
|
+
cumulativeRevenue(granularity: MONTH, currency: "usd") { period periodValue cumulativeValue }
|
|
550
|
+
orderMovingAverage(windowDays: 7) { date dailyValue movingAverage }
|
|
551
|
+
revenueMovingAverage(windowDays: 7, currency: "usd") { date dailyValue movingAverage }
|
|
552
|
+
}
|
|
553
|
+
}`,
|
|
554
|
+
variables: { storeId: "STO_xxx" },
|
|
555
|
+
});
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### distributionAnalysis — Amount Distribution & AOV
|
|
559
|
+
|
|
560
|
+
```typescript
|
|
561
|
+
const distribution = await client.graphql.query({
|
|
562
|
+
query: `query ($storeId: String!) {
|
|
563
|
+
distributionAnalysis(
|
|
564
|
+
storeId: $storeId,
|
|
565
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
566
|
+
) {
|
|
567
|
+
orderAmountPercentiles(currency: "usd") { p10 p25 p50 p75 p90 p95 p99 min max avg stddev count }
|
|
568
|
+
aovTrend(granularity: MONTH, currency: "usd") { period averageOrderValue orderCount totalRevenue }
|
|
569
|
+
orderAmountBuckets(currency: "usd", bucketCount: 10) { rangeMin rangeMax count percentage }
|
|
570
|
+
}
|
|
571
|
+
}`,
|
|
572
|
+
variables: { storeId: "STO_xxx" },
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### customerAnalysis — Retention, LTV & Repeat Purchases
|
|
577
|
+
|
|
578
|
+
```typescript
|
|
579
|
+
const customers = await client.graphql.query({
|
|
580
|
+
query: `query ($storeId: String!) {
|
|
581
|
+
customerAnalysis(
|
|
582
|
+
storeId: $storeId,
|
|
583
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
584
|
+
) {
|
|
585
|
+
cohortRetention(granularity: MONTH) {
|
|
586
|
+
cohortPeriod cohortSize
|
|
587
|
+
retention { periodOffset activeCustomers retentionRate }
|
|
588
|
+
}
|
|
589
|
+
ltvDistribution(currency: "usd") {
|
|
590
|
+
averageLtv medianLtv
|
|
591
|
+
buckets { rangeMin rangeMax count percentage }
|
|
592
|
+
}
|
|
593
|
+
purchaseFrequency { purchaseCount customerCount percentage }
|
|
594
|
+
repeatPurchaseRate(granularity: MONTH) { period totalBuyers repeatBuyers repeatRate }
|
|
595
|
+
topCustomers(limit: 10, currency: "usd") { buyerEmail totalSpent orderCount firstPurchaseDate lastPurchaseDate }
|
|
596
|
+
}
|
|
597
|
+
}`,
|
|
598
|
+
variables: { storeId: "STO_xxx" },
|
|
599
|
+
});
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### taxAnalysis — Tax Breakdown
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
const tax = await client.graphql.query({
|
|
606
|
+
query: `query ($storeId: String!) {
|
|
607
|
+
taxAnalysis(
|
|
608
|
+
storeId: $storeId,
|
|
609
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
610
|
+
) {
|
|
611
|
+
byCategory(currency: "usd") { taxCategory totalTax totalAmount paymentCount }
|
|
612
|
+
byRateGroup(currency: "usd") { taxRate totalTax totalAmount paymentCount }
|
|
613
|
+
byCountry(currency: "usd") { country totalTax totalAmount paymentCount }
|
|
614
|
+
b2bVsB2c(currency: "usd") { isBusiness label totalTax totalAmount orderCount }
|
|
615
|
+
effectiveTaxRateTrend(granularity: MONTH, currency: "usd") { period avgTaxRate paymentCount }
|
|
616
|
+
taxAmountByPeriod(granularity: MONTH, currency: "usd") { period totalTax paymentCount }
|
|
617
|
+
}
|
|
618
|
+
}`,
|
|
619
|
+
variables: { storeId: "STO_xxx" },
|
|
620
|
+
});
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### subscriptionAnalysis — Churn, Trial Conversion & Billing
|
|
624
|
+
|
|
625
|
+
```typescript
|
|
626
|
+
const subscriptions = await client.graphql.query({
|
|
627
|
+
query: `query ($storeId: String!) {
|
|
628
|
+
subscriptionAnalysis(
|
|
629
|
+
storeId: $storeId,
|
|
630
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
631
|
+
) {
|
|
632
|
+
billingPeriodDistribution(currency: "usd") { billingPeriod count totalAmount percentage }
|
|
633
|
+
activeCount
|
|
634
|
+
cancellationStats { totalSubscriptions canceledCount cancellationRate avgLifetimeDays medianLifetimeDays }
|
|
635
|
+
cancellationTrend(granularity: MONTH) { period canceledCount }
|
|
636
|
+
trialConversion { totalTrials convertedCount activeTrials conversionRate }
|
|
637
|
+
trialConversionByProduct { productId productName totalTrials convertedCount conversionRate }
|
|
638
|
+
churnRate(granularity: MONTH) { period startActive churned churnRate }
|
|
639
|
+
}
|
|
640
|
+
}`,
|
|
641
|
+
variables: { storeId: "STO_xxx" },
|
|
642
|
+
});
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### refundTicketAnalysis — Refund Reasons & Review Efficiency
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
const refundAnalysis = await client.graphql.query({
|
|
649
|
+
query: `query ($storeId: String!) {
|
|
650
|
+
refundTicketAnalysis(
|
|
651
|
+
storeId: $storeId,
|
|
652
|
+
filter: { timeRange: { startDate: "2025-01-01T00:00:00Z", endDate: "2026-01-01T00:00:00Z" } }
|
|
653
|
+
) {
|
|
654
|
+
reasonDistribution(currency: "usd") { reason count totalAmount percentage }
|
|
655
|
+
statusDistribution { status count percentage }
|
|
656
|
+
reviewEfficiency { avgHours medianHours p90Hours totalReviewed }
|
|
657
|
+
ticketTrend(granularity: MONTH) { period totalCreated resolvedCount approvedCount rejectedCount }
|
|
658
|
+
approvalRate { approved rejected rate }
|
|
659
|
+
processingSuccessRate { succeeded failed rate }
|
|
660
|
+
}
|
|
661
|
+
}`,
|
|
662
|
+
variables: { storeId: "STO_xxx" },
|
|
663
|
+
});
|
|
664
|
+
```
|