> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stigg.io/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK

<Update label="5.0.0" description="2026-09-02">
  **Consistent entitlement fallbacks across the Node and JavaScript SDKs**

  Entitlement fallbacks, misses and offline reads now behave the same way in both SDKs. Reads served from cache are unchanged, field for field — every change below affects a degraded read only: a configured fallback, a miss, a kind mismatch, offline mode, or a failed read.

  | Change                                                                                             | Migration                                                                                                                                                                                                                                         |
  | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | Credit `isFallback` is now `false` on a plain miss, where it was always `true`                     | ⚠️ If you branch on `isFallback` to mean "no data available", add an `accessDeniedReason` check to tell an unentitled currency from a read that never landed — see the [upgrade note](#credit-isfallback-telling-no-data-from-not-entitled) below |
  | Enum `requestedValues` is `[]` rather than `undefined` when the caller passes none                 | ⚠️ Also affects reads served from cache. `if (entitlement.requestedValues)` now takes the other branch — test for `.length` instead                                                                                                               |
  | Credit `accessDeniedReason` on a fallback is `EntitlementNotFound`, was `Unknown`                  | ⚠️ Update any equality check against `Unknown`                                                                                                                                                                                                    |
  | Metered `requestedUsage` on a fallback is the caller's value (`0` when unset), not a hardcoded `1` | ✅ None. Real metered reads already behaved this way. Also applies to the exported `METERED_DEFAULT_FALLBACK_ENTITLEMENT`                                                                                                                          |
  | A wrong-kind read whose fallback grants access no longer carries `FeatureTypeMismatch`             | ✅ None                                                                                                                                                                                                                                            |
  | Enum `requestedValues` on an unavailable read echoes the caller's values instead of being absent   | ✅ None                                                                                                                                                                                                                                            |
  | A fallback that grants access no longer carries an `accessDeniedReason` (untyped reads)            | ✅ None, unless you read the reason without checking `hasAccess` first                                                                                                                                                                             |
  | `feature` on an untyped fallback is now present, carrying the requested ID and the kind answered   | ✅ None                                                                                                                                                                                                                                            |
  | A configured fallback read through the bulk APIs returns a real entitlement of its own kind        | ✅ None, unless you relied on bulk fallbacks collapsing to an untyped boolean-shaped object. A metered entry now keeps its `usageLimit`                                                                                                            |
  | A fallback's fields belonging to another entitlement kind are dropped rather than echoed           | ⚠️ Configure fallback fields on the kind that owns them — a numeric value no longer rides along on a boolean answer                                                                                                                               |
  | A cached entitlement of a kind you did not ask for is no longer answered as the asked-for kind     | ✅ None. It used to produce a silently incorrect answer                                                                                                                                                                                            |

  Unchanged: the typed reads (`getMeteredEntitlement` and friends) still treat "not in the subscription" as a real answer and ignore the configured fallback, while `getEntitlement` / `getEntitlementV2` still answer from it.

  ### Credit `isFallback`: telling "no data" from "not entitled"

  `isFallback` on a credit read used to be `true` on every miss, so the flag never meant what it says. It now means only what the [fallback strategy](/documentation/high-availability-and-scale/local-caching-and-fallback-strategy) page already documents: the read never reached cached state.

  Consequence: a customer who simply has no entitlement to a currency now comes back with `isFallback: false` and a zeroed balance. Code that used `isFallback` alone to mean "we have no real data" renders that zero as though it were real.

  The check to migrate to:

  ```javascript theme={null}
  const noEntitlementReasons = [
    AccessDeniedReason.EntitlementNotFound,
    AccessDeniedReason.CustomerNotFound,
    AccessDeniedReason.CustomerResourceNotFound,
    AccessDeniedReason.NoActiveSubscription,
    AccessDeniedReason.CustomerIsArchived,
  ];
  const hasBalanceData =
    !entitlement.isFallback &&
    (entitlement.accessDeniedReason == null ||
      !noEntitlementReasons.includes(entitlement.accessDeniedReason));
  ```

  A spent balance is deliberately not in that list: it comes back as a real entitlement carrying `RequestedUsageExceedingLimit`, and its numbers are the ones worth rendering — "0 / 100" and an offer to top up, not "no data".

  If you use `@stigg/react-sdk`'s credit widgets, this is handled for you as of react-sdk 11.0.0 — see the [React SDK changelog](/api-and-sdks/changelog/frontend/react).
</Update>

<Update label="4.6.0" description="2026-06-25">
  **Credit wallet soft limit**

  * Added: `hasSoftLimit` field on `CreditEntitlement`. When a credit entitlement is configured as a soft limit, `getEntitlement()` returns `hasAccess: true` and `hasSoftLimit: true` even after the credit balance reaches zero. Hard limit (the default) continues to return `hasAccess: false` when the balance is exhausted. Credit-backed features inherit the wallet's soft-limit so dependent feature reads stay consistent.
</Update>

<Update label="4.0.0" description="2026-04-01">
  Breaking changes — aligns entitlement types and evaluation behavior with `@stigg/node-server-sdk`:

  | Change                                                                                                                        | Migration                                                                                                                                  |
  | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
  | `entitlementsUpdated` event payload changed from `Map<string, CachedEntitlement>` to `CustomerEntitlementsResultV2`           | Update listeners to iterate `.entitlements` (an `EntitlementV2[]` array) instead of a `Map`.                                               |
  | `EntitlementsState` type removed                                                                                              | Replace imports with `CustomerEntitlementsResult` from `@stigg/js-client-sdk`.                                                             |
  | `resetSettings` on `MeteredEntitlement` removed (was `@deprecated`)                                                           | Use the top-level `resetPeriod` and `usagePeriodEnd` fields directly on the entitlement.                                                   |
  | `getNumericEntitlement()` called on a metered feature now returns a `FeatureTypeMismatch` fallback instead of granting access | Use `getMeteredEntitlement()` for metered features.                                                                                        |
  | `isGranted` on credit entitlements removed                                                                                    | Use `hasAccess` — same semantics, aligned with the shared decision model.                                                                  |
  | `Logger` interface second parameter type widened to `LoggerExtra` (`Record<string, any> \| Error \| Error['stack']`)          | Widen the second parameter of any custom `Logger` implementation to accept `LoggerExtra`. No behavior change needed — type-signature only. |
  | `Entitlement` union type now includes `EnumEntitlement`                                                                       | Add an `EnumEntitlement` branch to any exhaustive `switch`/`case` on `Entitlement`.                                                        |
  | `CreditEntitlementCurrency` named export removed                                                                              | Use `CreditEntitlement['currency']` inline type instead. Shape is unchanged.                                                               |
</Update>

<Update label="3.102.1" description="2026-03-19">
  * Added: `billingCycleAnchor` property when provisioning and updating subscriptions. Accepts `SubscriptionBillingCycleAnchor.UNCHANGED` (default) to keep the existing billing cycle anchor, or `SubscriptionBillingCycleAnchor.NOW` to reset it to the current timestamp.
</Update>

<Update label="3.101.0" description="2026-03-17">
  * Deprecated: `getCreditBalance()` (please use `getCreditEntitlement()` instead). `getCreditEntitlement()` reads directly from the SDK's local cache, significantly reducing latency and removing rate-limit concerns. It returns the same data: `currentBalance`, `totalConsumed`, `totalGranted`, and `currency`.
</Update>

<Update label="3.99.1" description="2026-03-17">
  * Added: `getCreditEntitlement()` method for low-latency retrieval of customer credit balance.
  * Added: Support for provisioning subscriptions with variable recurring credit grant entitlements.
</Update>

<Update label="3.90.0" description="2026-02-26">
  * Enhanced `getCreditEntitlement` to return currency information.
</Update>

<Update label="3.75.0" description="2026-01-24">
  * Added: Support for configuring and managing credit auto-recharge settings, including trigger balance, target top-up amount, and monthly spend limit.
</Update>

<Update label="3.72.0" description="2025-12-07">
  * Added support for subscriptions filter by resourceId and plan (planId/displayName).
</Update>

<Update label="3.60.2" description="2025-09-09">
  * Updated SDK to prevent dependency on [compromised NPM packages](https://www.aikido.dev/blog/npm-debug-and-chalk-packages-compromised)
</Update>

<Update label="3.54.0" description="2025-09-01">
  * Added: `AccessDeniedReason.Revoked` for determining when an entitlement has been explicitly revoked.
</Update>

<Update label="3.42.0" description="2025-06-26">
  * Added: `getSubscriptions` endpoint that allows retrieving all of customers' subscriptions
</Update>

<Update label="3.36.0" description="2025-02-19">
  * Added: ability to determine the number of attempts that were made to collect payment for a generated invoice when Stigg is integrated with Stripe using the `latestInvoice.attemptCount` property of the `getActiveSubscriptions()` and `getSubscription()` endpoints
</Update>

<Update label="3.35.0" description="2025-01-12">
  * Added: [support for offline mode](/api-and-sdks/integration/frontend/javascript#offline-mode)
</Update>

<Update label="3.34.0" description="2024-12-17">
  * Added: `GetUsageHistoryV2`
  * ⚠️ Deprecated: `GetUsageHistory`(please use `GetUsageHistoryV2` instead)
  * Changed:
    * Input Object:
      * `customerRefId` renamed to `customerId`
      * `resourceRefId` renamed to `resourceId`
      * `featureRefId` renamed to `featureId`
      * `resetPeriod` removed
      * `yearlyResetPeriodConfiguration` removed
      * `monthlyResetPeriodConfiguration` removed
      * `weeklyResetPeriodConfiguration` removed
    * Output Object
      * `startDate` removed
      * `endDate` removed
      * `usageMeasurements[i].date` renamed to `series[0].point[i].timestamp`
      * `usageMeasurements[i].value` renamed to `series[0].point[i].value`
      * `usageMeasurements[i].isResetPoint` renamed to `series[0].point[i].isResetPoint`
        * Old Value: `true` if and only if usage was reset due to periodic reset.
        * New Value: `true` if and only if usage was reset due to periodic reset or due to a plan transition.
      * `groups[i].groupInfo[j].key` renamed to `series[i].tags[j].key`
      * `groups[i].groupInfo[j].value` renamed to `series[i].tags[j].value`
      * `groups[i].usageMeasurements[j].date` renamed to `series[i].point[j].timestamp`
      * `groups[i].usageMeasurements[j].value` renamed to `series[i].point[j].value`
      * `groups[i].usageMeasurements[j].isResetPoint` renamed to `series[i].point[j].isResetPoint`
        * Old Value: `true` if and only if usage was reset due to periodic reset.
        * New Value: `true` if and only if usage was reset due to periodic reset or due to a plan transition.
</Update>

<Update label="3.33.0" description="2024-12-08">
  * Added: ability to override prices when there's a scheduled update in place
</Update>

<Update label="3.31.0" description="2024-11-21">
  * Added: support for price localization in fixed fee coupons
</Update>

<Update label="3.30.0" description="2024-10-14">
  * Added: ability to estimate the subscription cost when the payment of the subscription is delegated to a different customer using:
    * `PreviewSubscription.payingCustomerId`
    * `EstimateSubscription.payingCustomerId`
    * `EstimateSubscriptionUpdate.payingCustomerId`
</Update>

<Update label="3.27.0" description="2024-10-08">
  * Added: ability to more easily determine the usage period of metered entitlements using:
    * `MeteredEntitlement.usagePeriodStart`
    * `MeteredEntitlement.usagePeriodEnd`
  * 🛑 Removed: `MeteredEntitlement.nextResetDate`
</Update>

<Update label="3.20.0" description="2024-06-20">
  * Added: ability to get the list of active subscriptions from Edge using `getActiveSubscriptionsList()`
</Update>

<Update label="3.19.0" description="2024-06-20">
  * Added: ability to get the details of a specific subscription using `getSubscription()`
</Update>


## Related topics

- [JavaScript](/api-and-sdks/integration/frontend/javascript.md)
- [React](/api-and-sdks/integration/frontend/react.md)
- [React SDK](/api-and-sdks/changelog/frontend/react.md)
- [Handling reported usage](/documentation/getting-usage-data-into-stigg/handling-reported-usage.md)
- [API Client (JS)](/api-and-sdks/changelog/backend-graphql/api-client-js.md)
