@kelviq/react-sdk provides a seamless way to integrate kelviq entitlement management into your React applications.
Overview
- A React Context Provider (
KelviqProvider) to initialize and configure the SDK. - Hooks to easily access entitlement status and data within your components.
- Conditional rendering components to show or hide UI elements based on feature access.
- Automatic and manual data fetching and caching mechanisms.
2. Installation
Install the SDK using npm or yarn:react as a peer dependency.
3. Setup & Configuration
KelviqProvider
The core of the SDK is the KelviqProvider. You need to wrap your application (or the relevant part of it) with this provider. It initializes the SDK and makes entitlement data available to its children components via context.
Required Props for KelviqProvider
customerId: string- The ID of the customer for whom entitlements are being fetched. This will be sent as a query parameter (
customer_id).
- The ID of the customer for whom entitlements are being fetched. This will be sent as a query parameter (
accessToken: string | null- Your Client API Key for authenticating requests to the Kelviq API. This key is safe to expose in client-side code. You can find it in the Developers section of your Kelviq dashboard. Never use your Server API Key in client-side code.
Optional Props for KelviqProvider
4. Fetching Entitlements
Automatic Fetching on Mount
By default (fetchEntitlementsOnMount: true in the config prop, or if config or this specific option is omitted), the SDK will attempt to fetch all entitlements for the specified customerId as soon as the KelviqProvider is mounted.
The isLoading state from useKelviq() will be true during this initial fetch.
Manual Fetching
IffetchEntitlementsOnMount is set to false, or if you need to re-fetch entitlements at any point (e.g., after a user action that might change their entitlements), you can use the refreshAllEntitlements function.
5. Accessing Entitlement Data (Hooks)
The SDK provides several hooks to access entitlement data and SDK state.useKelviq()
This is the primary hook to access the SDK’s context.
- Returns:
KelviqContextValueobject containing:allEntitlements: AsyncState<EntitlementMap | null>: The state object for all fetched entitlements.data: AnEntitlementMap(aRecord<string, Entitlement>) where keys arefeatureIds, ornullif not loaded or error.isLoading: Boolean indicating if theallEntitlementsdata is currently being fetched/refreshed.error: AnErrorobject if the last fetch failed, otherwisenull.
refreshAllEntitlements: () => Promise<void>: Function to manually trigger a re-fetch of all entitlements.getEntitlements: () => EntitlementMap: Returns all aggregated entitlements as aRecord<string, Entitlement>keyed byfeatureId. Returns an empty object if data has not been fetched yet.getEntitlement: (featureId: string) => Entitlement | null: Returns the aggregated entitlement for a givenfeatureId, ornullif not found or not yet loaded.getRawEntitlements: () => EntitlementsResponse | null: Returns the raw API response withcustomerIdand the un-aggregatedentitlementsarray (duplicatefeatureIdentries are preserved). Returnsnullif data has not been fetched yet.getRawEntitlement: (featureId: string) => EntitlementsResponse | null: Returns the raw API response filtered to a specificfeatureId, withcustomerIdand only the matching entries.hasAccess: (featureId: string) => boolean: A utility function to quickly check access for a feature. Returnstrueif access is granted,falseif denied, feature not found, or data is not yet loaded.updateEntitlement: (featureId: string, data: Partial<...>) => void: Updates a cached entitlement in-place. Accepts partial data (excludingfeatureId,featureType, anditems). Automatically recalculatesremainingwhenusageLimitorcurrentUsageare updated.subscriptions: AsyncState<RawSubscriptionData[] | null>: The state object for the customer’s subscriptions. Only populated whenfetchSubscriptionsOnMountistrueor after callingrefreshSubscriptions().refreshSubscriptions: () => Promise<void>: Function to manually trigger a re-fetch of the customer’s subscriptions.customer: AsyncState<RawCustomerApiResponse | null>: The state object for customer data. Only populated whenfetchCustomerOnMountistrueor after callingrefreshCustomer().refreshCustomer: () => Promise<void>: Function to manually trigger a re-fetch of the customer data.isLoading: boolean: A global loading state indicating if the SDK is performing its initial configured fetch or a refresh operation.error: Error | null: A global error state reflecting any error from the last fetch operation initiated by the provider.customerId: string: The customer ID passed to the provider.environment: string: The environment ('production'or'sandbox') passed to the provider.apiUrl: string: The resolved API URL used by the provider.entitlementsPath: string: The entitlements path passed to the provider.
hasAccess(featureId)
Quickly check if a customer has access to a feature.
Response
Response
getEntitlement(featureId)
Returns the aggregated entitlement for a given feature. When the API returns multiple entries for the same featureId (e.g. from different subscriptions), the SDK groups them and exposes aggregated totals at the top level.
Response — Metered Entitlement
Response — Metered Entitlement
Response — Boolean Entitlement
Response — Boolean Entitlement
Response — Customizable Entitlement
Response — Customizable Entitlement
getEntitlements()
Returns all aggregated entitlements as a Record<string, Entitlement> keyed by featureId.
Response
Response
getRawEntitlements()
Returns the raw, un-aggregated API response with customerId. Duplicate featureId entries from multiple subscriptions are preserved as-is.
Response
Response
getRawEntitlement(featureId)
Returns the raw API response filtered to a specific featureId. Useful for accessing per-subscription data for a single feature.
Response
Response
updateEntitlement(featureId, data)
Updates a cached entitlement in-place. Useful for optimistically updating the UI after a usage increment without waiting for a full refresh. The remaining field is automatically recalculated when usageLimit or currentUsage are updated.
Updated Entitlement
Updated Entitlement
Partial<Omit<Entitlement, 'featureId' | 'featureType' | 'items'>>. You can update any combination of hasAccess, currentUsage, usageLimit, and remaining.
useAllEntitlements()
A convenience hook that directly returns the allEntitlements state object.
- Returns:
AsyncState<EntitlementMap | null>
Response — entitlementsMap
Response — entitlementsMap
useBooleanEntitlement(featureId: string)
Returns the aggregated entitlement for a specific boolean feature from the cache.
- Arguments:
featureId: string: The identifier of the boolean feature.
- Returns:
Entitlement | null
Response
Response
useCustomizableEntitlement(featureId: string)
Returns the aggregated entitlement for a specific customizable feature from the cache.
- Arguments:
featureId: string: The identifier of the customizable feature.
- Returns:
Entitlement | null
Response
Response
useMeteredEntitlement(featureId: string)
Returns the aggregated entitlement for a specific metered feature from the cache.
- Arguments:
featureId: string: The identifier of the metered feature.
- Returns:
Entitlement | null
Response
Response
useSubscriptions()
Returns the customer’s subscription data. Only populated when fetchSubscriptionsOnMount is enabled in the provider config, or after calling refreshSubscriptions() from useKelviq().
- Returns:
AsyncState<RawSubscriptionData[] | null>
Response — subscriptions
Response — subscriptions
You must enable
fetchSubscriptionsOnMount: true in the provider’s config prop, or call refreshSubscriptions() manually, for this hook to return data.useCustomer()
Returns the customer data. Only populated when fetchCustomerOnMount is enabled in the provider config, or after calling refreshCustomer() from useKelviq().
- Returns:
AsyncState<RawCustomerApiResponse | null>
Response — customer
Response — customer
You must enable
fetchCustomerOnMount: true in the provider’s config prop, or call refreshCustomer() manually, for this hook to return data.6. Conditional Rendering Components
These components provide a declarative way to render UI based on entitlement status. They internally use the respective hooks. Common Props:featureId: string: The unique identifier of the feature to check.children: ReactNode | ((data: Entitlement) => ReactNode):- If a
ReactNode, it’s rendered when the user is entitled and conditions are met. - If a function (render prop), it’s called with the aggregated
Entitlementdata and its return value is rendered.
- If a
fallback?: ReactNode: Content to render if the user is not entitled, or if data is loading (and noloadingComponentis provided), or if an error occurs. Defaults tonull.loadingComponent?: ReactNode: Specific content to render while the entitlement data is loading. Overridesfallbackduring loading.
ShowWhenBooleanEntitled
Renders children if the boolean feature is enabled (hasAccess: true).
Render Prop Data (entitlementData)
Render Prop Data (entitlementData)
ShowWhenCustomizableEntitled
Renders children if the customizable feature is enabled (hasAccess: true).
Render Prop Data (entitlementData)
Render Prop Data (entitlementData)
ShowWhenMeteredEntitled
Renders children if the metered feature is enabled and, by default, if remaining usage is greater than 0 or unlimited (usageLimit is null).
- Optional Prop:
condition?: (data: Entitlement) => boolean: A custom function to further determine if children should render based on the entitlement data.
- Children Prop: Can be
ReactNodeor(data: Entitlement) => ReactNode.
Render Prop Data (meterData)
Render Prop Data (meterData)
7. Key Types
The SDK exports several types for better integration with TypeScript. Some key ones include:KelviqContextValue: The shape of the object returned byuseKelviq().KelviqApiBehaviorOptions: Configuration options for theconfigprop.AsyncState<T>: Generic type for asynchronous data states ({ data, isLoading, error }).Entitlement: The unified entitlement type with aggregated data and anitemsarray containing the raw API objects.EntitlementMap: The structure of the cached entitlements (Record<string, Entitlement>), keyed byfeatureId.EntitlementsResponse: The raw API response shape ({ customerId, entitlements }) returned bygetRawEntitlements()andgetRawEntitlement().RawEntitlementsApiResponseand relatedRaw...types: Represent the structure of the direct API response.RawSubscriptionData: A single subscription object as returned by the subscriptions API, includingplan,product,features,status,amount,recurrence, etc.RawCustomerApiResponse: Customer data as returned by the customer API, includingid,customerId,name,email,billingAddress,details,metadata,createdOn, andmodifiedOn.RawBillingAddress: The billing address object (country,line1,line2,postalCode,city,state).
8. Error Handling
- Provider Level: The
onErrorcallback inconfig(KelviqApiBehaviorOptions) can be used to globally handle errors that occur during the entitlement fetching process initiated by the provider. - Context Level:
useKelviq()returns a globalisLoading: booleananderror: Error | nullstate, reflecting the provider’s most recent fetch operation. Use these for loading/error UI in your components. allEntitlementsLevel: TheallEntitlementsobject fromuseKelviq()oruseAllEntitlements()also carries its ownisLoadinganderrorfields within theAsyncStatewrapper.
9. Example Usage
A comprehensive example is provided within the comments of the SDK code, demonstrating provider setup and component usage. The core setup involves:- Wrapping your application with
KelviqProviderand providing the required props (customerId,accessToken) - Using hooks like
useBooleanEntitlementor conditional components likeShowWhenBooleanEntitledin your components to control UI and behavior based on entitlements.
10. API Request Service
The SDK relies on anapiRequest function for making HTTP requests. The SDK’s KelviqProvider passes configuration like timeout, maxRetries, backoffBaseDelay, and accessToken to this function.
- Your Responsibility: You need to ensure that your project includes an implementation of this
apiRequestservice (e.g., insrc/services/makeRequest.service.ts) that matches theApiRequestConfigandApiResponseinterfaces used by the SDK. This service should handle actual HTTP communication, including appending query parameters passed viaApiRequestConfig.queryParamsand using theaccessTokento set theAuthorizationheader. - The placeholder
apiRequestfunction included in the SDK’s source code is for demonstration and type-checking purposes only and will not make real API calls.
11. Project Structure (for contributors/reference)
The SDK source code (lib/) is organized as follows:
components/: Contains conditional rendering React components.ShowWhenBooleanEntitled.tsxShowWhenCustomizableEntitled.tsxShowWhenMeteredEntitled.tsxShowWhenEntitledInternal.tsx(Internal helper, not typically exported)
contexts/: Defines the React Context and Provider.KelviqContext.tsKelviqProvider.tsx
hooks/: Contains all custom React Hooks.useKelviq.tsuseAllEntitlements.tsuseBooleanEntitlement.tsuseCustomizableEntitlement.tsuseMeteredEntitlement.tsuseSubscriptions.tsuseCustomer.tsindex.ts(Exports all hooks)
types/: Contains all TypeScript definitions.api.types.ts(Raw types from API)sdk.types.ts(Processed types for SDK and public use)index.ts(Re-exports all types)
utils/: Contains utility functions.transformations.ts(FortransformApiEntitlements)index.ts(Exports utilities)
index.ts: The main entry point of the SDK, re-exporting all public APIs (provider, hooks, components, types).
Using the Sandbox
If you want to use the sandbox, you need to set theenvironment option to sandbox in the KelviqProvider.