@skalpgg/sdk 1.7.0 → 1.8.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/README.md CHANGED
@@ -41,7 +41,8 @@ Create the key on the API keys page of your dashboard. Each key is bound to one
41
41
 
42
42
  | Method | Scope |
43
43
  | --- | --- |
44
- | `checkout.create({ productId, quantity?, customerEmail?, metadata?, couponCode?, returnUrl?, customFields? })` | `checkout:write` |
44
+ | `me()` | none |
45
+ | `checkout.create({ productId, quantity?, customerEmail?, metadata?, couponCode?, returnUrl?, customFields?, player? })` | `checkout:write` |
45
46
  | `checkout.get(id)` | `checkout:read` |
46
47
  | `orders.list({ status?, productId?, email?, identifier?, createdAfter?, createdBefore?, updatedSince?, limit?, offset? })` | `orders:read` |
47
48
  | `orders.get(id)` | `orders:read` |
@@ -63,7 +64,7 @@ Create the key on the API keys page of your dashboard. Each key is bound to one
63
64
  | `groups.list()` / `groups.get(id)` | `products:read` |
64
65
  | `groups.create({ title, productIds, ... })` / `groups.update(id, { ... })` / `groups.delete(id)` | `products:write` |
65
66
  | `coupons.list()` / `coupons.get(id)` | `coupons:read` |
66
- | `coupons.create({ code, discountType?, discountPercent?, discountAmount?, validFrom?, validTo?, maxUses?, ... })` / `coupons.update(id, { ... })` / `coupons.delete(id)` | `coupons:write` |
67
+ | `coupons.create({ code, discountType?, discountPercent?, discountAmount?, validFrom?, validTo?, maxUses?, subscriptionDuration?, subscriptionMonths?, ... })` / `coupons.update(id, { ... })` / `coupons.delete(id)` | `coupons:write` |
67
68
  | `customers.list({ search?, limit?, offset? })` / `customers.get(id)` | `customers:read` |
68
69
  | `customers.create({ email, name?, note? })` / `customers.update(id, { name?, note? })` / `customers.delete(id)` | `customers:write` |
69
70
  | `feedback.list({ productId?, rating?, limit?, offset? })` / `feedback.get(id)` | `feedback:read` |
@@ -86,6 +87,8 @@ Create the key on the API keys page of your dashboard. Each key is bound to one
86
87
  | `licenses.resetDevices({ key, hardwareId? })` | `licenses:write` |
87
88
  | `licenses.verify({ licenseKey, serverIp, serverKey, serverPort? })` | none |
88
89
  | `licenses.heartbeat({ licenseKey, serverIp })` | none |
90
+ | `webhooks.list()` | `webhooks:read` |
91
+ | `webhooks.create({ url, events, productIds? })` / `webhooks.delete(id)` | `webhooks:write` |
89
92
  | `webhooks.constructEvent(rawBody, headers)` | none |
90
93
  | `webhooks.verify(rawBody, headers)` | none |
91
94
 
@@ -135,7 +138,9 @@ const { replacements } = await skalp.orders.replace(order.id, { reason: 'Key doe
135
138
 
136
139
  `updatedSince` lists oldest change first, so you can page through it and keep the last `updatedAt` as your cursor; without it, newest orders come first. Amounts are in major units (`19.5`).
137
140
 
138
- Coupons take `validFrom`, `validTo` as an ISO string or a `Date`; `coupons.update` accepts `null` to clear `validTo`, `maxUses`, `minPurchaseAmount` and `description`.
141
+ Coupons take `validFrom`, `validTo` as an ISO string or a `Date`; `coupons.update` accepts `null` to clear `validTo`, `maxUses`, `minPurchaseAmount`, `subscriptionMonths` and `description`. On a subscription, `subscriptionDuration` sets how long the discount lasts: `ONCE` (the default), `REPEATING` for `subscriptionMonths` (1 to 36) or `FOREVER`.
142
+
143
+ `me()` returns the store and the key you are using, with its scopes. `checkout.create` takes `player`, a `name` and game `ids` such as `steamid64` or `mc_name`, when your server already knows who gets the order. Orders carry `serviceFee`, the buyer fee included in `amount`, and customers carry `spent`, one total per currency.
139
144
 
140
145
  ## Support and access rules
141
146
 
@@ -180,9 +185,15 @@ export async function POST(request: Request) {
180
185
  }
181
186
  ```
182
187
 
188
+ `webhooks.create` returns the endpoint's signing `secret` once, so store it then. `events` takes event names or `'*'` for all of them.
189
+
190
+ ```ts
191
+ const { id, secret } = await skalp.webhooks.create({ url: 'https://example.com/skalp', events: ['order.paid', 'subscription.renewed'] })
192
+ ```
193
+
183
194
  A webhook with the default events receives every purchase as both `order.paid` and its legacy name `purchase.completed`. Handle `order.paid` and deduplicate on `data.idempotencyKey`.
184
195
 
185
- `order.created`, `order.updated`, `order.canceled`, `order.replaced`, `query.created`, `query.replied`, `feedback.received` and the subscription events `subscription.updated`, `subscription.trial_started`, `subscription.trial_ended` and `subscription.upcoming` are not in the default list either: subscribe the webhook to them by name, and `event.type` narrows `event.data` to the right payload. `order.created`, `order.updated` and `order.canceled` carry the order as `orders.get` returns it, plus `previousStatus`; `order.replaced` adds `reason` and the new keys in `replacements[].key`. Every one of them, like `query.created`, `query.replied` and `feedback.received`, carries a `data.idempotencyKey` that stays the same on every retry of the same event, so deduplicate on it. `subscription.trial_started` follows `subscription.created` when a subscription starts with a trial, free or paid, `subscription.trial_ended` comes when the trial is over, and `subscription.upcoming` comes before a renewal is charged.
196
+ `order.created`, `order.updated`, `order.canceled`, `order.replaced`, `query.created`, `query.replied`, `feedback.received` and the subscription events `subscription.trial_started`, `subscription.trial_ended` and `subscription.upcoming` are not in the default list either: subscribe the webhook to them by name, and `event.type` narrows `event.data` to the right payload. `order.created`, `order.updated` and `order.canceled` carry the order as `orders.get` returns it, plus `previousStatus`; `order.replaced` adds `reason` and the new keys in `replacements[].key`. Every one of them, like `query.created`, `query.replied` and `feedback.received`, carries a `data.idempotencyKey` that stays the same on every retry of the same event, so deduplicate on it. `subscription.trial_started` follows `subscription.created` when a subscription starts with a trial, free or paid, `subscription.trial_ended` comes when the trial is over, and `subscription.upcoming` comes before a renewal is charged.
186
197
 
187
198
  `product.created`, `product.updated` and `product.stock` are not in the default list: subscribe the webhook to them by name. `product.stock` carries `stock`, `previousStock` and `change` whenever the number of available keys changes.
188
199
 
@@ -1,6 +1,6 @@
1
- import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams } from './types.js';
1
+ import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, CreateWebhookParams, CreatedWebhookEndpoint, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Me, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams, WebhookEndpoint } from './types.js';
2
2
  export type * from './types.js';
3
- export declare const VERSION = "1.7.0";
3
+ export declare const VERSION = "1.8.0";
4
4
  export interface SkalpOptions {
5
5
  apiKey?: string;
6
6
  webhookSecret?: string;
@@ -31,8 +31,9 @@ export declare class SkalpSignatureError extends Error {
31
31
  export declare class Skalp {
32
32
  #private;
33
33
  constructor(options?: string | SkalpOptions);
34
+ readonly me: () => Promise<Me>;
34
35
  readonly checkout: {
35
- create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }: CreateCheckoutParams) => Promise<CheckoutSession>;
36
+ create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }: CreateCheckoutParams) => Promise<CheckoutSession>;
36
37
  get: (id: string) => Promise<CheckoutSessionStatus>;
37
38
  };
38
39
  readonly orders: {
@@ -129,6 +130,12 @@ export declare class Skalp {
129
130
  }>;
130
131
  };
131
132
  readonly webhooks: {
133
+ list: () => Promise<WebhookEndpoint[]>;
134
+ create: ({ url, events, productIds }: CreateWebhookParams) => Promise<CreatedWebhookEndpoint>;
135
+ delete: (id: string) => Promise<{
136
+ id: string;
137
+ deleted: true;
138
+ }>;
132
139
  verify: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<boolean>;
133
140
  constructEvent: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<SkalpEvent>;
134
141
  };
package/dist/cjs/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Skalp = exports.SkalpSignatureError = exports.SkalpConnectionError = exports.SkalpError = exports.VERSION = void 0;
4
- exports.VERSION = '1.7.0';
4
+ exports.VERSION = '1.8.0';
5
5
  const SIGNATURE_HEADER = 'skalp-signature';
6
6
  const SIGNATURE_TOLERANCE_SECONDS = 300;
7
7
  const PRODUCT_PAGE = 100;
@@ -82,6 +82,9 @@ const PRODUCT_FIELDS = [
82
82
  'volumeDiscounts',
83
83
  'upsells',
84
84
  'prices',
85
+ 'poolsEnabled',
86
+ 'upgradeFrom',
87
+ 'includes',
85
88
  ];
86
89
  const COUPON_FIELDS = [
87
90
  'discountType',
@@ -93,6 +96,8 @@ const COUPON_FIELDS = [
93
96
  'maxUses',
94
97
  'minPurchaseAmount',
95
98
  'oneTimePerUser',
99
+ 'subscriptionDuration',
100
+ 'subscriptionMonths',
96
101
  ];
97
102
  const GROUP_FIELDS = ['title', 'productIds', 'description', 'image', 'sortPriority', 'unlisted'];
98
103
  function pick(source, keys) {
@@ -123,9 +128,10 @@ class Skalp {
123
128
  throw new Error('Skalp: your API key is a secret and must never reach the browser. Call the SDK from server code, or pass dangerouslyAllowBrowser: true if you really know what you are doing.');
124
129
  }
125
130
  }
131
+ me = () => this.#request('GET', '/v1/me');
126
132
  checkout = {
127
- create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }) => this.#request('POST', '/v1/checkout/sessions', {
128
- body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields },
133
+ create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }) => this.#request('POST', '/v1/checkout/sessions', {
134
+ body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields, player },
129
135
  }),
130
136
  get: (id) => this.#request('GET', `/v1/checkout/sessions/${segment(id)}`),
131
137
  };
@@ -303,6 +309,9 @@ class Skalp {
303
309
  }),
304
310
  };
305
311
  webhooks = {
312
+ list: () => this.#request('GET', '/v1/webhooks'),
313
+ create: ({ url, events, productIds }) => this.#request('POST', '/v1/webhooks', { body: { url, events, productIds } }),
314
+ delete: (id) => this.#request('DELETE', `/v1/webhooks/${segment(id)}`),
306
315
  verify: async (payload, signature, secret) => (await this.#checkSignature(payload, signature, secret)) === undefined,
307
316
  constructEvent: async (payload, signature, secret) => {
308
317
  const failure = await this.#checkSignature(payload, signature, secret);
@@ -416,10 +425,10 @@ function parseSignature(header) {
416
425
  function toBytes(payload, encoder) {
417
426
  if (typeof payload === 'string')
418
427
  return encoder.encode(payload);
419
- if (payload instanceof ArrayBuffer)
428
+ if (ArrayBuffer.isView(payload))
429
+ return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
430
+ if (Object.prototype.toString.call(payload) === '[object ArrayBuffer]')
420
431
  return new Uint8Array(payload);
421
- if (payload instanceof Uint8Array)
422
- return payload;
423
432
  throw new TypeError('Skalp: webhook payload must be the raw request body (string, Buffer or ArrayBuffer). A parsed JSON object cannot be verified, because re-serializing it changes the bytes that were signed.');
424
433
  }
425
434
  function retryAfterSeconds(res, attempt) {
@@ -5,10 +5,19 @@ export type ProductType = 'ONE_TIME' | 'RECURRING' | 'COINS';
5
5
  export type Game = 'fivem' | 'minecraft' | 'rust';
6
6
  export type BillingInterval = 'WEEK' | 'MONTH' | 'QUARTER' | 'HALF_YEAR' | 'YEAR';
7
7
  export type OrderStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED' | 'CANCELED';
8
- export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL';
8
+ export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL' | 'PAYSSION';
9
9
  export type DeliveryStatus = 'PENDING' | 'PROCESSING' | 'DELIVERED' | 'FAILED';
10
10
  export type SubscriptionStatus = 'ACTIVE' | 'CANCELED' | 'PAST_DUE' | 'UNPAID' | 'INCOMPLETE' | 'INCOMPLETE_EXPIRED' | 'TRIALING' | 'PAUSED';
11
11
  export type Metadata = Record<string, string>;
12
+ export type PlayerIdKey = 'fivem' | 'license2' | 'steam' | 'discord' | 'xbl' | 'live' | 'fivemId' | 'mc_uuid' | 'mc_name' | 'steamid64';
13
+ export interface PlayerInput {
14
+ name?: string;
15
+ ids?: Partial<Record<PlayerIdKey, string>>;
16
+ }
17
+ export interface Player {
18
+ name: string | null;
19
+ ids: Partial<Record<PlayerIdKey, string>>;
20
+ }
12
21
  export interface CreateCheckoutParams {
13
22
  productId: string;
14
23
  /** Units to sell, within the product's minQuantity and maxQuantity. Defaults to minQuantity. */
@@ -19,6 +28,7 @@ export interface CreateCheckoutParams {
19
28
  returnUrl?: string;
20
29
  /** Answers you already have, by field key; the buyer adds the rest on the pay page. */
21
30
  customFields?: Record<string, string>;
31
+ player?: PlayerInput;
22
32
  }
23
33
  export interface CheckoutSession {
24
34
  id: string;
@@ -28,7 +38,7 @@ export interface CheckoutSession {
28
38
  }
29
39
  export interface CheckoutSessionStatus {
30
40
  id: string;
31
- status: 'pending' | 'completed' | 'failed';
41
+ status: 'pending' | 'completed' | 'failed' | 'canceled';
32
42
  orderNumber: string;
33
43
  amount: number;
34
44
  currency: Currency;
@@ -45,23 +55,24 @@ export interface Order {
45
55
  vatRate: number | null;
46
56
  currency: Currency;
47
57
  discountAmount: number;
58
+ serviceFee: number | null;
48
59
  couponCode: string | null;
49
60
  productId: string;
50
61
  productName: string;
51
62
  productSlug: string;
52
63
  /** Units of productId. */
53
64
  quantity: number;
54
- fulfillmentType: FulfillmentType;
65
+ fulfillmentType: FulfillmentType | null;
55
66
  bundleId: string | null;
56
67
  buyerEmail: string;
57
68
  buyerCountry: string | null;
58
69
  paymentProvider: PaymentProvider | null;
59
70
  isGift: boolean;
60
- granted?: boolean;
71
+ granted: boolean;
61
72
  deliveryStatus: DeliveryStatus | null;
62
73
  serialsCount?: number;
63
74
  serialsReplaced?: number;
64
- /** Delivered and replaced keys by id, never their values. Only orders.get and orders.cancel fill it in. */
75
+ /** Delivered and replaced keys by id, never their values. Filled in by orders.get, orders.cancel and orders.redeliver. */
65
76
  serials?: Array<OrderSerial>;
66
77
  createdAt: string;
67
78
  updatedAt: string;
@@ -240,6 +251,9 @@ export interface Product {
240
251
  volumeDiscounts: Array<VolumeDiscount>;
241
252
  /** Products offered on this product's checkout page. */
242
253
  upsells: Array<ProductUpsell>;
254
+ poolsEnabled: boolean | null;
255
+ upgradeFrom: Array<string>;
256
+ includes: Array<string>;
243
257
  stock: number | null;
244
258
  sale: ProductSale | null;
245
259
  salesCount: number;
@@ -313,6 +327,9 @@ interface ProductFields {
313
327
  upsells?: Array<ProductUpsellInput> | null;
314
328
  /** Up to 3 currencies other than the store currency, not for coin packs; the list replaces the old one, [] or null removes them all. */
315
329
  prices?: Array<ProductPrice> | null;
330
+ poolsEnabled?: boolean;
331
+ upgradeFrom?: Array<string>;
332
+ includes?: Array<string>;
316
333
  }
317
334
  export interface CreateProductParams extends ProductFields {
318
335
  name: string;
@@ -370,6 +387,39 @@ export interface Deleted {
370
387
  id: string;
371
388
  deleted: true;
372
389
  }
390
+ export interface Me {
391
+ store: {
392
+ id: string;
393
+ name: string;
394
+ slug: string;
395
+ currency: Currency;
396
+ url: string;
397
+ };
398
+ key: {
399
+ name: string;
400
+ scopes: Array<string>;
401
+ };
402
+ }
403
+ export type WebhookEventName = SkalpEventType | '*';
404
+ export interface WebhookEndpoint {
405
+ id: string;
406
+ url: string;
407
+ events: Array<WebhookEventName>;
408
+ format: 'skalp' | (string & {});
409
+ isActive: boolean;
410
+ createdAt: string;
411
+ }
412
+ export interface CreateWebhookParams {
413
+ url: string;
414
+ events: Array<WebhookEventName>;
415
+ productIds?: Array<string>;
416
+ }
417
+ export interface CreatedWebhookEndpoint {
418
+ id: string;
419
+ url: string;
420
+ events: Array<WebhookEventName>;
421
+ secret: string;
422
+ }
373
423
  export interface StoreCategory {
374
424
  id: string;
375
425
  name: string;
@@ -423,6 +473,7 @@ export interface UpdateProductGroupParams {
423
473
  unlisted?: boolean;
424
474
  }
425
475
  export type CouponDiscountType = 'PERCENT' | 'FIXED';
476
+ export type CouponDuration = 'ONCE' | 'REPEATING' | 'FOREVER';
426
477
  export interface Coupon {
427
478
  id: string;
428
479
  code: string;
@@ -432,6 +483,8 @@ export interface Coupon {
432
483
  discountAmount: number | null;
433
484
  productIds: Array<string>;
434
485
  disabledWithVolumeDiscounts: boolean;
486
+ subscriptionDuration: CouponDuration;
487
+ subscriptionMonths: number | null;
435
488
  validFrom: string;
436
489
  validTo: string | null;
437
490
  maxUses: number | null;
@@ -455,6 +508,8 @@ export interface CreateCouponParams {
455
508
  maxUses?: number;
456
509
  minPurchaseAmount?: number;
457
510
  oneTimePerUser?: boolean;
511
+ subscriptionDuration?: CouponDuration;
512
+ subscriptionMonths?: number;
458
513
  }
459
514
  export interface UpdateCouponParams {
460
515
  discountType?: CouponDiscountType;
@@ -469,6 +524,8 @@ export interface UpdateCouponParams {
469
524
  minPurchaseAmount?: number | null;
470
525
  oneTimePerUser?: boolean;
471
526
  isActive?: boolean;
527
+ subscriptionDuration?: CouponDuration;
528
+ subscriptionMonths?: number | null;
472
529
  }
473
530
  export interface Customer {
474
531
  id: string;
@@ -479,6 +536,10 @@ export interface Customer {
479
536
  ordersCount: number;
480
537
  totalSpent: number;
481
538
  currency: Currency;
539
+ spent: Array<{
540
+ currency: Currency;
541
+ amount: number;
542
+ }>;
482
543
  firstOrderAt: string | null;
483
544
  lastOrderAt: string | null;
484
545
  createdAt: string;
@@ -486,6 +547,17 @@ export interface Customer {
486
547
  }
487
548
  export interface CustomerDetails extends Customer {
488
549
  recentOrders: Array<Order>;
550
+ recentSubscriptionPayments: Array<SubscriptionPayment>;
551
+ }
552
+ export interface SubscriptionPayment {
553
+ id: string;
554
+ orderNumber: string | null;
555
+ status: 'COMPLETED' | 'REFUNDED';
556
+ amount: number;
557
+ currency: Currency;
558
+ productName: string;
559
+ subscriptionId: string;
560
+ createdAt: string;
489
561
  }
490
562
  export interface ListCustomersParams {
491
563
  search?: string;
@@ -615,7 +687,7 @@ export interface CreateSubscriptionCheckoutParams {
615
687
  customerEmail?: string;
616
688
  externalRef?: string;
617
689
  metadata?: Metadata;
618
- currency?: 'EUR' | 'USD' | 'PLN';
690
+ currency?: 'EUR' | 'USD' | 'PLN' | 'BRL';
619
691
  returnUrl?: string;
620
692
  }
621
693
  export interface SubscriptionCheckout {
@@ -692,7 +764,7 @@ export interface Invoice {
692
764
  }
693
765
  export interface CreateUsageChargeParams {
694
766
  amount: number;
695
- currency: 'EUR' | 'USD' | 'PLN';
767
+ currency: Currency;
696
768
  description: string;
697
769
  idempotencyKey: string;
698
770
  periodStart: string | Date;
@@ -824,6 +896,7 @@ export interface OrderPaidData {
824
896
  customFields: Record<string, string>;
825
897
  deliveryType?: string;
826
898
  deliveryCommand?: string;
899
+ player?: Player;
827
900
  }
828
901
  export interface OrderRefundedData {
829
902
  orderId: string;
@@ -839,6 +912,8 @@ export interface OrderRefundedData {
839
912
  fullRefund: boolean;
840
913
  licenses: Array<WebhookLicense>;
841
914
  revocations: Array<Revocation>;
915
+ upgradedTo?: string;
916
+ player?: Player;
842
917
  }
843
918
  export interface Revocation {
844
919
  productId: string;
@@ -891,6 +966,9 @@ export interface SubscriptionEventData {
891
966
  licenseKey: string | null;
892
967
  licenseStatus: string | null;
893
968
  licenseExpiresAt: string | null;
969
+ deliveryType?: string;
970
+ deliveryCommand?: string;
971
+ player?: Player;
894
972
  }
895
973
  export interface ProductEventData {
896
974
  productId: string;
@@ -953,7 +1031,10 @@ export interface FeedbackReceivedData {
953
1031
  customerName: string | null;
954
1032
  createdAt: string;
955
1033
  }
956
- 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 & {
1034
+ 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', SubscriptionEventData> | Envelope<'subscription.upcoming', SubscriptionEventData & {
1035
+ amountDue: number;
1036
+ nextPaymentAttempt: string | null;
1037
+ }> | Envelope<'subscription.renewed', SubscriptionEventData & {
957
1038
  invoiceId: string;
958
1039
  amountPaid: number;
959
1040
  periodExtendedTo: string;
@@ -963,7 +1044,7 @@ export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.can
963
1044
  nextPaymentAttempt: string | null;
964
1045
  }> | Envelope<'subscription.canceled', SubscriptionEventData & {
965
1046
  endedAt: string | null;
966
- cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe';
1047
+ cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe' | 'expired';
967
1048
  revokeCommand?: string;
968
1049
  }> | Envelope<'subscription.refunded', SubscriptionEventData & {
969
1050
  invoiceId: string;
@@ -1,6 +1,6 @@
1
- import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams } from './types.js';
1
+ import type { AccessRule, AddAccessRuleParams, AddSerialsParams, AddSerialsResult, AppealFeedbackParams, ChangeSubscriptionPlanParams, CheckoutSession, CheckoutSessionStatus, CoinCheckout, CoinCheckoutStatus, Coupon, CreateCheckoutParams, CreateCoinCheckoutParams, CreateCouponParams, CreateCustomerParams, CreateProductGroupParams, CreateProductParams, CreateStoreCategoryParams, CreateSubscriptionCheckoutParams, CreateUsageChargeParams, CreateWebhookParams, CreatedWebhookEndpoint, Customer, CustomerDetails, CustomerList, Deleted, Feedback, FeedbackList, HeartbeatParams, Invoice, LicenseKeyInfo, LicenseValidation, LicenseVerification, ListAccessRulesParams, ListCustomersParams, ListFeedbackParams, ListOrdersParams, ListProductsParams, ListQueriesParams, ListSerialsParams, ListSubscriptionsParams, Me, Order, OrderKeysReplaced, OrderList, Product, ProductGroup, ProductStock, ReplaceOrderKeysParams, ReplyParams, SerialList, SkalpEvent, StoreCategory, StoreCategoryWithCount, Subscription, SubscriptionCheckout, SubscriptionCheckoutStatus, SubscriptionList, SupportQueryDetails, SupportQueryList, ResetLicenseDevicesParams, UpdateCouponParams, UpdateCustomerParams, UpdateProductGroupParams, UpdateProductParams, UpdateStoreCategoryParams, UsageCharge, ValidateLicenseParams, VerifyLicenseParams, WebhookEndpoint } from './types.js';
2
2
  export type * from './types.js';
3
- export declare const VERSION = "1.7.0";
3
+ export declare const VERSION = "1.8.0";
4
4
  export interface SkalpOptions {
5
5
  apiKey?: string;
6
6
  webhookSecret?: string;
@@ -31,8 +31,9 @@ export declare class SkalpSignatureError extends Error {
31
31
  export declare class Skalp {
32
32
  #private;
33
33
  constructor(options?: string | SkalpOptions);
34
+ readonly me: () => Promise<Me>;
34
35
  readonly checkout: {
35
- create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }: CreateCheckoutParams) => Promise<CheckoutSession>;
36
+ create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }: CreateCheckoutParams) => Promise<CheckoutSession>;
36
37
  get: (id: string) => Promise<CheckoutSessionStatus>;
37
38
  };
38
39
  readonly orders: {
@@ -129,6 +130,12 @@ export declare class Skalp {
129
130
  }>;
130
131
  };
131
132
  readonly webhooks: {
133
+ list: () => Promise<WebhookEndpoint[]>;
134
+ create: ({ url, events, productIds }: CreateWebhookParams) => Promise<CreatedWebhookEndpoint>;
135
+ delete: (id: string) => Promise<{
136
+ id: string;
137
+ deleted: true;
138
+ }>;
132
139
  verify: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<boolean>;
133
140
  constructEvent: (payload: WebhookPayload, signature: SignatureSource, secret?: string) => Promise<SkalpEvent>;
134
141
  };
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = '1.7.0';
1
+ export const VERSION = '1.8.0';
2
2
  const SIGNATURE_HEADER = 'skalp-signature';
3
3
  const SIGNATURE_TOLERANCE_SECONDS = 300;
4
4
  const PRODUCT_PAGE = 100;
@@ -76,6 +76,9 @@ const PRODUCT_FIELDS = [
76
76
  'volumeDiscounts',
77
77
  'upsells',
78
78
  'prices',
79
+ 'poolsEnabled',
80
+ 'upgradeFrom',
81
+ 'includes',
79
82
  ];
80
83
  const COUPON_FIELDS = [
81
84
  'discountType',
@@ -87,6 +90,8 @@ const COUPON_FIELDS = [
87
90
  'maxUses',
88
91
  'minPurchaseAmount',
89
92
  'oneTimePerUser',
93
+ 'subscriptionDuration',
94
+ 'subscriptionMonths',
90
95
  ];
91
96
  const GROUP_FIELDS = ['title', 'productIds', 'description', 'image', 'sortPriority', 'unlisted'];
92
97
  function pick(source, keys) {
@@ -117,9 +122,10 @@ export class Skalp {
117
122
  throw new Error('Skalp: your API key is a secret and must never reach the browser. Call the SDK from server code, or pass dangerouslyAllowBrowser: true if you really know what you are doing.');
118
123
  }
119
124
  }
125
+ me = () => this.#request('GET', '/v1/me');
120
126
  checkout = {
121
- create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields }) => this.#request('POST', '/v1/checkout/sessions', {
122
- body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields },
127
+ create: ({ productId, quantity, customerEmail, metadata, couponCode, returnUrl, customFields, player }) => this.#request('POST', '/v1/checkout/sessions', {
128
+ body: { items: [{ productId, quantity }], customerEmail, metadata, couponCode, returnUrl, customFields, player },
123
129
  }),
124
130
  get: (id) => this.#request('GET', `/v1/checkout/sessions/${segment(id)}`),
125
131
  };
@@ -297,6 +303,9 @@ export class Skalp {
297
303
  }),
298
304
  };
299
305
  webhooks = {
306
+ list: () => this.#request('GET', '/v1/webhooks'),
307
+ create: ({ url, events, productIds }) => this.#request('POST', '/v1/webhooks', { body: { url, events, productIds } }),
308
+ delete: (id) => this.#request('DELETE', `/v1/webhooks/${segment(id)}`),
300
309
  verify: async (payload, signature, secret) => (await this.#checkSignature(payload, signature, secret)) === undefined,
301
310
  constructEvent: async (payload, signature, secret) => {
302
311
  const failure = await this.#checkSignature(payload, signature, secret);
@@ -409,10 +418,10 @@ function parseSignature(header) {
409
418
  function toBytes(payload, encoder) {
410
419
  if (typeof payload === 'string')
411
420
  return encoder.encode(payload);
412
- if (payload instanceof ArrayBuffer)
421
+ if (ArrayBuffer.isView(payload))
422
+ return new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
423
+ if (Object.prototype.toString.call(payload) === '[object ArrayBuffer]')
413
424
  return new Uint8Array(payload);
414
- if (payload instanceof Uint8Array)
415
- return payload;
416
425
  throw new TypeError('Skalp: webhook payload must be the raw request body (string, Buffer or ArrayBuffer). A parsed JSON object cannot be verified, because re-serializing it changes the bytes that were signed.');
417
426
  }
418
427
  function retryAfterSeconds(res, attempt) {
@@ -5,10 +5,19 @@ export type ProductType = 'ONE_TIME' | 'RECURRING' | 'COINS';
5
5
  export type Game = 'fivem' | 'minecraft' | 'rust';
6
6
  export type BillingInterval = 'WEEK' | 'MONTH' | 'QUARTER' | 'HALF_YEAR' | 'YEAR';
7
7
  export type OrderStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED' | 'CANCELED';
8
- export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL';
8
+ export type PaymentProvider = 'STRIPE' | 'NOWPAYMENTS' | 'PAYPAL' | 'PAYSSION';
9
9
  export type DeliveryStatus = 'PENDING' | 'PROCESSING' | 'DELIVERED' | 'FAILED';
10
10
  export type SubscriptionStatus = 'ACTIVE' | 'CANCELED' | 'PAST_DUE' | 'UNPAID' | 'INCOMPLETE' | 'INCOMPLETE_EXPIRED' | 'TRIALING' | 'PAUSED';
11
11
  export type Metadata = Record<string, string>;
12
+ export type PlayerIdKey = 'fivem' | 'license2' | 'steam' | 'discord' | 'xbl' | 'live' | 'fivemId' | 'mc_uuid' | 'mc_name' | 'steamid64';
13
+ export interface PlayerInput {
14
+ name?: string;
15
+ ids?: Partial<Record<PlayerIdKey, string>>;
16
+ }
17
+ export interface Player {
18
+ name: string | null;
19
+ ids: Partial<Record<PlayerIdKey, string>>;
20
+ }
12
21
  export interface CreateCheckoutParams {
13
22
  productId: string;
14
23
  /** Units to sell, within the product's minQuantity and maxQuantity. Defaults to minQuantity. */
@@ -19,6 +28,7 @@ export interface CreateCheckoutParams {
19
28
  returnUrl?: string;
20
29
  /** Answers you already have, by field key; the buyer adds the rest on the pay page. */
21
30
  customFields?: Record<string, string>;
31
+ player?: PlayerInput;
22
32
  }
23
33
  export interface CheckoutSession {
24
34
  id: string;
@@ -28,7 +38,7 @@ export interface CheckoutSession {
28
38
  }
29
39
  export interface CheckoutSessionStatus {
30
40
  id: string;
31
- status: 'pending' | 'completed' | 'failed';
41
+ status: 'pending' | 'completed' | 'failed' | 'canceled';
32
42
  orderNumber: string;
33
43
  amount: number;
34
44
  currency: Currency;
@@ -45,23 +55,24 @@ export interface Order {
45
55
  vatRate: number | null;
46
56
  currency: Currency;
47
57
  discountAmount: number;
58
+ serviceFee: number | null;
48
59
  couponCode: string | null;
49
60
  productId: string;
50
61
  productName: string;
51
62
  productSlug: string;
52
63
  /** Units of productId. */
53
64
  quantity: number;
54
- fulfillmentType: FulfillmentType;
65
+ fulfillmentType: FulfillmentType | null;
55
66
  bundleId: string | null;
56
67
  buyerEmail: string;
57
68
  buyerCountry: string | null;
58
69
  paymentProvider: PaymentProvider | null;
59
70
  isGift: boolean;
60
- granted?: boolean;
71
+ granted: boolean;
61
72
  deliveryStatus: DeliveryStatus | null;
62
73
  serialsCount?: number;
63
74
  serialsReplaced?: number;
64
- /** Delivered and replaced keys by id, never their values. Only orders.get and orders.cancel fill it in. */
75
+ /** Delivered and replaced keys by id, never their values. Filled in by orders.get, orders.cancel and orders.redeliver. */
65
76
  serials?: Array<OrderSerial>;
66
77
  createdAt: string;
67
78
  updatedAt: string;
@@ -240,6 +251,9 @@ export interface Product {
240
251
  volumeDiscounts: Array<VolumeDiscount>;
241
252
  /** Products offered on this product's checkout page. */
242
253
  upsells: Array<ProductUpsell>;
254
+ poolsEnabled: boolean | null;
255
+ upgradeFrom: Array<string>;
256
+ includes: Array<string>;
243
257
  stock: number | null;
244
258
  sale: ProductSale | null;
245
259
  salesCount: number;
@@ -313,6 +327,9 @@ interface ProductFields {
313
327
  upsells?: Array<ProductUpsellInput> | null;
314
328
  /** Up to 3 currencies other than the store currency, not for coin packs; the list replaces the old one, [] or null removes them all. */
315
329
  prices?: Array<ProductPrice> | null;
330
+ poolsEnabled?: boolean;
331
+ upgradeFrom?: Array<string>;
332
+ includes?: Array<string>;
316
333
  }
317
334
  export interface CreateProductParams extends ProductFields {
318
335
  name: string;
@@ -370,6 +387,39 @@ export interface Deleted {
370
387
  id: string;
371
388
  deleted: true;
372
389
  }
390
+ export interface Me {
391
+ store: {
392
+ id: string;
393
+ name: string;
394
+ slug: string;
395
+ currency: Currency;
396
+ url: string;
397
+ };
398
+ key: {
399
+ name: string;
400
+ scopes: Array<string>;
401
+ };
402
+ }
403
+ export type WebhookEventName = SkalpEventType | '*';
404
+ export interface WebhookEndpoint {
405
+ id: string;
406
+ url: string;
407
+ events: Array<WebhookEventName>;
408
+ format: 'skalp' | (string & {});
409
+ isActive: boolean;
410
+ createdAt: string;
411
+ }
412
+ export interface CreateWebhookParams {
413
+ url: string;
414
+ events: Array<WebhookEventName>;
415
+ productIds?: Array<string>;
416
+ }
417
+ export interface CreatedWebhookEndpoint {
418
+ id: string;
419
+ url: string;
420
+ events: Array<WebhookEventName>;
421
+ secret: string;
422
+ }
373
423
  export interface StoreCategory {
374
424
  id: string;
375
425
  name: string;
@@ -423,6 +473,7 @@ export interface UpdateProductGroupParams {
423
473
  unlisted?: boolean;
424
474
  }
425
475
  export type CouponDiscountType = 'PERCENT' | 'FIXED';
476
+ export type CouponDuration = 'ONCE' | 'REPEATING' | 'FOREVER';
426
477
  export interface Coupon {
427
478
  id: string;
428
479
  code: string;
@@ -432,6 +483,8 @@ export interface Coupon {
432
483
  discountAmount: number | null;
433
484
  productIds: Array<string>;
434
485
  disabledWithVolumeDiscounts: boolean;
486
+ subscriptionDuration: CouponDuration;
487
+ subscriptionMonths: number | null;
435
488
  validFrom: string;
436
489
  validTo: string | null;
437
490
  maxUses: number | null;
@@ -455,6 +508,8 @@ export interface CreateCouponParams {
455
508
  maxUses?: number;
456
509
  minPurchaseAmount?: number;
457
510
  oneTimePerUser?: boolean;
511
+ subscriptionDuration?: CouponDuration;
512
+ subscriptionMonths?: number;
458
513
  }
459
514
  export interface UpdateCouponParams {
460
515
  discountType?: CouponDiscountType;
@@ -469,6 +524,8 @@ export interface UpdateCouponParams {
469
524
  minPurchaseAmount?: number | null;
470
525
  oneTimePerUser?: boolean;
471
526
  isActive?: boolean;
527
+ subscriptionDuration?: CouponDuration;
528
+ subscriptionMonths?: number | null;
472
529
  }
473
530
  export interface Customer {
474
531
  id: string;
@@ -479,6 +536,10 @@ export interface Customer {
479
536
  ordersCount: number;
480
537
  totalSpent: number;
481
538
  currency: Currency;
539
+ spent: Array<{
540
+ currency: Currency;
541
+ amount: number;
542
+ }>;
482
543
  firstOrderAt: string | null;
483
544
  lastOrderAt: string | null;
484
545
  createdAt: string;
@@ -486,6 +547,17 @@ export interface Customer {
486
547
  }
487
548
  export interface CustomerDetails extends Customer {
488
549
  recentOrders: Array<Order>;
550
+ recentSubscriptionPayments: Array<SubscriptionPayment>;
551
+ }
552
+ export interface SubscriptionPayment {
553
+ id: string;
554
+ orderNumber: string | null;
555
+ status: 'COMPLETED' | 'REFUNDED';
556
+ amount: number;
557
+ currency: Currency;
558
+ productName: string;
559
+ subscriptionId: string;
560
+ createdAt: string;
489
561
  }
490
562
  export interface ListCustomersParams {
491
563
  search?: string;
@@ -615,7 +687,7 @@ export interface CreateSubscriptionCheckoutParams {
615
687
  customerEmail?: string;
616
688
  externalRef?: string;
617
689
  metadata?: Metadata;
618
- currency?: 'EUR' | 'USD' | 'PLN';
690
+ currency?: 'EUR' | 'USD' | 'PLN' | 'BRL';
619
691
  returnUrl?: string;
620
692
  }
621
693
  export interface SubscriptionCheckout {
@@ -692,7 +764,7 @@ export interface Invoice {
692
764
  }
693
765
  export interface CreateUsageChargeParams {
694
766
  amount: number;
695
- currency: 'EUR' | 'USD' | 'PLN';
767
+ currency: Currency;
696
768
  description: string;
697
769
  idempotencyKey: string;
698
770
  periodStart: string | Date;
@@ -824,6 +896,7 @@ export interface OrderPaidData {
824
896
  customFields: Record<string, string>;
825
897
  deliveryType?: string;
826
898
  deliveryCommand?: string;
899
+ player?: Player;
827
900
  }
828
901
  export interface OrderRefundedData {
829
902
  orderId: string;
@@ -839,6 +912,8 @@ export interface OrderRefundedData {
839
912
  fullRefund: boolean;
840
913
  licenses: Array<WebhookLicense>;
841
914
  revocations: Array<Revocation>;
915
+ upgradedTo?: string;
916
+ player?: Player;
842
917
  }
843
918
  export interface Revocation {
844
919
  productId: string;
@@ -891,6 +966,9 @@ export interface SubscriptionEventData {
891
966
  licenseKey: string | null;
892
967
  licenseStatus: string | null;
893
968
  licenseExpiresAt: string | null;
969
+ deliveryType?: string;
970
+ deliveryCommand?: string;
971
+ player?: Player;
894
972
  }
895
973
  export interface ProductEventData {
896
974
  productId: string;
@@ -953,7 +1031,10 @@ export interface FeedbackReceivedData {
953
1031
  customerName: string | null;
954
1032
  createdAt: string;
955
1033
  }
956
- 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 & {
1034
+ 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', SubscriptionEventData> | Envelope<'subscription.upcoming', SubscriptionEventData & {
1035
+ amountDue: number;
1036
+ nextPaymentAttempt: string | null;
1037
+ }> | Envelope<'subscription.renewed', SubscriptionEventData & {
957
1038
  invoiceId: string;
958
1039
  amountPaid: number;
959
1040
  periodExtendedTo: string;
@@ -963,7 +1044,7 @@ export type SkalpEvent = Envelope<'order.created' | 'order.updated' | 'order.can
963
1044
  nextPaymentAttempt: string | null;
964
1045
  }> | Envelope<'subscription.canceled', SubscriptionEventData & {
965
1046
  endedAt: string | null;
966
- cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe';
1047
+ cancelReason: 'requested' | 'payment_failure' | 'dispute' | 'stripe' | 'expired';
967
1048
  revokeCommand?: string;
968
1049
  }> | Envelope<'subscription.refunded', SubscriptionEventData & {
969
1050
  invoiceId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skalpgg/sdk",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Official Skalp SDK for Node.js and edge runtimes: checkout, subscriptions, catalog and key stock, webhooks and license verification.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://skalp.gg/docs/sdk",