Skip to main content
May 9, 2026

Improvements

KelviqProvidercustomerId and plansEnabled Props for Pricing

The pricing request now forwards two additional optional props to the product offerings API.customerId — when provided, the pricing response is personalized to that customer (e.g. reflecting their existing subscription state):
plansEnabled — a comma-separated list of plan identifiers to include in the response. When omitted, all active plans are returned:
Both props are reactive — updating either value will trigger a new pricing fetch automatically.
May 9, 2026

New Features

Product Offerings — Pricing & Feature Components

The SDK now supports fetching and displaying product pricing and plan features, with localized currency based on user location.
Setup
Pass productId and enable fetchPricingOnMount in your provider config:
usePricing() — Pricing Data Hook
Returns the full pricing API response as an AsyncState. Only populated when fetchPricingOnMount is enabled, or after calling refreshPricing() from useKelviq().
<KQPrice /> — Render-Prop Price Component
Displays localized pricing for a plan and billing period:
The render prop receives:
<KQFeatureList /> — Render-Prop Feature Component
Iterates over enabled features for a plan. Supports optional filtering by feature type:
kqFormatPrice() — Price Formatter Utility
Standalone utility for formatting a numeric amount with a currency symbol:
New Types
New Exports
February 27, 2026

New Features

Duplicate featureId Aggregation

The SDK now handles customers with multiple subscriptions that grant entitlements to the same feature. Raw entries are grouped by featureId and aggregated automatically:
  • METER: usageLimit and currentUsage are summed across entries; remaining is recalculated
  • BOOLEAN / CUSTOMIZABLE: hasAccess is OR’d across entries (any truetrue) The raw un-aggregated entries are preserved in the items array on each Entitlement.

getEntitlements() — Convenience Accessor

Returns the aggregated entitlements map directly, without the AsyncState wrapper:

getRawEntitlements() — Raw API Response

Access the un-aggregated API response with the customerId wrapper:

getRawEntitlement(featureId) — Raw Data for a Single Feature

Returns the raw API response filtered to a specific featureId:

updateEntitlement() — Client-Side Entitlement Mutation

Update an entitlement in-place, for example after recording a usage increment on the client side. The remaining field is automatically recalculated.
Accepts Partial<Omit<Entitlement, 'featureId' | 'featureType' | 'items'>>.

environment Prop on KelviqProvider

Supports 'production' (default) and 'sandbox', which selects the appropriate default API URL:

Breaking Changes

Unified Entitlement Type

The three separate entitlement interfaces and their union type have been replaced by a single unified Entitlement interface:

featureKey Renamed to featureId

All props, parameters, and type fields now use featureId to match the backend API naming:

Config Renamed to Customizable

type Field Renamed to featureType with Uppercase Values

configuration Field Removed

ConfigEntitlement.configuration has been removed. Customizable entitlements now use the same usageLimit, currentUsage, and remaining fields as metered entitlements.

Hooks Return Entitlement | null Directly

All entitlement hooks now return the entitlement object directly (or null) instead of an AsyncState wrapper. Use the top-level isLoading and error from useKelviq() for loading/error states.

getEntitlement() Simplified

The generic type parameter and second argument have been removed:

hasAccess() Returns boolean (Never undefined)

hasAccess(featureId) now returns false when data is unavailable instead of undefined. No need for nullish checks.

Metered Field Renames

allEntitlements.data Shape Changed

The map is now keyed by featureId (previously featureKey) and contains unified Entitlement objects. Use the new getEntitlements() convenience method:

Migration Checklist

  1. Replace all featureKey props/params with featureId
  2. Replace entitlement.type with entitlement.featureType and update values to uppercase
  3. Replace useConfigEntitlement with useCustomizableEntitlement
  4. Replace ShowWhenConfigEntitled with ShowWhenCustomizableEntitled
  5. Replace ConfigEntitlement.configuration with usageLimit / currentUsage / remaining
  6. Update hook consumers: hooks now return Entitlement | null directly (not AsyncState)
  7. Remove type parameters from getEntitlement() calls
  8. Replace limitusageLimit, usedcurrentUsage
  9. Replace entitlement.resetAt with entitlement.items[].resetAt
  10. Use getEntitlements() instead of allEntitlements.data
  11. Use getRawEntitlements() for un-aggregated API data
February 27, 2026

New Features

Duplicate featureId Aggregation

The SDK now handles customers with multiple subscriptions that grant entitlements to the same feature. Raw entries are grouped by featureId and aggregated automatically:
  • METER: usageLimit and currentUsage are summed across entries; remaining is recalculated
  • BOOLEAN / CUSTOMIZABLE: hasAccess is OR’d across entries (any truetrue)
The raw un-aggregated entries are preserved in the items array on each Entitlement.

getEntitlements() — Convenience Accessor

Returns the aggregated entitlements map directly, without the AsyncState wrapper:

getRawEntitlements() — Raw API Response

Access the un-aggregated API response with the customerId wrapper:

getRawEntitlement(featureId) — Raw Data for a Single Feature

Returns the raw API response filtered to a specific featureId:

updateEntitlement() — Client-Side Entitlement Mutation

Update an entitlement in-place, for example after recording a usage increment on the client side. The remaining field is automatically recalculated.
Accepts Partial<Omit<Entitlement, 'featureId' | 'featureType' | 'items'>>.

environment Prop on KelviqProvider

Supports 'production' (default) and 'sandbox', which selects the appropriate default API URL:

Breaking Changes

Unified Entitlement Type

The three separate entitlement interfaces and their union type have been replaced by a single unified Entitlement interface:

featureKey Renamed to featureId

All props, parameters, and type fields now use featureId to match the backend API naming:

Config Renamed to Customizable

type Field Renamed to featureType with Uppercase Values

configuration Field Removed

ConfigEntitlement.configuration has been removed. Customizable entitlements now use the same usageLimit, currentUsage, and remaining fields as metered entitlements.

Hooks Return Entitlement | null Directly

All entitlement hooks now return the entitlement object directly (or null) instead of an AsyncState wrapper. Use the top-level isLoading and error from useKelviq() for loading/error states.

getEntitlement() Simplified

The generic type parameter and second argument have been removed:

hasAccess() Returns boolean (Never undefined)

hasAccess(featureId) now returns false when data is unavailable instead of undefined. No need for nullish checks.

Metered Field Renames

allEntitlements.data Shape Changed

The map is now keyed by featureId (previously featureKey) and contains unified Entitlement objects. Use the new getEntitlements() convenience method:

Migration Checklist

  1. Replace all featureKey props/params with featureId
  2. Replace entitlement.type with entitlement.featureType and update values to uppercase
  3. Replace useConfigEntitlement with useCustomizableEntitlement
  4. Replace ShowWhenConfigEntitled with ShowWhenCustomizableEntitled
  5. Replace ConfigEntitlement.configuration with usageLimit / currentUsage / remaining
  6. Update hook consumers: hooks now return Entitlement | null directly (not AsyncState)
  7. Remove type parameters from getEntitlement() calls
  8. Replace limitusageLimit, usedcurrentUsage
  9. Replace entitlement.resetAt with entitlement.items[].resetAt
  10. Use getEntitlements() instead of allEntitlements.data
  11. Use getRawEntitlements() for un-aggregated API data