@skalpgg/sdk 1.1.0 → 1.4.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.
@@ -1,16 +1,23 @@
1
1
  export type Currency = 'EUR' | 'USD' | 'PLN' | (string & {});
2
- export type FulfillmentType = 'FILE' | 'SERIAL' | 'GAME' | 'SERVICE';
2
+ export type FulfillmentType = 'FILE' | 'SERIAL' | 'GAME' | 'SERVICE' | 'DYNAMIC' | 'LICENSE';
3
+ export type ProductStatus = 'DRAFT' | 'PENDING_REVIEW' | 'PROCESSING' | 'PROCESSING_FAILED' | 'ACTIVE' | 'REJECTED' | 'ARCHIVED';
3
4
  export type ProductType = 'ONE_TIME' | 'RECURRING' | 'COINS';
4
5
  export type BillingInterval = 'WEEK' | 'MONTH' | 'YEAR';
5
- export type OrderStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED';
6
+ export type OrderStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED' | 'CANCELED';
7
+ export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL';
8
+ export type DeliveryStatus = 'PENDING' | 'PROCESSING' | 'DELIVERED' | 'FAILED';
6
9
  export type SubscriptionStatus = 'ACTIVE' | 'CANCELED' | 'PAST_DUE' | 'UNPAID' | 'INCOMPLETE' | 'INCOMPLETE_EXPIRED' | 'TRIALING' | 'PAUSED';
7
10
  export type Metadata = Record<string, string>;
8
11
  export interface CreateCheckoutParams {
9
12
  productId: string;
13
+ /** Units to sell, within the product's minQuantity and maxQuantity. Defaults to minQuantity. */
14
+ quantity?: number;
10
15
  customerEmail?: string;
11
16
  metadata?: Metadata;
12
17
  couponCode?: string;
13
18
  returnUrl?: string;
19
+ /** Answers you already have, by field key; the buyer adds the rest on the pay page. */
20
+ customFields?: Record<string, string>;
14
21
  }
15
22
  export interface CheckoutSession {
16
23
  id: string;
@@ -34,28 +41,534 @@ export interface Order {
34
41
  amount: number;
35
42
  netAmount: number | null;
36
43
  vatAmount: number | null;
44
+ vatRate: number | null;
37
45
  currency: Currency;
46
+ discountAmount: number;
47
+ couponCode: string | null;
38
48
  productId: string;
39
49
  productName: string;
40
50
  productSlug: string;
51
+ /** Units of productId. */
52
+ quantity: number;
41
53
  fulfillmentType: FulfillmentType;
54
+ bundleId: string | null;
42
55
  buyerEmail: string;
56
+ buyerCountry: string | null;
57
+ paymentProvider: PaymentProvider | null;
58
+ isGift: boolean;
59
+ granted?: boolean;
60
+ deliveryStatus: DeliveryStatus | null;
43
61
  serialsCount?: number;
62
+ serialsReplaced?: number;
63
+ /** Delivered and replaced keys by id, never their values. Only orders.get and orders.cancel fill it in. */
64
+ serials?: Array<OrderSerial>;
44
65
  createdAt: string;
66
+ updatedAt: string;
45
67
  completedAt: string | null;
46
68
  metadata: Metadata;
69
+ /** One entry per product: a bundle or a cart order has several. */
70
+ items?: Array<OrderItem>;
71
+ replacements?: Array<OrderReplacement>;
72
+ }
73
+ export interface OrderSerial {
74
+ id: string;
75
+ productId: string;
76
+ status: 'DELIVERED' | 'REPLACED';
77
+ deliveredAt: string | null;
78
+ /** The serial that took this one's place, once replaced. */
79
+ replacedById: string | null;
80
+ }
81
+ export interface OrderReplacement {
82
+ id: string;
83
+ productId: string;
84
+ oldSerialId: string | null;
85
+ newSerialId: string | null;
86
+ reason: string | null;
87
+ source: string;
88
+ createdAt: string;
89
+ }
90
+ export interface ListOrdersParams {
91
+ status?: OrderStatus;
92
+ productId?: string;
93
+ email?: string;
94
+ createdAfter?: string | Date;
95
+ createdBefore?: string | Date;
96
+ updatedSince?: string | Date;
97
+ limit?: number;
98
+ offset?: number;
99
+ }
100
+ export interface OrderList {
101
+ data: Array<Order>;
102
+ total: number;
103
+ limit: number;
104
+ offset: number;
105
+ }
106
+ export interface ReplaceOrderKeysParams {
107
+ serialIds?: Array<string>;
108
+ values?: Array<string>;
109
+ reason?: string;
110
+ }
111
+ export interface OrderKeyReplacement {
112
+ productId: string;
113
+ productName: string;
114
+ oldSerialId: string;
115
+ newSerialId: string;
116
+ value: string;
117
+ }
118
+ export interface OrderKeysReplaced {
119
+ orderId: string;
120
+ replacements: Array<OrderKeyReplacement>;
121
+ }
122
+ export interface OrderItem {
123
+ productId: string;
124
+ name: string;
125
+ /** Per unit, after every discount. */
126
+ price: number | null;
127
+ quantity: number;
128
+ /** The buyer's answers to the product's custom fields. */
129
+ customFields: Record<string, string>;
130
+ }
131
+ /** Another product of the store, discountPercent off when bought with this one. */
132
+ export interface ProductSale {
133
+ title: string | null;
134
+ discountPercent: number;
135
+ price: number;
136
+ endsAt: string;
137
+ remaining: number | null;
138
+ }
139
+ export interface ProductUpsell {
140
+ productId: string;
141
+ discountPercent: number;
142
+ }
143
+ export interface ProductUpsellInput {
144
+ productId: string;
145
+ /** 0 to 90; defaults to 0. */
146
+ discountPercent?: number;
147
+ }
148
+ /** An order of at least quantity units costs percent less. */
149
+ export interface VolumeDiscount {
150
+ quantity: number;
151
+ percent: number;
152
+ }
153
+ export type CustomFieldType = 'text' | 'textarea' | 'number' | 'email' | 'checkbox' | 'select' | 'hidden';
154
+ /** A question the buyer answers at checkout. */
155
+ export interface CustomField {
156
+ key: string;
157
+ label: string;
158
+ type: CustomFieldType;
159
+ required: boolean;
160
+ placeholder: string | null;
161
+ options: Array<string>;
47
162
  }
163
+ export interface CustomFieldInput {
164
+ /** Lowercase letters, digits and underscores, starting with a letter. */
165
+ key: string;
166
+ label: string;
167
+ type: CustomFieldType;
168
+ required?: boolean;
169
+ placeholder?: string | null;
170
+ /** For select: up to 20 choices. */
171
+ options?: Array<string>;
172
+ }
173
+ export type DeliveryType = 'COMMAND' | 'SQL';
174
+ /**
175
+ * PUBLIC is listed and buyable, UNLISTED is buyable from its link only,
176
+ * ON_HOLD is listed but not buyable, PRIVATE sells only through the API.
177
+ */
178
+ export type ProductVisibility = 'PUBLIC' | 'UNLISTED' | 'ON_HOLD' | 'PRIVATE';
48
179
  export interface Product {
49
180
  id: string;
181
+ storeId: string;
50
182
  name: string;
51
183
  slug: string;
184
+ description: string;
185
+ shortDescription: string | null;
52
186
  price: number;
187
+ comparePrice: number | null;
53
188
  currency: Currency;
54
- fulfillmentType: FulfillmentType;
189
+ status: ProductStatus;
190
+ rejectionReason: string | null;
55
191
  productType: ProductType;
56
192
  billingInterval: BillingInterval | null;
57
193
  trialPeriodDays: number;
58
- stock?: number;
194
+ fulfillmentType: FulfillmentType | null;
195
+ category: string;
196
+ categoryId: string | null;
197
+ storeCategoryId: string | null;
198
+ tags: Array<string>;
199
+ images: Array<string>;
200
+ videoUrl: string | null;
201
+ licenseDeviceLimit: number;
202
+ licenseDurationDays: number | null;
203
+ dynamicUrl: string | null;
204
+ /** Server stores: COMMAND or SQL. */
205
+ deliveryType: DeliveryType | null;
206
+ /** Server stores: what the game server runs after payment. */
207
+ deliveryPayload: string | null;
208
+ visibility: ProductVisibility;
209
+ /** Higher comes first on the store page. */
210
+ sortPriority: number;
211
+ /** Shown to the buyer after paying. */
212
+ deliveryNote: string | null;
213
+ /** The buyer accepts them before paying. */
214
+ termsOfService: string | null;
215
+ warrantyDays: number | null;
216
+ warrantyText: string | null;
217
+ blockVpn: boolean;
218
+ maxRiskScore: number | null;
219
+ customFields: Array<CustomField>;
220
+ minQuantity: number;
221
+ /** null allows up to 1000. */
222
+ maxQuantity: number | null;
223
+ volumeDiscounts: Array<VolumeDiscount>;
224
+ /** Products offered on this product's checkout page. */
225
+ upsells: Array<ProductUpsell>;
226
+ stock: number | null;
227
+ sale: ProductSale | null;
228
+ salesCount: number;
229
+ rating: number | null;
230
+ reviewCount: number;
231
+ url: string;
232
+ createdAt: string;
233
+ updatedAt: string;
234
+ }
235
+ export interface ListProductsParams {
236
+ status?: ProductStatus | 'all';
237
+ }
238
+ interface ProductFields {
239
+ slug?: string;
240
+ description?: string;
241
+ shortDescription?: string;
242
+ category?: string;
243
+ categoryId?: string;
244
+ storeCategoryId?: string | null;
245
+ tags?: Array<string>;
246
+ images?: Array<string>;
247
+ videoUrl?: string;
248
+ fulfillmentType?: FulfillmentType;
249
+ billingInterval?: BillingInterval;
250
+ trialPeriodDays?: number;
251
+ dynamicUrl?: string | null;
252
+ licenseDeviceLimit?: number;
253
+ licenseDurationDays?: number | null;
254
+ /** Required for a server store, refused for the others. */
255
+ deliveryType?: DeliveryType;
256
+ /** Required for a server store; needs a placeholder such as {steamhex}. */
257
+ deliveryPayload?: string;
258
+ visibility?: ProductVisibility;
259
+ sortPriority?: number;
260
+ /** null or an empty string clears it. */
261
+ deliveryNote?: string | null;
262
+ /** null or an empty string clears it. */
263
+ termsOfService?: string | null;
264
+ warrantyDays?: number | null;
265
+ warrantyText?: string | null;
266
+ blockVpn?: boolean;
267
+ maxRiskScore?: number | null;
268
+ /** Up to 10 questions; the list replaces the old one, [] or null removes them all. */
269
+ customFields?: Array<CustomFieldInput> | null;
270
+ /** SERIAL, LICENSE, SERVICE and GAME one-time products only. */
271
+ minQuantity?: number;
272
+ maxQuantity?: number | null;
273
+ /** Up to 10 tiers; the list replaces the old one, [] or null removes them all. */
274
+ volumeDiscounts?: Array<VolumeDiscount> | null;
275
+ /** Up to 3 one-time products of the store; the list replaces the old one, [] or null removes them all. */
276
+ upsells?: Array<ProductUpsellInput> | null;
277
+ }
278
+ export interface CreateProductParams extends ProductFields {
279
+ name: string;
280
+ price: number;
281
+ comparePrice?: number;
282
+ productType?: 'ONE_TIME' | 'RECURRING';
283
+ submit?: boolean;
284
+ }
285
+ export interface UpdateProductParams extends ProductFields {
286
+ name?: string;
287
+ price?: number;
288
+ comparePrice?: number | null;
289
+ status?: 'DRAFT' | 'ARCHIVED';
290
+ }
291
+ export interface ProductStock {
292
+ productId: string;
293
+ available: number;
294
+ delivered: number;
295
+ revoked: number;
296
+ total: number;
297
+ }
298
+ export type SerialStatus = 'AVAILABLE' | 'DELIVERED' | 'REVOKED';
299
+ export type SerialSource = 'POOL' | 'DYNAMIC' | 'MANUAL';
300
+ export interface Serial {
301
+ id: string;
302
+ value: string;
303
+ status: SerialStatus | 'REPLACED';
304
+ source: SerialSource;
305
+ orderId: string | null;
306
+ createdAt: string;
307
+ deliveredAt: string | null;
308
+ }
309
+ export interface ListSerialsParams {
310
+ status?: SerialStatus;
311
+ limit?: number;
312
+ offset?: number;
313
+ }
314
+ export interface SerialList {
315
+ data: Array<Serial>;
316
+ total: number;
317
+ limit: number;
318
+ offset: number;
319
+ }
320
+ export interface AddSerialsParams {
321
+ serials?: Array<string>;
322
+ text?: string;
323
+ delimiter?: 'newline' | 'comma' | 'semicolon' | (string & {});
324
+ }
325
+ export interface AddSerialsResult {
326
+ added: number;
327
+ skipped: number;
328
+ stock: number;
329
+ }
330
+ export interface Deleted {
331
+ id: string;
332
+ deleted: true;
333
+ }
334
+ export interface StoreCategory {
335
+ id: string;
336
+ name: string;
337
+ sortOrder: number;
338
+ createdAt: string;
339
+ }
340
+ export interface StoreCategoryWithCount extends StoreCategory {
341
+ activeProducts: number;
342
+ }
343
+ export interface CreateStoreCategoryParams {
344
+ name: string;
345
+ }
346
+ export interface UpdateStoreCategoryParams {
347
+ name?: string;
348
+ sortOrder?: number;
349
+ }
350
+ export interface ProductGroupItem {
351
+ id: string;
352
+ name: string;
353
+ slug: string;
354
+ status: ProductStatus;
355
+ price: number;
356
+ }
357
+ export interface ProductGroup {
358
+ id: string;
359
+ storeId: string;
360
+ title: string;
361
+ description: string | null;
362
+ image: string | null;
363
+ sortPriority: number;
364
+ unlisted: boolean;
365
+ productIds: Array<string>;
366
+ products: Array<ProductGroupItem>;
367
+ createdAt: string;
368
+ updatedAt: string;
369
+ }
370
+ export interface CreateProductGroupParams {
371
+ title: string;
372
+ productIds: Array<string>;
373
+ description?: string | null;
374
+ image?: string | null;
375
+ sortPriority?: number;
376
+ unlisted?: boolean;
377
+ }
378
+ export interface UpdateProductGroupParams {
379
+ title?: string;
380
+ productIds?: Array<string>;
381
+ description?: string | null;
382
+ image?: string | null;
383
+ sortPriority?: number;
384
+ unlisted?: boolean;
385
+ }
386
+ export type CouponDiscountType = 'PERCENT' | 'FIXED';
387
+ export interface Coupon {
388
+ id: string;
389
+ code: string;
390
+ description: string | null;
391
+ discountType: CouponDiscountType;
392
+ discountPercent: number | null;
393
+ discountAmount: number | null;
394
+ productIds: Array<string>;
395
+ disabledWithVolumeDiscounts: boolean;
396
+ validFrom: string;
397
+ validTo: string | null;
398
+ maxUses: number | null;
399
+ usedCount: number;
400
+ minPurchaseAmount: number | null;
401
+ oneTimePerUser: boolean;
402
+ isActive: boolean;
403
+ createdAt: string;
404
+ updatedAt: string;
405
+ }
406
+ export interface CreateCouponParams {
407
+ code: string;
408
+ discountType?: CouponDiscountType;
409
+ discountPercent?: number;
410
+ discountAmount?: number;
411
+ productIds?: Array<string>;
412
+ disabledWithVolumeDiscounts?: boolean;
413
+ description?: string;
414
+ validFrom?: string | Date;
415
+ validTo?: string | Date;
416
+ maxUses?: number;
417
+ minPurchaseAmount?: number;
418
+ oneTimePerUser?: boolean;
419
+ }
420
+ export interface UpdateCouponParams {
421
+ discountType?: CouponDiscountType;
422
+ discountPercent?: number;
423
+ discountAmount?: number;
424
+ productIds?: Array<string>;
425
+ disabledWithVolumeDiscounts?: boolean;
426
+ description?: string | null;
427
+ validFrom?: string | Date;
428
+ validTo?: string | Date | null;
429
+ maxUses?: number | null;
430
+ minPurchaseAmount?: number | null;
431
+ oneTimePerUser?: boolean;
432
+ isActive?: boolean;
433
+ }
434
+ export interface Customer {
435
+ id: string;
436
+ email: string;
437
+ name: string | null;
438
+ note: string | null;
439
+ country: string | null;
440
+ ordersCount: number;
441
+ totalSpent: number;
442
+ currency: Currency;
443
+ firstOrderAt: string | null;
444
+ lastOrderAt: string | null;
445
+ createdAt: string;
446
+ updatedAt: string;
447
+ }
448
+ export interface CustomerDetails extends Customer {
449
+ recentOrders: Array<Order>;
450
+ }
451
+ export interface ListCustomersParams {
452
+ search?: string;
453
+ limit?: number;
454
+ offset?: number;
455
+ }
456
+ export interface CustomerList {
457
+ data: Array<Customer>;
458
+ total: number;
459
+ limit: number;
460
+ offset: number;
461
+ }
462
+ export interface CreateCustomerParams {
463
+ email: string;
464
+ name?: string;
465
+ note?: string;
466
+ }
467
+ export interface UpdateCustomerParams {
468
+ name?: string | null;
469
+ note?: string | null;
470
+ }
471
+ export interface FeedbackReply {
472
+ id: string;
473
+ content: string;
474
+ createdAt: string;
475
+ }
476
+ export type FeedbackAppealStatus = 'PENDING' | 'ACCEPTED' | 'REJECTED';
477
+ export interface FeedbackAppeal {
478
+ id: string;
479
+ status: FeedbackAppealStatus;
480
+ reason: string;
481
+ adminNote: string | null;
482
+ createdAt: string;
483
+ resolvedAt: string | null;
484
+ }
485
+ export interface Feedback {
486
+ id: string;
487
+ productId: string;
488
+ productName: string;
489
+ rating: number;
490
+ title: string | null;
491
+ content: string | null;
492
+ customerName: string | null;
493
+ verified: boolean;
494
+ helpfulCount: number;
495
+ replies: Array<FeedbackReply>;
496
+ appeal: FeedbackAppeal | null;
497
+ createdAt: string;
498
+ updatedAt: string;
499
+ }
500
+ export interface ListFeedbackParams {
501
+ productId?: string;
502
+ rating?: number;
503
+ limit?: number;
504
+ offset?: number;
505
+ }
506
+ export interface FeedbackList {
507
+ data: Array<Feedback>;
508
+ total: number;
509
+ limit: number;
510
+ offset: number;
511
+ }
512
+ export interface ReplyParams {
513
+ message: string;
514
+ }
515
+ export interface AppealFeedbackParams {
516
+ reason: string;
517
+ }
518
+ export type QueryStatus = 'PENDING' | 'SHOP_REPLY' | 'CUSTOMER_REPLY' | 'CLOSED';
519
+ export interface QueryMessage {
520
+ id: string;
521
+ content: string;
522
+ from: 'customer' | 'shop';
523
+ createdAt: string;
524
+ }
525
+ export interface SupportQuery {
526
+ id: string;
527
+ title: string | null;
528
+ status: QueryStatus;
529
+ customerEmail: string;
530
+ customerName: string | null;
531
+ productId: string | null;
532
+ productName: string | null;
533
+ orderId: string | null;
534
+ orderNumber: string | null;
535
+ messageCount: number;
536
+ lastMessage: QueryMessage | null;
537
+ closedAt: string | null;
538
+ createdAt: string;
539
+ updatedAt: string;
540
+ }
541
+ export interface SupportQueryDetails extends SupportQuery {
542
+ messages: Array<QueryMessage>;
543
+ }
544
+ export interface ListQueriesParams {
545
+ status?: QueryStatus;
546
+ limit?: number;
547
+ offset?: number;
548
+ }
549
+ export interface SupportQueryList {
550
+ data: Array<SupportQuery>;
551
+ total: number;
552
+ limit: number;
553
+ offset: number;
554
+ }
555
+ export type AccessList = 'BLACKLIST' | 'WHITELIST';
556
+ export type AccessRuleType = 'EMAIL' | 'IP' | 'COUNTRY' | 'ISP' | 'ASN' | 'HOST';
557
+ export interface AccessRule {
558
+ id: string;
559
+ list: AccessList;
560
+ type: AccessRuleType;
561
+ value: string;
562
+ note: string | null;
563
+ createdAt: string;
564
+ }
565
+ export interface ListAccessRulesParams {
566
+ type?: AccessRuleType;
567
+ }
568
+ export interface AddAccessRuleParams {
569
+ type: AccessRuleType;
570
+ value: string;
571
+ note?: string;
59
572
  }
60
573
  export interface CreateSubscriptionCheckoutParams {
61
574
  productId?: string;
@@ -118,6 +631,14 @@ export interface SubscriptionList {
118
631
  limit: number;
119
632
  offset: number;
120
633
  }
634
+ export interface InvoiceLine {
635
+ description: string | null;
636
+ amount: number;
637
+ currency: Currency;
638
+ periodStart: string;
639
+ periodEnd: string;
640
+ usageChargeId?: string;
641
+ }
121
642
  export interface Invoice {
122
643
  id: string;
123
644
  number: string | null;
@@ -128,6 +649,46 @@ export interface Invoice {
128
649
  status: string | null;
129
650
  hostedUrl: string | null;
130
651
  pdfUrl: string | null;
652
+ lines: Array<InvoiceLine>;
653
+ }
654
+ export interface CreateUsageChargeParams {
655
+ amount: number;
656
+ currency: 'EUR' | 'USD' | 'PLN';
657
+ description: string;
658
+ idempotencyKey: string;
659
+ periodStart: string | Date;
660
+ periodEnd: string | Date;
661
+ }
662
+ export interface UsageCharge {
663
+ id: string;
664
+ invoiceId: string | null;
665
+ hostedUrl: string | null;
666
+ amount: number;
667
+ currency: Currency;
668
+ status: 'paid' | 'open' | 'pending';
669
+ }
670
+ export interface CreateCoinCheckoutParams {
671
+ steamHex: string;
672
+ coins: number;
673
+ idempotencyKey?: string;
674
+ returnUrl?: string;
675
+ }
676
+ export interface CoinCheckout {
677
+ checkoutUrl: string;
678
+ reference: string;
679
+ coins: number;
680
+ baseCoins: number;
681
+ bonusCoins: number;
682
+ amount: number;
683
+ amountIsNet: boolean;
684
+ currency: Currency;
685
+ expiresAt: string;
686
+ }
687
+ export interface CoinCheckoutStatus {
688
+ status: 'pending' | 'paid' | 'failed' | 'refunded';
689
+ coins: number;
690
+ deliveryStatus: DeliveryStatus | null;
691
+ paidAt: string | null;
131
692
  }
132
693
  export interface VerifyLicenseParams {
133
694
  licenseKey: string;
@@ -136,6 +697,36 @@ export interface VerifyLicenseParams {
136
697
  serverPort?: number;
137
698
  }
138
699
  export type LicenseError = 'INVALID_FORMAT' | 'INVALID_LICENSE' | 'LICENSE_INACTIVE' | 'LICENSE_EXPIRED' | 'PRODUCT_INACTIVE' | 'SERVER_NOT_ACTIVATED' | 'SERVER_KEY_REQUIRED' | 'SERVER_KEY_MISMATCH' | 'RATE_LIMITED' | 'REPLAY_DETECTED' | (string & {});
700
+ export interface ValidateLicenseParams {
701
+ key: string;
702
+ productId?: string;
703
+ hardwareId?: string;
704
+ }
705
+ export interface ResetLicenseDevicesParams {
706
+ key: string;
707
+ hardwareId?: string;
708
+ }
709
+ export type LicenseCheckCode = 'VALID' | 'NOT_FOUND' | 'PRODUCT_MISMATCH' | 'LICENSING_DISABLED' | 'REVOKED' | 'SUSPENDED' | 'EXPIRED' | 'SUBSCRIPTION_INACTIVE' | 'DEVICE_LIMIT_REACHED';
710
+ export interface LicenseKeyInfo {
711
+ key: string;
712
+ status: 'ACTIVE' | 'SUSPENDED' | 'REVOKED' | 'EXPIRED';
713
+ productId: string;
714
+ productName: string;
715
+ orderId: string | null;
716
+ subscriptionId: string | null;
717
+ createdAt: string;
718
+ expiresAt: string | null;
719
+ devices: {
720
+ used: number;
721
+ limit: number | null;
722
+ };
723
+ }
724
+ export interface LicenseValidation {
725
+ valid: boolean;
726
+ code: LicenseCheckCode;
727
+ message: string;
728
+ license?: LicenseKeyInfo;
729
+ }
139
730
  export interface LicenseVerification {
140
731
  valid: boolean;
141
732
  error?: LicenseError;
@@ -182,6 +773,7 @@ export interface OrderPaidData {
182
773
  amount: number;
183
774
  currency: Currency;
184
775
  quantity: number;
776
+ granted?: boolean;
185
777
  coins?: number;
186
778
  baseCoins?: number;
187
779
  bonusCoins?: number;
@@ -189,19 +781,24 @@ export interface OrderPaidData {
189
781
  steamhex: string | null;
190
782
  identifier: string | null;
191
783
  metadata: Metadata;
784
+ /** The buyer's answers to the product's custom fields. */
785
+ customFields: Record<string, string>;
192
786
  deliveryType?: string;
193
787
  deliveryCommand?: string;
194
788
  }
195
789
  export interface OrderRefundedData {
196
790
  orderId: string;
197
791
  orderNumber: string;
198
- refundId: string;
792
+ refundId: string | null;
199
793
  amount: number;
200
794
  reason: string | null;
201
795
  identifier: string | null;
202
796
  steamHex: string | null;
203
797
  coins?: number;
204
798
  giftRecipient: boolean;
799
+ granted?: boolean;
800
+ fullRefund: boolean;
801
+ licenses: Array<WebhookLicense>;
205
802
  }
206
803
  export interface OrderDisputedData {
207
804
  orderId: string;
@@ -210,8 +807,9 @@ export interface OrderDisputedData {
210
807
  reason: string;
211
808
  steamHex: string | null;
212
809
  identifier: string | null;
213
- coins?: number;
810
+ coins: number;
214
811
  banned: boolean;
812
+ licenses: Array<WebhookLicense>;
215
813
  }
216
814
  export interface AccountRestoreData {
217
815
  identifier: string;
@@ -237,14 +835,75 @@ export interface SubscriptionEventData {
237
835
  canceledAt: string | null;
238
836
  trialEnd: string | null;
239
837
  metadata: Metadata;
838
+ identifier: string | null;
839
+ steamhex: string | null;
240
840
  idempotencyKey: string;
841
+ licenseId: string | null;
842
+ licenseKey: string | null;
843
+ licenseStatus: string | null;
844
+ licenseExpiresAt: string | null;
845
+ }
846
+ export interface ProductEventData {
847
+ productId: string;
848
+ productName: string;
849
+ productSlug: string;
850
+ status: ProductStatus;
851
+ price: number;
852
+ fulfillmentType: FulfillmentType | null;
853
+ productType: ProductType;
854
+ }
855
+ export interface ProductStockData {
856
+ productId: string;
857
+ productName: string;
858
+ productSlug: string;
859
+ stock: number;
860
+ previousStock: number;
861
+ change: number;
241
862
  }
242
863
  export interface WebhookTestData {
243
864
  message: string;
244
865
  webhookId: string;
245
866
  sample: Partial<OrderPaidData>;
246
867
  }
247
- export type SkalpEvent = Envelope<'order.paid' | 'purchase.completed', OrderPaidData> | Envelope<'order.refunded', OrderRefundedData> | Envelope<'order.disputed' | 'account.suspend', OrderDisputedData> | Envelope<'account.restore', AccountRestoreData> | Envelope<'subscription.created' | 'subscription.updated', SubscriptionEventData> | Envelope<'subscription.renewed', SubscriptionEventData & {
868
+ export type OrderEventData = Omit<Order, 'serialsCount' | 'serialsReplaced' | 'serials' | 'replacements'> & {
869
+ previousStatus: OrderStatus | null;
870
+ /** Dedupe key: `order.created:<orderId>`, `order.updated:<orderId>:<transition>` or `order.canceled:<orderId>`. */
871
+ idempotencyKey: string;
872
+ };
873
+ export interface OrderReplacedData extends Omit<Order, 'serialsCount' | 'serialsReplaced' | 'serials' | 'replacements'> {
874
+ /** Dedupe key: `order.replaced:<orderId>:<first new serial id>`. */
875
+ idempotencyKey: string;
876
+ reason: string | null;
877
+ replacements: Array<OrderKeyReplacement>;
878
+ }
879
+ export interface QueryEventData {
880
+ /** Dedupe key: `query.created:<queryId>` or `query.replied:<messageId>`. */
881
+ idempotencyKey: string;
882
+ queryId: string;
883
+ title: string;
884
+ status: QueryStatus;
885
+ customerEmail: string;
886
+ productId: string | null;
887
+ orderId: string | null;
888
+ message: {
889
+ id: string;
890
+ content: string;
891
+ createdAt: string;
892
+ };
893
+ }
894
+ export interface FeedbackReceivedData {
895
+ /** Dedupe key: `feedback.received:<feedbackId>`. */
896
+ idempotencyKey: string;
897
+ feedbackId: string;
898
+ productId: string;
899
+ productName: string;
900
+ rating: number;
901
+ title: string | null;
902
+ content: string | null;
903
+ customerName: string | null;
904
+ createdAt: string;
905
+ }
906
+ export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.canceled', OrderEventData> | Envelope<'order.replaced', OrderReplacedData> | Envelope<'order.paid' | 'purchase.completed', OrderPaidData> | Envelope<'order.refunded', OrderRefundedData> | Envelope<'order.disputed' | 'account.suspend', OrderDisputedData> | Envelope<'account.restore', AccountRestoreData> | Envelope<'subscription.created' | 'subscription.updated' | 'subscription.trial_started' | 'subscription.trial_ended' | 'subscription.upcoming', SubscriptionEventData> | Envelope<'subscription.renewed', SubscriptionEventData & {
248
907
  invoiceId: string;
249
908
  amountPaid: number;
250
909
  periodExtendedTo: string;
@@ -254,7 +913,16 @@ export type SkalpEvent = Envelope<'order.paid' | 'purchase.completed', OrderPaid
254
913
  nextPaymentAttempt: string | null;
255
914
  }> | Envelope<'subscription.canceled', SubscriptionEventData & {
256
915
  endedAt: string | null;
257
- cancelReason: 'requested' | 'payment_failure' | 'stripe';
258
- }> | Envelope<'webhook.test', WebhookTestData>;
916
+ cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe';
917
+ }> | Envelope<'subscription.refunded', SubscriptionEventData & {
918
+ invoiceId: string;
919
+ amountRefunded: number;
920
+ fullyRefunded: boolean;
921
+ }> | Envelope<'subscription.disputed', SubscriptionEventData & {
922
+ invoiceId: string;
923
+ disputeId: string;
924
+ disputeStatus: 'open' | 'won' | 'lost';
925
+ disputeReason: string | null;
926
+ }> | Envelope<'product.created' | 'product.updated', ProductEventData> | Envelope<'product.stock', ProductStockData> | Envelope<'query.created' | 'query.replied', QueryEventData> | Envelope<'feedback.received', FeedbackReceivedData> | Envelope<'webhook.test', WebhookTestData>;
259
927
  export type SkalpEventType = SkalpEvent['type'];
260
928
  export {};