license_manager 0.1.1 → 0.3.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.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +152 -0
  3. data/README.md +3 -3
  4. data/docs/BillingPortalSession.md +18 -0
  5. data/docs/CancelLicense.md +22 -0
  6. data/docs/CancellationReason.md +15 -0
  7. data/docs/CancellationStats.md +30 -0
  8. data/docs/CancellationStatsByReasonInner.md +20 -0
  9. data/docs/ConnectStripe.md +1 -1
  10. data/docs/CreateBillingPortalSession.md +18 -0
  11. data/docs/CreateIntegrationMapping.md +1 -1
  12. data/docs/CreateLicense.md +2 -0
  13. data/docs/CreatePolicy.md +3 -1
  14. data/docs/CreateProductWithPolicy.md +1 -1
  15. data/docs/CreateToken.md +1 -1
  16. data/docs/EventActorOneOf.md +1 -1
  17. data/docs/Integration.md +11 -1
  18. data/docs/IntegrationMapping.md +2 -0
  19. data/docs/IntegrationMappingRecurring.md +20 -0
  20. data/docs/IntegrationsApi.md +74 -0
  21. data/docs/License.md +12 -0
  22. data/docs/LicenseSubscription.md +34 -0
  23. data/docs/LicensesApi.md +80 -3
  24. data/docs/Machine.md +3 -1
  25. data/docs/MachinesApi.md +1 -1
  26. data/docs/Mrr.md +26 -0
  27. data/docs/MrrByIntervalInner.md +24 -0
  28. data/docs/MrrByPolicyInner.md +22 -0
  29. data/docs/Policy.md +2 -0
  30. data/docs/PolicySettings.md +3 -1
  31. data/docs/PortalApi.md +80 -1
  32. data/docs/PortalLink.md +2 -2
  33. data/docs/Product.md +2 -0
  34. data/docs/ProductStats.md +8 -4
  35. data/docs/ProductsApi.md +2 -2
  36. data/docs/Revenue.md +10 -2
  37. data/docs/StripeIntegration.md +1 -1
  38. data/docs/StripePermission.md +5 -1
  39. data/docs/StripePrice.md +2 -0
  40. data/docs/StripePriceRecurring.md +20 -0
  41. data/docs/SubscriptionStats.md +38 -0
  42. data/docs/UpdateIntegration.md +20 -0
  43. data/docs/UpdateLicense.md +3 -1
  44. data/docs/UpdatePolicy.md +3 -1
  45. data/docs/UpdateProduct.md +3 -1
  46. data/lib/license_manager/api/integrations_api.rb +74 -0
  47. data/lib/license_manager/api/licenses_api.rb +80 -6
  48. data/lib/license_manager/api/machines_api.rb +3 -3
  49. data/lib/license_manager/api/portal_api.rb +72 -2
  50. data/lib/license_manager/api/products_api.rb +4 -4
  51. data/lib/license_manager/models/billing_portal_session.rb +178 -0
  52. data/lib/license_manager/models/cancel_license.rb +238 -0
  53. data/lib/license_manager/models/cancellation_reason.rb +45 -0
  54. data/lib/license_manager/models/cancellation_stats.rb +347 -0
  55. data/lib/license_manager/models/cancellation_stats_by_reason_inner.rb +225 -0
  56. data/lib/license_manager/models/connect_stripe.rb +1 -1
  57. data/lib/license_manager/models/create_billing_portal_session.rb +161 -0
  58. data/lib/license_manager/models/create_integration_mapping.rb +1 -1
  59. data/lib/license_manager/models/create_license.rb +12 -1
  60. data/lib/license_manager/models/create_policy.rb +40 -5
  61. data/lib/license_manager/models/create_product_with_policy.rb +1 -1
  62. data/lib/license_manager/models/create_token.rb +1 -1
  63. data/lib/license_manager/models/event_type.rb +7 -1
  64. data/lib/license_manager/models/integration.rb +136 -1
  65. data/lib/license_manager/models/integration_mapping.rb +13 -1
  66. data/lib/license_manager/models/integration_mapping_recurring.rb +228 -0
  67. data/lib/license_manager/models/license.rb +91 -1
  68. data/lib/license_manager/models/license_status.rb +2 -1
  69. data/lib/license_manager/models/license_subscription.rb +388 -0
  70. data/lib/license_manager/models/machine.rb +17 -4
  71. data/lib/license_manager/models/mrr.rb +291 -0
  72. data/lib/license_manager/models/mrr_by_interval_inner.rb +279 -0
  73. data/lib/license_manager/models/mrr_by_policy_inner.rb +229 -0
  74. data/lib/license_manager/models/policy.rb +14 -1
  75. data/lib/license_manager/models/policy_settings.rb +40 -5
  76. data/lib/license_manager/models/portal_link.rb +1 -1
  77. data/lib/license_manager/models/product.rb +28 -1
  78. data/lib/license_manager/models/product_stats.rb +31 -5
  79. data/lib/license_manager/models/revenue.rb +112 -4
  80. data/lib/license_manager/models/stripe_integration.rb +1 -1
  81. data/lib/license_manager/models/stripe_permission.rb +58 -4
  82. data/lib/license_manager/models/stripe_price.rb +13 -1
  83. data/lib/license_manager/models/stripe_price_recurring.rb +228 -0
  84. data/lib/license_manager/models/subscription_stats.rb +456 -0
  85. data/lib/license_manager/models/update_integration.rb +199 -0
  86. data/lib/license_manager/models/update_license.rb +16 -5
  87. data/lib/license_manager/models/update_policy.rb +40 -5
  88. data/lib/license_manager/models/update_product.rb +14 -4
  89. data/lib/license_manager/version.rb +1 -1
  90. data/lib/license_manager.rb +14 -0
  91. data/openapi.json +1146 -59
  92. data/spec/api/integrations_api_spec.rb +13 -0
  93. data/spec/api/licenses_api_spec.rb +16 -3
  94. data/spec/api/machines_api_spec.rb +1 -1
  95. data/spec/api/portal_api_spec.rb +14 -1
  96. data/spec/api/products_api_spec.rb +2 -2
  97. data/spec/models/billing_portal_session_spec.rb +36 -0
  98. data/spec/models/cancel_license_spec.rb +48 -0
  99. data/spec/models/cancellation_reason_spec.rb +30 -0
  100. data/spec/models/cancellation_stats_by_reason_inner_spec.rb +42 -0
  101. data/spec/models/cancellation_stats_spec.rb +72 -0
  102. data/spec/models/create_billing_portal_session_spec.rb +36 -0
  103. data/spec/models/create_license_spec.rb +6 -0
  104. data/spec/models/create_policy_spec.rb +6 -0
  105. data/spec/models/create_token_spec.rb +1 -1
  106. data/spec/models/integration_mapping_recurring_spec.rb +46 -0
  107. data/spec/models/integration_mapping_spec.rb +6 -0
  108. data/spec/models/integration_spec.rb +30 -0
  109. data/spec/models/license_spec.rb +36 -0
  110. data/spec/models/license_subscription_spec.rb +88 -0
  111. data/spec/models/machine_spec.rb +7 -1
  112. data/spec/models/mrr_by_interval_inner_spec.rb +58 -0
  113. data/spec/models/mrr_by_policy_inner_spec.rb +48 -0
  114. data/spec/models/mrr_spec.rb +60 -0
  115. data/spec/models/policy_settings_spec.rb +6 -0
  116. data/spec/models/policy_spec.rb +6 -0
  117. data/spec/models/product_spec.rb +6 -0
  118. data/spec/models/product_stats_spec.rb +12 -0
  119. data/spec/models/revenue_spec.rb +24 -0
  120. data/spec/models/stripe_permission_spec.rb +12 -0
  121. data/spec/models/stripe_price_recurring_spec.rb +46 -0
  122. data/spec/models/stripe_price_spec.rb +6 -0
  123. data/spec/models/subscription_stats_spec.rb +96 -0
  124. data/spec/models/token_spec.rb +1 -1
  125. data/spec/models/update_integration_spec.rb +42 -0
  126. data/spec/models/update_license_spec.rb +6 -0
  127. data/spec/models/update_policy_spec.rb +6 -0
  128. data/spec/models/update_product_spec.rb +6 -0
  129. metadata +57 -1
@@ -0,0 +1,34 @@
1
+ # LicenseManager::LicenseSubscription
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **stripe_subscription_id** | **String** | | |
8
+ | **status** | **String** | Status of the subscription in Stripe: `active`, `trialing`, `past_due` while a failed payment is retried, `canceled`, `unpaid`, `paused`, `incomplete` or `incomplete_expired`. | |
9
+ | **interval** | **String** | | |
10
+ | **interval_count** | **Integer** | Number of intervals between payments. | |
11
+ | **quantity** | **Integer** | Units subscribed, multiplying the policy's machines. | |
12
+ | **price** | [**Price**](Price.md) | Price of one unit for one period, before taxes. | |
13
+ | **current_period_end** | **Time** | End of the paid period, when the subscription renews or ends. | |
14
+ | **cancel_at_period_end** | **Boolean** | Whether the subscription ends at the end of the period. | |
15
+ | **ended_at** | **Time** | | |
16
+
17
+ ## Example
18
+
19
+ ```ruby
20
+ require 'license_manager'
21
+
22
+ instance = LicenseManager::LicenseSubscription.new(
23
+ stripe_subscription_id: sub_1MowQVLkdIwHu7ix,
24
+ status: active,
25
+ interval: null,
26
+ interval_count: 1,
27
+ quantity: 1,
28
+ price: null,
29
+ current_period_end: null,
30
+ cancel_at_period_end: null,
31
+ ended_at: null
32
+ )
33
+ ```
34
+
data/docs/LicensesApi.md CHANGED
@@ -4,6 +4,7 @@ All URIs are relative to *https://api.licensemanager.dev*
4
4
 
5
5
  | Method | HTTP request | Description |
6
6
  | ------ | ------------ | ----------- |
7
+ | [**cancel_license**](LicensesApi.md#cancel_license) | **POST** /v1/licenses/{id}/cancel | Cancel a license |
7
8
  | [**create_license**](LicensesApi.md#create_license) | **POST** /v1/products/{productId}/licenses | Create a license |
8
9
  | [**delete_license**](LicensesApi.md#delete_license) | **DELETE** /v1/licenses/{id} | Delete a license |
9
10
  | [**get_license**](LicensesApi.md#get_license) | **GET** /v1/licenses/{id} | Get a license |
@@ -16,13 +17,89 @@ All URIs are relative to *https://api.licensemanager.dev*
16
17
  | [**validate_key**](LicensesApi.md#validate_key) | **POST** /v1/products/{productId}/validate-key | Validate a license key |
17
18
 
18
19
 
20
+ ## cancel_license
21
+
22
+ > <License> cancel_license(id, cancel_license)
23
+
24
+ Cancel a license
25
+
26
+ Cancels the license right away: validating its key then fails with `license_expired`, like an expired license, and its status is `canceled`. A cancellation can't be undone. Customers can cancel their licenses until their `cancellableUntil`, the end of their money back guarantee: tokens can't cancel a license past it, or without one. API keys and sessions can cancel any license. When the license was bought through the Stripe integration, its payment is refunded in the background, unless the integration disables `autoRefund`, its API key lacks the optional Refunds: Write permission (`canRefund`), or `refund` is `false`: the refund is its price paid, taxes included, and its id is set as `stripeRefundId`. The customer is emailed a confirmation, and the owners and admins of the organization are told about the cancellation and its refund. In test products, the customer is only emailed when their email is a member's of the organization. A subscription license isn't refunded: its Stripe subscription is canceled at once, without proration, which needs the integration's `canManageSubscriptions`. Records a `license.canceled` event, then a `license.refunded` or `license.refund_failed` one once the refund is done. **Token access**: customer, license tokens with the `license:cancel` permission (or the matching write one). A token reaches the license it's scoped to, or the licenses of its customer. **Required role permission**: `license:cancel` when called with a session, granted by the member's role. API keys aren't limited by roles.
27
+
28
+ ### Examples
29
+
30
+ ```ruby
31
+ require 'time'
32
+ require 'license_manager'
33
+ # setup authorization
34
+ LicenseManager.configure do |config|
35
+ # Configure API key authorization: apiKey
36
+ config.api_key['x-api-key'] = 'YOUR API KEY'
37
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
38
+ # config.api_key_prefix['x-api-key'] = 'Bearer'
39
+
40
+ # Configure Bearer authorization (JWT): token
41
+ config.access_token = 'YOUR_BEARER_TOKEN'
42
+ end
43
+
44
+ api_instance = LicenseManager::LicensesApi.new
45
+ id = 'l3Nv8KwB' # String |
46
+ cancel_license = LicenseManager::CancelLicense.new({reason: LicenseManager::CancellationReason::TOO_EXPENSIVE}) # CancelLicense |
47
+
48
+ begin
49
+ # Cancel a license
50
+ result = api_instance.cancel_license(id, cancel_license)
51
+ p result
52
+ rescue LicenseManager::ApiError => e
53
+ puts "Error when calling LicensesApi->cancel_license: #{e}"
54
+ end
55
+ ```
56
+
57
+ #### Using the cancel_license_with_http_info variant
58
+
59
+ This returns an Array which contains the response data, status code and headers.
60
+
61
+ > <Array(<License>, Integer, Hash)> cancel_license_with_http_info(id, cancel_license)
62
+
63
+ ```ruby
64
+ begin
65
+ # Cancel a license
66
+ data, status_code, headers = api_instance.cancel_license_with_http_info(id, cancel_license)
67
+ p status_code # => 2xx
68
+ p headers # => { ... }
69
+ p data # => <License>
70
+ rescue LicenseManager::ApiError => e
71
+ puts "Error when calling LicensesApi->cancel_license_with_http_info: #{e}"
72
+ end
73
+ ```
74
+
75
+ ### Parameters
76
+
77
+ | Name | Type | Description | Notes |
78
+ | ---- | ---- | ----------- | ----- |
79
+ | **id** | **String** | | |
80
+ | **cancel_license** | [**CancelLicense**](CancelLicense.md) | | |
81
+
82
+ ### Return type
83
+
84
+ [**License**](License.md)
85
+
86
+ ### Authorization
87
+
88
+ [apiKey](../README.md#apiKey), [token](../README.md#token)
89
+
90
+ ### HTTP request headers
91
+
92
+ - **Content-Type**: application/json
93
+ - **Accept**: application/json
94
+
95
+
19
96
  ## create_license
20
97
 
21
98
  > <License> create_license(product_id, create_license)
22
99
 
23
100
  Create a license
24
101
 
25
- Without a `key`, the license gets a random one, like `7KQ2M-X9ZPA-H4TRC-WN6EY-B3JDF`: 5 groups of 5 characters separated by dashes, each character an upper case letter or a digit other than `O`, `0`, `I` and `1`. That's 32 possible characters encoding 5 bits each, for 125 random bits. Without a `policyId`, the license follows the product's default policy. Without an `expiresAt`, the license expires after the duration of its policy, or never when the policy has none. `expiresAt: null` makes it never expire. Without a `price`, the price paid for the license is unknown: it's left out of the revenue stats. The values of `maxVersion` left out are taken from the max version of the policy: its hard-coded version, or the times after the creation of the license its versions lock. The license belongs to the product's customer with the given `email`, which is created when there's none. With `sendKey: true`, the key is emailed to the customer once the license is created. The license copies the settings of its policy when it's created: later changes to the policy don't affect it. Its key, policy and customer can't be changed afterwards. **Required role permission**: `license:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
102
+ Without a `key`, the license gets a random one, like `7KQ2M-X9ZPA-H4TRC-WN6EY-B3JDF`: 5 groups of 5 characters separated by dashes, each character an upper case letter or a digit other than `O`, `0`, `I` and `1`. That's 32 possible characters encoding 5 bits each, for 125 random bits. Without a `policyId`, the license follows the product's default policy. Without an `expiresAt`, the license expires after the duration of its policy, or never when the policy has none. `expiresAt: null` makes it never expire. Without a `price`, the price paid for the license is unknown: it's left out of the revenue stats. Without a `cancellableUntil`, the customer can cancel the license during the policy's `moneyBackGuaranteeDays` after its creation, or never when the policy has none. The values of `maxVersion` left out are taken from the max version of the policy: its hard-coded version, or the times after the creation of the license its versions lock. The license belongs to the product's customer with the given `email`, which is created when there's none. With `sendKey: true`, the key is emailed to the customer once the license is created. The license copies the settings of its policy when it's created: later changes to the policy don't affect it. Its key, policy and customer can't be changed afterwards. **Required role permission**: `license:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
26
103
 
27
104
  ### Examples
28
105
 
@@ -683,7 +760,7 @@ nil (empty response body)
683
760
 
684
761
  Update a license
685
762
 
686
- The key, policy and customer of a license can't be changed: sending them does nothing. The changes apply to the next validations of the key, not to the license tokens `validateKey` already returned, which stay valid until they expire. Lowering `maxMachines` doesn't deactivate machines: the ones already active keep validating, and new ones are refused until enough are deactivated. **Required role permission**: `license:update` when called with a session, granted by the member's role. API keys aren't limited by roles.
763
+ The key, policy and customer of a license can't be changed: sending them does nothing. The changes apply to the next validations of the key, not to the license tokens `validateKey` already returned, which stay valid until they expire. Lowering `maxMachines` doesn't deactivate machines: the ones already active keep validating, and new ones replace them one at a time when the product has `autoMachineChange`, or are refused until enough are deactivated. **Required role permission**: `license:update` when called with a session, granted by the member's role. API keys aren't limited by roles.
687
764
 
688
765
  ### Examples
689
766
 
@@ -756,7 +833,7 @@ end
756
833
 
757
834
  Validate a license key
758
835
 
759
- Checks the license key of the product on a machine and returns a token the application can verify offline with the organization's public key. Doesn't need authentication. The license must allow the `version`: up to its `maxVersion.version` when it has one, like `\"2.3\"` for every 2.3.z version and older. Its `maxVersion.lockMajorAt` and `maxVersion.lockMinorAt` are enforced once they hard-code `maxVersion.version`, within the hour they're reached. When it doesn't, the error's `latestAllowedVersion` is the latest release of the product the license allows, so the application can offer to install it. The machine with the `fingerprint` is created when the license has none, and activated when it's deactivated, unless the license is already active on its maximum number of machines. A machine that's already active is never refused for the maximum number of machines, even when it was lowered below the number of active machines. Its `version`, and its `name` and `platform` when given, are updated: they can't be cleared. The checks run in this order, and the first one failing answers: the license has expired, then it doesn't allow the version, then it's on its maximum number of machines. Each failure is recorded as a `license.validation_failed` event, except for keys that don't exist. Changes to the license, like deactivating the machine or shortening its expiration, don't revoke the tokens already returned: the application only sees them when it validates its key again, at the latest when its token expires.
836
+ Checks the license key of the product on a machine and returns a token the application can verify offline with the organization's public key. Doesn't need authentication. The license must allow the `version`: up to its `maxVersion.version` when it has one, like `\"2.3\"` for every 2.3.z version and older. Its `maxVersion.lockMajorAt` and `maxVersion.lockMinorAt` are enforced once they hard-code `maxVersion.version`, within the hour they're reached. When it doesn't, the error's `latestAllowedVersion` is the latest release of the product the license allows, so the application can offer to install it. The machine with the `fingerprint` is created when the license has none, and activated when it's deactivated, unless the license is already active on its maximum number of machines. A machine that's already active is never refused for the maximum number of machines, even when it was lowered below the number of active machines. Its `version`, and its `name` and `platform` when given, are updated: they can't be cleared. Unless the product disables `autoMachineChange`, a new machine isn't refused when the license is on its maximum number of machines: it takes the place of the active machine validated the longest ago, which is deactivated with its `overriddenByMachineId` set to the new machine, and recorded as a `machine.deactivated` event. When a machine deactivated this way is validated again, it takes its place back: the machine that overrode it, and the ones that overrode that one in turn, are locked, with their `overriddenByMachineId` set to the machine coming back. A locked machine is always refused, so two machines can't take turns on one place. The checks run in this order, and the first one failing answers: the license has expired or was canceled, then it doesn't allow the version, then the machine is locked, then it's on its maximum number of machines. Each failure is recorded as a `license.validation_failed` event, except for keys that don't exist. Changes to the license, like deactivating the machine or shortening its expiration, don't revoke the tokens already returned: the application only sees them when it validates its key again, at the latest when its token expires.
760
837
 
761
838
  ### Examples
762
839
 
data/docs/Machine.md CHANGED
@@ -9,8 +9,9 @@
9
9
  | **fingerprint** | **String** | Identifies the machine. Unique within the license. | |
10
10
  | **platform** | **String** | | |
11
11
  | **name** | **String** | | |
12
- | **status** | **String** | Whether the machine counts as using the license. | |
12
+ | **status** | **String** | Whether the machine counts as using the license. A &#x60;locked&#x60; machine doesn&#39;t, and its validations are refused with &#x60;machine_locked&#x60;: it overrode a machine that came back. See &#x60;validateKey&#x60;. | |
13
13
  | **version** | **String** | Version of the application last validated on the machine. | |
14
+ | **overridden_by_machine_id** | **String** | For a machine deactivated or locked by automatic machine changes, the machine that took its place. Validating the key on a deactivated machine that has one takes its place back. &#x60;null&#x60; otherwise. | |
14
15
  | **last_validated_at** | **Time** | When the license was last validated on the machine. | |
15
16
  | **created_at** | **Time** | | |
16
17
  | **updated_at** | **Time** | | |
@@ -28,6 +29,7 @@ instance = LicenseManager::Machine.new(
28
29
  name: Jane&#39;s MacBook,
29
30
  status: active,
30
31
  version: 1.4.2,
32
+ overridden_by_machine_id: null,
31
33
  last_validated_at: 2026-01-15T09:30:00.000Z,
32
34
  created_at: 2026-01-15T09:30:00.000Z,
33
35
  updated_at: 2026-01-15T09:30:00.000Z
data/docs/MachinesApi.md CHANGED
@@ -15,7 +15,7 @@ All URIs are relative to *https://api.licensemanager.dev*
15
15
 
16
16
  Deactivate a machine
17
17
 
18
- The machine no longer counts as using the license, freeing its place when the license has a maximum number of machines. Validating the license key on the machine activates it again, unless the license is on its maximum number of machines by then. Deactivating a deactivated machine does nothing. The license token `validateKey` returned to the machine isn't revoked: the application can keep running offline until it expires. Machines can't be deleted: they're deleted with their license. **Token access**: customer, license, machine tokens with the `machine:write` permission (or the matching write one). A token reaches the machine it's scoped to, or the machines of its license or customer. **Required role permission**: `machine:deactivate` when called with a session, granted by the member's role. API keys aren't limited by roles.
18
+ The machine no longer counts as using the license, freeing its place when the license has a maximum number of machines. Validating the license key on the machine activates it again, unless the license is on its maximum number of machines by then. Deactivating a deactivated or locked machine does nothing. The license token `validateKey` returned to the machine isn't revoked: the application can keep running offline until it expires. Machines can't be deleted: they're deleted with their license. **Token access**: customer, license, machine tokens with the `machine:write` permission (or the matching write one). A token reaches the machine it's scoped to, or the machines of its license or customer. **Required role permission**: `machine:deactivate` when called with a session, granted by the member's role. API keys aren't limited by roles.
19
19
 
20
20
  ### Examples
21
21
 
data/docs/Mrr.md ADDED
@@ -0,0 +1,26 @@
1
+ # LicenseManager::Mrr
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **currency** | **String** | | |
8
+ | **mrr** | **Float** | Monthly recurring revenue: the price of every ongoing subscription in the currency, times its quantity, brought to one month (a year counts for a twelfth), before taxes and discounts. | |
9
+ | **by_interval** | [**Array&lt;MrrByIntervalInner&gt;**](MrrByIntervalInner.md) | Ongoing subscriptions and MRR of each billing period, like monthly and yearly, from the highest MRR. | |
10
+ | **by_policy** | [**Array&lt;MrrByPolicyInner&gt;**](MrrByPolicyInner.md) | MRR of each policy, from the highest. | |
11
+ | **by_month** | **Array&lt;Float&gt;** | MRR at the end of each month, aligned on &#x60;months&#x60;, today for this month, at the current prices of the subscriptions. | |
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ require 'license_manager'
17
+
18
+ instance = LicenseManager::Mrr.new(
19
+ currency: USD,
20
+ mrr: 1240,
21
+ by_interval: null,
22
+ by_policy: null,
23
+ by_month: [900, 1100, 1240]
24
+ )
25
+ ```
26
+
@@ -0,0 +1,24 @@
1
+ # LicenseManager::MrrByIntervalInner
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **interval** | **String** | | |
8
+ | **interval_count** | **Integer** | | |
9
+ | **subscription_count** | **Integer** | | |
10
+ | **mrr** | **Float** | | |
11
+
12
+ ## Example
13
+
14
+ ```ruby
15
+ require 'license_manager'
16
+
17
+ instance = LicenseManager::MrrByIntervalInner.new(
18
+ interval: null,
19
+ interval_count: 1,
20
+ subscription_count: 80,
21
+ mrr: 800
22
+ )
23
+ ```
24
+
@@ -0,0 +1,22 @@
1
+ # LicenseManager::MrrByPolicyInner
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **policy_id** | **String** | | |
8
+ | **subscription_count** | **Integer** | | |
9
+ | **mrr** | **Float** | | |
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ require 'license_manager'
15
+
16
+ instance = LicenseManager::MrrByPolicyInner.new(
17
+ policy_id: p4Rt8LmQ,
18
+ subscription_count: 80,
19
+ mrr: 800
20
+ )
21
+ ```
22
+
data/docs/Policy.md CHANGED
@@ -13,6 +13,7 @@
13
13
  | **max_machines** | **Integer** | Maximum number of active machines of the licenses created with this policy. &#x60;null&#x60; when there&#39;s no limit. | |
14
14
  | **max_offline_duration_seconds** | **Integer** | Longest the applications can run offline with the licenses created with this policy, in seconds. | |
15
15
  | **max_version** | [**PolicyMaxVersion**](PolicyMaxVersion.md) | | |
16
+ | **money_back_guarantee_days** | **Integer** | Number of days after their creation during which customers can cancel the licenses created with this policy, from the customer portal or with &#x60;cancelLicense&#x60;. &#x60;null&#x60; when they can&#39;t. | |
16
17
  | **license_count** | **Integer** | Number of licenses following this policy. | |
17
18
  | **created_at** | **Time** | | |
18
19
  | **updated_at** | **Time** | | |
@@ -32,6 +33,7 @@ instance = LicenseManager::Policy.new(
32
33
  max_machines: 3,
33
34
  max_offline_duration_seconds: 604800,
34
35
  max_version: null,
36
+ money_back_guarantee_days: 30,
35
37
  license_count: 12,
36
38
  created_at: 2026-01-15T09:30:00.000Z,
37
39
  updated_at: 2026-01-15T09:30:00.000Z
@@ -8,6 +8,7 @@
8
8
  | **max_machines** | **Integer** | Maximum number of active machines of the licenses created with this policy, copied to each of them. &#x60;null&#x60; for no limit. Defaults to &#x60;null&#x60;. | [optional] |
9
9
  | **max_offline_duration_seconds** | **Integer** | Longest the applications can run offline with the licenses created with this policy, in seconds, copied to each of them. At least one hour (&#x60;3600&#x60;). Defaults to one week. | [optional] |
10
10
  | **max_version** | [**PolicySettingsMaxVersion**](PolicySettingsMaxVersion.md) | | [optional] |
11
+ | **money_back_guarantee_days** | **Integer** | Number of days after their creation during which customers can cancel the licenses created with this policy, from the customer portal or with &#x60;cancelLicense&#x60;, which refunds their Stripe payment. Each license keeps the end of its own period as &#x60;cancellableUntil&#x60;. &#x60;null&#x60; for no money back guarantee. Defaults to &#x60;null&#x60;. | [optional] |
11
12
 
12
13
  ## Example
13
14
 
@@ -18,7 +19,8 @@ instance = LicenseManager::PolicySettings.new(
18
19
  duration: null,
19
20
  max_machines: 3,
20
21
  max_offline_duration_seconds: 604800,
21
- max_version: null
22
+ max_version: null,
23
+ money_back_guarantee_days: 30
22
24
  )
23
25
  ```
24
26
 
data/docs/PortalApi.md CHANGED
@@ -4,19 +4,98 @@ All URIs are relative to *https://api.licensemanager.dev*
4
4
 
5
5
  | Method | HTTP request | Description |
6
6
  | ------ | ------------ | ----------- |
7
+ | [**create_billing_portal_session**](PortalApi.md#create_billing_portal_session) | **POST** /v1/customers/{id}/billing-portal-sessions | Open the Stripe customer portal of a customer |
7
8
  | [**create_portal_link**](PortalApi.md#create_portal_link) | **POST** /v1/customers/{id}/portal-links | Create a link to the customer portal |
8
9
  | [**get_portal**](PortalApi.md#get_portal) | **GET** /v1/portal/{productId} | Get the customer portal of a product |
9
10
  | [**request_portal_link**](PortalApi.md#request_portal_link) | **POST** /v1/portal/{productId}/request-link | Email a link to the customer portal |
10
11
  | [**send_portal_link**](PortalApi.md#send_portal_link) | **POST** /v1/customers/{id}/portal-links/send | Email a link to the customer portal to the customer |
11
12
 
12
13
 
14
+ ## create_billing_portal_session
15
+
16
+ > <BillingPortalSession> create_billing_portal_session(id, opts)
17
+
18
+ Open the Stripe customer portal of a customer
19
+
20
+ Link to the Stripe customer portal of the customer's Stripe customer, where they manage their subscriptions: change their plan or payment method, see their invoices, cancel. Needs the Stripe integration's `canBillingPortal`, and the customer portal configured in the Stripe account's settings. The changes come back through the integration's webhook, keeping the subscription licenses in line. **Token access**: customer tokens with the `customer:billing` permission (or the matching write one). A customer token reaches its own customer. **Required role permission**: `portalLink:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
21
+
22
+ ### Examples
23
+
24
+ ```ruby
25
+ require 'time'
26
+ require 'license_manager'
27
+ # setup authorization
28
+ LicenseManager.configure do |config|
29
+ # Configure API key authorization: apiKey
30
+ config.api_key['x-api-key'] = 'YOUR API KEY'
31
+ # Uncomment the following line to set a prefix for the API key, e.g. 'Bearer' (defaults to nil)
32
+ # config.api_key_prefix['x-api-key'] = 'Bearer'
33
+
34
+ # Configure Bearer authorization (JWT): token
35
+ config.access_token = 'YOUR_BEARER_TOKEN'
36
+ end
37
+
38
+ api_instance = LicenseManager::PortalApi.new
39
+ id = 'c9Wd3RtE' # String |
40
+ opts = {
41
+ create_billing_portal_session: LicenseManager::CreateBillingPortalSession.new # CreateBillingPortalSession |
42
+ }
43
+
44
+ begin
45
+ # Open the Stripe customer portal of a customer
46
+ result = api_instance.create_billing_portal_session(id, opts)
47
+ p result
48
+ rescue LicenseManager::ApiError => e
49
+ puts "Error when calling PortalApi->create_billing_portal_session: #{e}"
50
+ end
51
+ ```
52
+
53
+ #### Using the create_billing_portal_session_with_http_info variant
54
+
55
+ This returns an Array which contains the response data, status code and headers.
56
+
57
+ > <Array(<BillingPortalSession>, Integer, Hash)> create_billing_portal_session_with_http_info(id, opts)
58
+
59
+ ```ruby
60
+ begin
61
+ # Open the Stripe customer portal of a customer
62
+ data, status_code, headers = api_instance.create_billing_portal_session_with_http_info(id, opts)
63
+ p status_code # => 2xx
64
+ p headers # => { ... }
65
+ p data # => <BillingPortalSession>
66
+ rescue LicenseManager::ApiError => e
67
+ puts "Error when calling PortalApi->create_billing_portal_session_with_http_info: #{e}"
68
+ end
69
+ ```
70
+
71
+ ### Parameters
72
+
73
+ | Name | Type | Description | Notes |
74
+ | ---- | ---- | ----------- | ----- |
75
+ | **id** | **String** | | |
76
+ | **create_billing_portal_session** | [**CreateBillingPortalSession**](CreateBillingPortalSession.md) | | [optional] |
77
+
78
+ ### Return type
79
+
80
+ [**BillingPortalSession**](BillingPortalSession.md)
81
+
82
+ ### Authorization
83
+
84
+ [apiKey](../README.md#apiKey), [token](../README.md#token)
85
+
86
+ ### HTTP request headers
87
+
88
+ - **Content-Type**: application/json
89
+ - **Accept**: application/json
90
+
91
+
13
92
  ## create_portal_link
14
93
 
15
94
  > <PortalLink> create_portal_link(id, create_portal_link)
16
95
 
17
96
  Create a link to the customer portal
18
97
 
19
- Link letting the customer see their licenses and deactivate their machines in the customer portal, without signing in. Anyone with the link can, until it expires or the customer is deleted: it can't be revoked otherwise. The token also works with the API endpoints that accept customer tokens. Links can be created while the product's customer portal is disabled, but the portal answers `404` until it's enabled, and `sendPortalLink` refuses to email them. **Required role permission**: `portalLink:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
98
+ Link letting the customer see their licenses, cancel them during their money back guarantee, and deactivate their machines in the customer portal, without signing in. Anyone with the link can, until it expires or the customer is deleted: it can't be revoked otherwise. The token also works with the API endpoints that accept customer tokens. Links can be created while the product's customer portal is disabled, but the portal answers `404` until it's enabled, and `sendPortalLink` refuses to email them. **Required role permission**: `portalLink:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
20
99
 
21
100
  ### Examples
22
101
 
data/docs/PortalLink.md CHANGED
@@ -5,7 +5,7 @@
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **url** | **String** | Link to the customer portal, holding the token. | |
8
- | **token** | **String** | Customer token in the link, with the &#x60;customer:read&#x60;, &#x60;license:read&#x60; and &#x60;machine:write&#x60; permissions. | |
8
+ | **token** | **String** | Customer token in the link, with the &#x60;customer:read&#x60;, &#x60;license:read&#x60;, &#x60;license:cancel&#x60; and &#x60;machine:write&#x60; permissions. | |
9
9
  | **expires_at** | **Time** | When the link stops working. | |
10
10
 
11
11
  ## Example
@@ -14,7 +14,7 @@
14
14
  require 'license_manager'
15
15
 
16
16
  instance = LicenseManager::PortalLink.new(
17
- url: https://app.example.com/portal/x7Kp2QaZ?token&#x3D;eyJhbGciOi…,
17
+ url: https://app.licensemanager.dev/portal/x7Kp2QaZ?token&#x3D;eyJhbGciOi…,
18
18
  token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…,
19
19
  expires_at: 2026-01-22T09:30:00.000Z
20
20
  )
data/docs/Product.md CHANGED
@@ -10,6 +10,7 @@
10
10
  | **is_test_from_product_id** | **String** | For test products, id of the live product they&#39;re a sandbox of. &#x60;null&#x60; for live products. | |
11
11
  | **logo_url** | **String** | Public URL of the product&#39;s logo, shown in the web app and the customer portal. &#x60;null&#x60; without a logo. | |
12
12
  | **portal** | [**PortalSettings**](PortalSettings.md) | | |
13
+ | **auto_machine_change** | **Boolean** | Whether a new machine validating a license already on its max machines takes the place of the license&#39;s machine validated the longest ago, rather than being refused with &#x60;machine_limit_reached&#x60;. When the replaced machine is validated again, it takes its place back and the machine that replaced it is locked. See &#x60;validateKey&#x60;. | |
13
14
  | **created_at** | **Time** | | |
14
15
  | **updated_at** | **Time** | | |
15
16
 
@@ -25,6 +26,7 @@ instance = LicenseManager::Product.new(
25
26
  is_test_from_product_id: null,
26
27
  logo_url: https://cdn.example.com/logos/x7Kp2QaZ/k3f9a2LpQ7xw.webp,
27
28
  portal: null,
29
+ auto_machine_change: true,
28
30
  created_at: 2026-01-15T09:30:00.000Z,
29
31
  updated_at: 2026-01-15T09:30:00.000Z
30
32
  )
data/docs/ProductStats.md CHANGED
@@ -5,13 +5,13 @@
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **license_count** | **Integer** | Number of licenses of the product. | |
8
- | **active_license_count** | **Integer** | Number of licenses that haven&#39;t expired, and that a machine validated in the last 90 days. | |
8
+ | **active_license_count** | **Integer** | Number of licenses that haven&#39;t expired nor were canceled, and that a machine validated in the last 90 days. | |
9
9
  | **new_license_count** | **Integer** | Number of licenses created in the last 30 days, today included, in UTC. | |
10
- | **expiring_license_count** | **Integer** | Number of licenses expiring in the next 30 days. | |
11
- | **expired_license_count** | **Integer** | Number of licenses that expired in the last 30 days. | |
10
+ | **expiring_license_count** | **Integer** | Number of licenses expiring in the next 30 days, canceled ones left out. | |
11
+ | **expired_license_count** | **Integer** | Number of licenses that expired in the last 30 days, canceled ones left out. | |
12
12
  | **active_machine_count** | **Integer** | Number of active machines of the licenses of the product. | |
13
13
  | **in_use_license_count** | **Integer** | Number of licenses with at least one active machine. | |
14
- | **seat_count** | **Integer** | Sum of the maximum numbers of machines of the licenses that haven&#39;t expired. Licenses without a maximum are left out. | |
14
+ | **seat_count** | **Integer** | Sum of the maximum numbers of machines of the licenses that haven&#39;t expired nor were canceled. Licenses without a maximum are left out. | |
15
15
  | **used_seat_count** | **Integer** | Number of active machines of the licenses counted in &#x60;seatCount&#x60;, at most their maximum number of machines each. | |
16
16
  | **full_license_count** | **Integer** | Number of licenses counted in &#x60;seatCount&#x60; active on their maximum number of machines. | |
17
17
  | **days** | **Array&lt;Date&gt;** | The 30 days covered by the daily stats, from the oldest one, in UTC. | |
@@ -19,6 +19,8 @@
19
19
  | **new_licenses_by_day** | **Array&lt;Integer&gt;** | Number of licenses created each day, aligned on &#x60;days&#x60;. | |
20
20
  | **new_licenses_by_month** | **Array&lt;Integer&gt;** | Number of licenses created each month, aligned on &#x60;months&#x60;. | |
21
21
  | **new_licenses_by_policy** | [**Array&lt;ProductStatsNewLicensesByPolicyInner&gt;**](ProductStatsNewLicensesByPolicyInner.md) | Number of licenses of each policy created each day and each month, for the policies with licenses created over the covered months. | |
22
+ | **cancellation** | [**CancellationStats**](CancellationStats.md) | Cancellations of the licenses with a money back guarantee. &#x60;null&#x60; when no license of the product has one. | |
23
+ | **subscriptions** | [**SubscriptionStats**](SubscriptionStats.md) | Subscriptions of the product. &#x60;null&#x60; when it has never had one. | |
22
24
  | **revenue** | [**Array&lt;Revenue&gt;**](Revenue.md) | Revenue in each currency licenses were sold in, from the one with the most licenses sold. Amounts aren&#39;t converted between currencies. | |
23
25
  | **activations_by_version** | [**Array&lt;ProductStatsActivationsByVersionInner&gt;**](ProductStatsActivationsByVersionInner.md) | Successful activations of the licenses of the product each day, per version of the application, from the most recent one. | |
24
26
  | **active_machines_by_version** | [**Array&lt;ProductStatsActiveMachinesByVersionInner&gt;**](ProductStatsActiveMachinesByVersionInner.md) | Number of active machines running each version of the application, from the most recent one. | |
@@ -45,6 +47,8 @@ instance = LicenseManager::ProductStats.new(
45
47
  new_licenses_by_day: [0, 2, 1],
46
48
  new_licenses_by_month: [4, 9, 12],
47
49
  new_licenses_by_policy: null,
50
+ cancellation: null,
51
+ subscriptions: null,
48
52
  revenue: null,
49
53
  activations_by_version: null,
50
54
  active_machines_by_version: null,
data/docs/ProductsApi.md CHANGED
@@ -21,7 +21,7 @@ All URIs are relative to *https://api.licensemanager.dev*
21
21
 
22
22
  Create a product
23
23
 
24
- Without a `slug`, the product gets one derived from its name: lower cased, without accents and special characters (`Élan Pro 2!` becomes `elan-pro-2`). When another product of the organization already uses it, a dash and 3 random lowercase letters or digits are appended (`elan-pro-2-k3f`), until the slug is free. An explicit `slug` is used as is: the request fails with a `409` when it's taken, it's never changed. Slug uniqueness is enforced by the database, so when concurrent requests end up with the same slug, only one succeeds and the others get a `409`, even without an explicit `slug`. Retrying such a request without a `slug` derives a new one. The product is created with its default policy, named `Default policy` with the `default` slug, whose settings are given by `defaultPolicy`. Omitted settings default to licenses that never expire, on a single machine, offline for one week, for every version of the product. Unlike `createPolicy`, where `maxMachines` defaults to no limit. With `isTestFromProductId`, the product is a test product: its id, its slug, and the ids, slugs and license keys of its resources start with `test_` (`TEST-` for license keys), and only test API keys reach it. It starts with copies of the policies, releases and portal settings of the live product, `defaultPolicy` is ignored. Later changes to the live product aren't copied: reset the test product to copy them again. Test API keys can only create test products, live API keys only live ones. **Required role permission**: `product:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
24
+ Without a `slug`, the product gets one derived from its name: lower cased, without accents and special characters (`Élan Pro 2!` becomes `elan-pro-2`). When another product of the organization already uses it, a dash and 3 random lowercase letters or digits are appended (`elan-pro-2-k3f`), until the slug is free. An explicit `slug` is used as is: the request fails with a `409` when it's taken, it's never changed. Slug uniqueness is enforced by the database, so when concurrent requests end up with the same slug, only one succeeds and the others get a `409`, even without an explicit `slug`. Retrying such a request without a `slug` derives a new one. The product is created with its default policy, named `Default policy` with the `default` slug, whose settings are given by `defaultPolicy`. Omitted settings default to licenses that never expire, on a single machine, offline for one week, for every version of the product. Unlike `createPolicy`, where `maxMachines` defaults to no limit. With `isTestFromProductId`, the product is a test product: its id, its slug, and the ids, slugs and license keys of its resources start with `test_` (`TEST-` for license keys), and only test API keys reach it. It starts with copies of the policies, releases, portal settings and `autoMachineChange` of the live product, `defaultPolicy` is ignored. Later changes to the live product aren't copied: reset the test product to copy them again. Test API keys can only create test products, live API keys only live ones. **Required role permission**: `product:create` when called with a session, granted by the member's role. API keys aren't limited by roles.
25
25
 
26
26
  ### Examples
27
27
 
@@ -454,7 +454,7 @@ end
454
454
 
455
455
  Reset a test product
456
456
 
457
- Deletes the customers, licenses, machines, policies and releases of the test product, with their events, then copies the policies, releases and portal settings of its live product again. Its id, name and slug are kept, but the copied policies get new ids. The tokens of its customers, licenses and machines stop working. **Required role permission**: `product:update` when called with a session, granted by the member's role. API keys aren't limited by roles.
457
+ Deletes the customers, licenses, machines, policies and releases of the test product, with their events, then copies the policies, releases, portal settings and `autoMachineChange` of its live product again. Its id, name and slug are kept, but the copied policies get new ids. The tokens of its customers, licenses and machines stop working. **Required role permission**: `product:update` when called with a session, granted by the member's role. API keys aren't limited by roles.
458
458
 
459
459
  ### Examples
460
460
 
data/docs/Revenue.md CHANGED
@@ -5,8 +5,12 @@
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **currency** | **String** | ISO 4217 code of the currency of the revenue. | |
8
- | **license_count** | **Integer** | Number of licenses sold in the currency, free ones included. | |
9
- | **total** | **Float** | Sum of the prices of the licenses sold in the currency, in major units. | |
8
+ | **license_count** | **Integer** | Number of licenses sold once in the currency, free ones included, canceled ones and subscription licenses left out. | |
9
+ | **total** | **Float** | Revenue in the currency, in major units: the prices of the licenses sold once, canceled ones left out, plus the payments of the subscriptions, &#x60;subscriptionTotal&#x60;. | |
10
+ | **subscription_total** | **Float** | Sum of the payments of the subscription licenses in the currency, before taxes, in major units. | |
11
+ | **payment_count** | **Integer** | Number of payments of the subscription licenses in the currency. | |
12
+ | **canceled_license_count** | **Integer** | Number of canceled licenses sold once in the currency. | |
13
+ | **canceled_total** | **Float** | Sum of the prices of the canceled licenses sold once in the currency, in major units: revenue lost to cancellations. | |
10
14
  | **this_month** | **Float** | Revenue of the current month, in UTC. | |
11
15
  | **last_month** | **Float** | Revenue of the previous month, in UTC. | |
12
16
  | **last30_days** | **Float** | Revenue of the last 30 days, today included, in UTC. | |
@@ -23,6 +27,10 @@ instance = LicenseManager::Revenue.new(
23
27
  currency: USD,
24
28
  license_count: 42,
25
29
  total: 2099.58,
30
+ subscription_total: 480,
31
+ payment_count: 48,
32
+ canceled_license_count: 2,
33
+ canceled_total: 99.98,
26
34
  this_month: 349.93,
27
35
  last_month: 299.94,
28
36
  last30_days: 399.92,
@@ -6,7 +6,7 @@
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **livemode** | **Boolean** | Mode of the Stripe connection the product uses: live for live products, test for test products. | |
8
8
  | **webhook_url_reachable** | **Boolean** | Whether Stripe can reach the API&#39;s webhook URL. A local URL can&#39;t be: set &#x60;WEBHOOK_URL&#x60; on the server, like to a tunnel in development. | |
9
- | **required_permissions** | [**Array&lt;StripePermission&gt;**](StripePermission.md) | Permissions the restricted API key needs, and why. Every other permission can stay &#x60;None&#x60;. | |
9
+ | **required_permissions** | [**Array&lt;StripePermission&gt;**](StripePermission.md) | Permissions the restricted API key needs, and why, the &#x60;optional&#x60; ones included. Every other permission can stay &#x60;None&#x60;. | |
10
10
  | **integration** | [**Integration**](Integration.md) | The organization&#39;s Stripe connection in this mode, &#x60;null&#x60; when there&#39;s none. | |
11
11
  | **mappings** | [**Array&lt;IntegrationMapping&gt;**](IntegrationMapping.md) | Stripe prices creating licenses of the product. | |
12
12
 
@@ -7,6 +7,8 @@
7
7
  | **resource** | **String** | | |
8
8
  | **access** | **String** | | |
9
9
  | **reason** | **String** | | |
10
+ | **optional** | **Boolean** | Whether the key can connect without it, losing what it&#39;s for, explained by &#x60;reason&#x60;. | |
11
+ | **subscriptions** | **Boolean** | Whether it&#39;s only needed to sell subscriptions: checked once a recurring price is mapped. | |
10
12
 
11
13
  ## Example
12
14
 
@@ -16,7 +18,9 @@ require 'license_manager'
16
18
  instance = LicenseManager::StripePermission.new(
17
19
  resource: Prices,
18
20
  access: null,
19
- reason: Lists your prices so you can choose which ones create licenses, and checks they can still be paid.
21
+ reason: Lists your prices so you can choose which ones create licenses, and checks they can still be paid.,
22
+ optional: false,
23
+ subscriptions: false
20
24
  )
21
25
  ```
22
26
 
data/docs/StripePrice.md CHANGED
@@ -9,6 +9,7 @@
9
9
  | **product_name** | **String** | | |
10
10
  | **nickname** | **String** | | |
11
11
  | **price** | [**Price**](Price.md) | | |
12
+ | **recurring** | [**StripePriceRecurring**](StripePriceRecurring.md) | | |
12
13
  | **mapped** | **Boolean** | Whether the price already creates licenses of a product. | |
13
14
 
14
15
  ## Example
@@ -22,6 +23,7 @@ instance = LicenseManager::StripePrice.new(
22
23
  product_name: Acme Pro,
23
24
  nickname: Launch price,
24
25
  price: null,
26
+ recurring: null,
25
27
  mapped: null
26
28
  )
27
29
  ```
@@ -0,0 +1,20 @@
1
+ # LicenseManager::StripePriceRecurring
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **interval** | **String** | | |
8
+ | **interval_count** | **Integer** | | |
9
+
10
+ ## Example
11
+
12
+ ```ruby
13
+ require 'license_manager'
14
+
15
+ instance = LicenseManager::StripePriceRecurring.new(
16
+ interval: null,
17
+ interval_count: 1
18
+ )
19
+ ```
20
+
@@ -0,0 +1,38 @@
1
+ # LicenseManager::SubscriptionStats
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **active_count** | **Integer** | Number of ongoing subscriptions: &#x60;active&#x60;, &#x60;trialing&#x60; or &#x60;past_due&#x60;. | |
8
+ | **trialing_count** | **Integer** | | |
9
+ | **past_due_count** | **Integer** | Number of them whose renewal failed, as Stripe retries it: their licenses stay valid for the integration&#39;s grace days. | |
10
+ | **canceling_count** | **Integer** | Number of them set to end at the end of their period. | |
11
+ | **new_count** | **Integer** | Number of subscriptions started in the last 30 days. | |
12
+ | **ended_count** | **Integer** | Number of subscriptions that ended in the last 30 days. | |
13
+ | **churn_rate** | **Float** | Share of the subscriptions ongoing 30 days ago that ended since, from 0 to 1. | |
14
+ | **new_by_month** | **Array&lt;Integer&gt;** | Number of subscriptions started each month, aligned on &#x60;months&#x60;. | |
15
+ | **ended_by_month** | **Array&lt;Integer&gt;** | Number of subscriptions that ended each month, aligned on &#x60;months&#x60;. | |
16
+ | **active_by_month** | **Array&lt;Integer&gt;** | Number of ongoing subscriptions at the end of each month, aligned on &#x60;months&#x60;, today for this month. | |
17
+ | **mrr** | [**Array&lt;Mrr&gt;**](Mrr.md) | MRR in each currency, from the highest number of subscriptions. Amounts aren&#39;t converted between currencies. | |
18
+
19
+ ## Example
20
+
21
+ ```ruby
22
+ require 'license_manager'
23
+
24
+ instance = LicenseManager::SubscriptionStats.new(
25
+ active_count: 120,
26
+ trialing_count: 4,
27
+ past_due_count: 3,
28
+ canceling_count: 5,
29
+ new_count: 14,
30
+ ended_count: 3,
31
+ churn_rate: 0.025,
32
+ new_by_month: [3, 5, 8],
33
+ ended_by_month: [0, 1, 2],
34
+ active_by_month: [90, 104, 120],
35
+ mrr: null
36
+ )
37
+ ```
38
+