","Email":"configcat@example.com","Country":"US","SubscriptionType":"Pro","Role":"Admin","version":"1.0.0"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'False' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'True' => MATCH, applying rule
Returning 'True'.
```
### Logging Implementation[](#logging-implementation "Direct link to Logging Implementation")
You have the flexibility to use any slf4j implementation for logging with ConfigCat. However, some logger implementations may not display debug level messages by default. In these cases, you simply need to adjust the logger configuration to receive all log messages from the ConfigCat SDK.
Examples for [android-logger](https://github.com/configcat/android-sdk/blob/master/samples/android-kotlin/app/src/android-logger.properties) and [logback](https://github.com/configcat/android-sdk/blob/master/samples/android-java/app/src/main/assets/logback.xml) are available under the [Sample Apps](#sample-apps) section.
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by implementing the `LogFilterFunction` interface. The `apply` method will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `logLevel` option). That is, the `apply` method allows you to filter log events by `logLevel`, `eventId`, `message` or `exception`. The formatted message string can be obtained by calling `toString()` on the `message` parameter. If the `apply` method returns `true`, the event will be logged, otherwise it will be skipped.
```java
// Filter out events with id 1001 from the log.
LogFilterFunction filterLogFunction = ( LogLevel logLevel, int eventId, Object message, Throwable exception) -> eventId != 1001;
ConfigCatClient client = ConfigCatClient.get("#YOUR-SDK-KEY#", options -> options.logFilter(filterLogFunction));
```
caution
Please make sure that your log filter logic doesn't perform heavy computation and doesn't block the executing thread. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the ConfigCat SDK that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Sample App[](#sample-apps "Direct link to Sample App")
[Android App with auto polling and change listener](https://github.com/configcat/android-sdk/tree/master/samples)
## Guides[](#guides "Direct link to Guides")
See [this](https://configcat.com/blog/2022/01/24/feature-flags-in-android/) guide on how to use ConfigCat's Android SDK.
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat Android SDK's repository on GitHub](https://github.com/configcat/android-sdk)
* [ConfigCat Android SDK's javadoc page](https://javadoc.io/doc/com.configcat/configcat-android-client)
* [ConfigCat Android SDK on Maven Central](https://search.maven.org/artifact/com.configcat/configcat-android-client)
---
# Source: https://configcat.com/docs/sdk-reference/openfeature/angular.md
# Using ConfigCat's OpenFeature Provider in Angular
Copy page
## Getting started[](#getting-started "Direct link to Getting started")
OpenFeature offers an [Angular SDK](https://github.com/open-feature/js-sdk/tree/main/packages/angular) to streamline the use of OpenFeature in Angular applications. This SDK is built on top of the [OpenFeature JavaScript Web SDK](https://github.com/open-feature/js-sdk/blob/main/packages/web).
Since ConfigCat implements [a provider](https://configcat.com/docs/sdk-reference/openfeature/js.md) for the Web SDK, you can use ConfigCat with the OpenFeature Angular SDK, as explained below.
### 1. Install the Angular SDK and the ConfigCat provider[](#1-install-the-angular-sdk-and-the-configcat-provider "Direct link to 1. Install the Angular SDK and the ConfigCat provider")
```bash
npm i @openfeature/angular-sdk @openfeature/config-cat-web-provider
```
### 2. Initialize the Angular SDK[](#2-initialize-the-angular-sdk "Direct link to 2. Initialize the Angular SDK")
The `ConfigCatWebProvider.create()` function takes the SDK key and an optional `options` argument containing additional configuration options for the underlying [ConfigCat client](https://configcat.com/docs/sdk-reference/js/browser.md#creating-the-configcat-client):
* For applications using modules:
```ts
import { NgModule } from '@angular/core';
import { BooleanFeatureFlagDirective, type EvaluationContext, OpenFeatureModule } from '@openfeature/angular-sdk';
import { ConfigCatWebProvider } from '@openfeature/config-cat-web-provider';
import { createConsoleLogger, LogLevel } from '@configcat/sdk';
const configCatProvider = ConfigCatWebProvider.create('#YOUR-SDK-KEY#', {
// Specify options for the underlying ConfigCat client
logger: createConsoleLogger(LogLevel.Info),
setupHooks: (hooks) => hooks.on('clientReady', () => console.log('Client is ready!')),
// ...
});
// Set the initial context for your evaluations
const initialContext: EvaluationContext = {
targetingKey: 'user-1',
admin: false
};
@NgModule({
declarations: [
// ...
],
imports: [
// ...
OpenFeatureModule.forRoot({
provider: configCatProvider,
context: initialContext
}),
// Alternatively, you can import the directive directly in your components
BooleanFeatureFlagDirective
],
exports: [
// Not needed if you import the directive directly in your components
BooleanFeatureFlagDirective
],
bootstrap: [/* ... */]
})
export class AppModule { }
```
* For applications using standalone components:
```ts
import { type ApplicationConfig, importProvidersFrom } from '@angular/core';
import { type EvaluationContext, OpenFeatureModule } from '@openfeature/angular-sdk';
import { ConfigCatWebProvider } from '@openfeature/config-cat-web-provider';
import { createConsoleLogger, LogLevel } from '@configcat/sdk';
const configCatProvider = ConfigCatWebProvider.create('#YOUR-SDK-KEY#', {
// Specify options for the underlying ConfigCat client
logger: createConsoleLogger(LogLevel.Info),
setupHooks: (hooks) => hooks.on('clientReady', () => console.log('Client is ready!')),
// ...
});
// Set the initial context for your evaluations
const initialContext: EvaluationContext = {
targetingKey: 'user-1',
admin: false
};
export const appConfig: ApplicationConfig = {
providers: [
// ...
importProvidersFrom(
OpenFeatureModule.forRoot({
provider: configCatProvider,
context: initialContext
})
)
]
};
```
### 3. Use your feature flag[](#3-use-your-feature-flag "Direct link to 3. Use your feature flag")
```html
This is shown when the feature flag is enabled.
This is shown when the feature flag is disabled.
This is shown when the feature flag is initializing.
This is shown when the feature flag is reconciling.
```
## Evaluation Context[](#evaluation-context "Direct link to Evaluation Context")
An [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) in the OpenFeature specification is a container for arbitrary contextual data that can be used as a basis for feature flag evaluation.
You can find [here](https://configcat.com/docs/sdk-reference/openfeature/js.md#evaluation-context) how the ConfigCat provider translates these evaluation contexts to ConfigCat [User Objects](https://configcat.com/docs/sdk-reference/js/browser.md#user-object).
## Advanced features[](#advanced-features "Direct link to Advanced features")
Read the documentation of the [OpenFeature Angular SDK](https://openfeature.dev/docs/reference/technologies/client/web/angular/) to learn more about the advanced capabilities of the SDK.
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat OpenFeature Provider's repository on GitHub](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/config-cat-web)
* [ConfigCat OpenFeature Provider in NPM](https://www.npmjs.com/package/@openfeature/config-cat-web-provider)
---
# Source: https://configcat.com/docs/api/reference/audit-logs.md
# Audit logs
Copy page
Access audit log entries.
## [📄️ List Audit log items for Product](https://configcat.com/docs/api/reference/get-auditlogs.md)
[This endpoint returns the list of Audit log items for a given Product](https://configcat.com/docs/api/reference/get-auditlogs.md)
## [📄️ List Deleted Settings](https://configcat.com/docs/api/reference/get-deleted-settings.md)
[This endpoint returns the list of Feature Flags and Settings that were deleted from the given Config.](https://configcat.com/docs/api/reference/get-deleted-settings.md)
## [📄️ List Audit log items for Organization](https://configcat.com/docs/api/reference/get-organization-auditlogs.md)
[This endpoint returns the list of Audit log items for a given Organization](https://configcat.com/docs/api/reference/get-organization-auditlogs.md)
---
# Source: https://configcat.com/docs/advanced/team-management/saml/identity-providers/auth0.md
# Auth0 Identity Provider
Copy page
Connect ConfigCat with Auth0 via SAML.
## Introduction[](#introduction "Direct link to Introduction")
Each SSO Identity Provider requires specific information to configure a SAML integration. The following guide will walk you through how you can connect ConfigCat with Auth0 as a SAML Identity Provider.
## 1. Create an Application in Auth0[](#1-create-an-application-in-auth0 "Direct link to 1. Create an Application in Auth0")
* Log in to [Auth0](https://auth0.com/auth/login), select `Applications` from the menu, then click `Create Application`.

* Enter a descriptive `Name`, select `Regular Web Applications`, then click `Create`.

* Select the `Addons` tab, and click `SAML2`.

The next step will guide you on how to collect the information required for the appearing configuration dialog.
## 2. Configure SAML for the Auth0 Application[](#2-configure-saml-for-the-auth0-application "Direct link to 2. Configure SAML for the Auth0 Application")
* Open your organization's authentication settings on the [ConfigCat Dashboard](https://app.configcat.com/organization/authentication).

* Click `ADD SAML IDENTITY PROVIDER`.

* Give a name for your Identity Provider, and click `Create`.

* From the next section of the dialog, copy the following values and paste them into the Auth0 configuration dialog.
* `Entity ID` -> `"audience": ""` in the configuration JSON below.
* `Assertion Consumer Service` -> `Application Callback URL`
* For `Settings`, use the following JSON value:
```text
{
"audience": "",
"signatureAlgorithm": "rsa-sha256",
"nameIdentifierProbes": [
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
]
}
```
 
* Click on `Save`.
## 3. Configure ConfigCat with SAML Details from Auth0[](#3-configure-configcat-with-saml-details-from-auth0 "Direct link to 3. Configure ConfigCat with SAML Details from Auth0")
You can choose one of the following options to configure ConfigCat with SAML Identity Provider metadata.
* Metadata URL
* Manual Configuration
- Copy the URL of `Identity Provide metadata`.

- Paste the copied value into the `Metadata URL` field at ConfigCat.

- Select the **trusted domains**. Only user accounts from trusted domains can login with SAML SSO. You can bind multiple verified domains to a SAML Identity Provider.

- Click on `Save`.
* Copy the value of `Identity Provider Login URL` and download the `Identity Provider Certificate`, then paste them into the Configuration dialog at ConfigCat.

* Select the **trusted domains**. Only user accounts from trusted domains can login with SAML SSO. You can bind multiple verified domains to a SAML Identity Provider.

* Click on `Save`.
## 4. Sign In[](#4-sign-in "Direct link to 4. Sign In")
* Go to the [ConfigCat Log In](https://app.configcat.com) page, and click `COMPANY ACCOUNT - SAML`.

* Sign in with your company email address assigned to the Auth0 application.

* ConfigCat will redirect you to Auth0's sign in page. Type your credentials, and click `Continue`.

* You should be redirected to ConfigCat signed in with your company account.
## 5. Next Steps[](#5-next-steps "Direct link to 5. Next Steps")
* Configure the [auto-assignment of users](https://configcat.com/docs/advanced/team-management/auto-assign-users.md).
---
# Source: https://configcat.com/docs/advanced/team-management/auto-assign-users.md
# Auto-assign Users
Copy page
All new users who sign up with a [verified email domain](https://configcat.com/docs/advanced/team-management/domain-verification.md) will be automatically added to your organization. Furthermore, you can also set which Organization roles / Product permissions they should get upon on-boarding.
## Steps to configure[](#steps-to-configure "Direct link to Steps to configure")
* Open your organization's authentication settings on the [ConfigCat Dashboard](https://app.configcat.com/organization/authentication).

* Select the domain you want to configure, and click `RE-CONFIGURE` (or just `CONFIGURE` if you haven't configured it yet) under the `Auto-assign status`.

* In the dialog that appears, you can select which `Organization roles` and `Product permissions` should be assigned to the newly registered users.

* When you are ready, just hit `Save`.
---
# Source: https://configcat.com/docs/advanced/team-management/saml/identity-providers/azure-ad.md
# Entra ID (Azure AD) Identity Provider
Copy page
Connect ConfigCat with Entra ID via SAML.
## Introduction[](#introduction "Direct link to Introduction")
Each SSO Identity Provider requires specific information to configure a SAML integration. The following guide will walk you through how you can connect ConfigCat with Entra ID as a SAML Identity Provider.
## 1. Create an Entra ID Enterprise Application[](#1-create-an-entra-id-enterprise-application "Direct link to 1. Create an Entra ID Enterprise Application")
* Log in to the [Azure Portal](https://portal.azure.com/), go to the `Entra ID` resource, and select `Enterprise applications`.

* Click on `New application`.

* Click on `Create your own application`.

* Enter a descriptive `App name`, select the `Integrate any other application you don't find in the gallery (Non-gallery)` option, then click `Create`.

* On the `Manage` section of the application, select `Single sign-on`, then select `SAML`.

The next step will guide you on how to collect the information required for Configuring SAML in the application.
## 2. Configure SAML for the Azure Enterprise Application[](#2-configure-saml-for-the-azure-enterprise-application "Direct link to 2. Configure SAML for the Azure Enterprise Application")
* Open your organization's authentication settings on the [ConfigCat Dashboard](https://app.configcat.com/organization/authentication).

* Click `ADD SAML IDENTITY PROVIDER`.

* Give a name for your Identity Provider, and click `Create`.

* From the next section of the dialog, copy the following values and paste them into the Enterprise application.
* `Entity ID` -> `Identifier (Entity ID)`
* `Assertion Consumer Service` -> `Reply URL (Assertion Consumer Service URL)`
  
## 3. Configure ConfigCat with SAML Details from Azure[](#3-configure-configcat-with-saml-details-from-azure "Direct link to 3. Configure ConfigCat with SAML Details from Azure")
You can choose one of the following options to configure ConfigCat with SAML Identity Provider metadata.
* Metadata URL
* Manual Configuration
- Copy the value of `App Federation Metadata Url`.

- Paste the copied value into the `Metadata URL` field at ConfigCat.

- Select the **trusted domains**. Only user accounts from trusted domains can login with SAML SSO. You can bind multiple verified domains to a SAML Identity Provider.

- Click on `Save`.
* Copy the value of `Login URL` and download the `Certificate (Base64)`, then paste them into the Configuration dialog at ConfigCat.

* Select the **trusted domains**. Only user accounts from trusted domains can login with SAML SSO. You can bind multiple verified domains to a SAML Identity Provider.

* Click on `Save`.
## 4. Assign Users to the Enterprise Application[](#4-assign-users-to-the-enterprise-application "Direct link to 4. Assign Users to the Enterprise Application")
To let users authenticate via SAML, you need to assign individual users or groups to the Enterprise application.
* Select `Users and groups` on the `Manage` section of the menu.

* Click `Add user/group`, then select the users or groups you want to assign.

## 5. Sign In[](#5-sign-in "Direct link to 5. Sign In")
* Go to the [ConfigCat Log In](https://app.configcat.com) page, and click `COMPANY ACCOUNT - SAML`.

* Sign in with your company email address assigned to the Enterprise application.

* ConfigCat will redirect you to Microsoft's sign in page. Type your credentials for sign-in.

* You should be redirected to ConfigCat signed in with your company account.
## 6. Next Steps[](#6-next-steps "Direct link to 6. Next Steps")
* Configure [User provisioning (SCIM)](https://configcat.com/docs/advanced/team-management/scim/scim-overview.md)
* or configure the [auto-assignment of users](https://configcat.com/docs/advanced/team-management/auto-assign-users.md) if you don't want to provision your users with your Identity Provider.
---
# Source: https://configcat.com/docs/advanced/code-references/azure-devops.md
# Azure DevOps - Scan your source code for feature flags
Copy page
This section describes how to use the [ConfigCat CLI](https://configcat.com/docs/advanced/cli.md) in [Azure DevOps Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in Azure DevOps [Pipeline Variables](https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new or open your existing `azure-pipelines.yml` file, and add the following [job](https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema#job) to your `jobs` definition. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- job: configcat_scan_and_upload
container: configcat/cli:azure-devops-2.4.2
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
persistCredentials: true
- script: configcat scan $(Build.Repository.LocalPath)
--config-id=PASTE-YOUR-CONFIG-ID-HERE
--repo=$(Build.Repository.Name)
--branch=$(Build.SourceBranchName)
--file-url-template="$(Build.Repository.Uri)?path={filePath}&version=GC{commitHash}&line={lineNumber}&lineStartColumn=1&lineEndColumn=1"
--commit-url-template="$(Build.Repository.Uri)/commit/{commitHash}"
--runner="ConfigCat Azure DevOps Job"
--upload
--non-interactive
name: scan_repository
env:
CONFIGCAT_API_PASS: $(CONFIGCAT_API_PASS)
CONFIGCAT_API_USER: $(CONFIGCAT_API_USER)
```
info
If you are using a different VCS than Azure DevOps' Git, you should set the `--file-url-template` and `--commit-url-template` according to your VCS provider.
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
---
# Source: https://configcat.com/docs/glossary/beta-testing.md
# Beta Testing - Navigating the Road to Market Readiness
Copy page
## Introduction[](#introduction "Direct link to Introduction")
Beta testing stands as a critical milestone before a software product meets its audience. This phase is the trial test, bridging the gap between internal development and user experience. Let's explore the role of beta testing in software development and its significance in refining software products.
## What is Beta Testing in Software Development?[](#what-is-beta-testing-in-software-development "Direct link to What is Beta Testing in Software Development?")
Beta testing in software development involves releasing a near-complete version of the software to a selected group of external users. This phase follows alpha testing and is crucial for gathering feedback under real usage conditions to fine-tune the software before its official release.
## The Objectives of Beta Testing in Software Development[](#the-objectives-of-beta-testing-in-software-development "Direct link to The Objectives of Beta Testing in Software Development")
* **Gathering User Feedback**: Collecting insights about user experiences and preferences.
* **Assessing Market Response**: Evaluating how the software is perceived and received in the market.
* **Identifying Real-World Bugs**: Detecting issues that might have been missed during internal testing.
* **Refinement for Market Launch**: Adjusting and improving the software based on user feedback.
## The Beta Testing Process in Software Development[](#the-beta-testing-process-in-software-development "Direct link to The Beta Testing Process in Software Development")
* **Selection of Beta Testers**: Recruiting a diverse and representative sample of the target user base.
* **Distribution of Beta Version**: Providing the beta software to the chosen testers.
* **Monitoring and Feedback Collection**: Observing user interactions and gathering structured feedback.
* **Analysis and Iteration**: Analyzing user feedback to identify areas for improvement and implementing changes.
* **Release Readiness Assessment**: Evaluating if the software is ready for public launch based on tester feedback.
## Why Beta Testing is Crucial in Software Development[](#why-beta-testing-is-crucial-in-software-development "Direct link to Why Beta Testing is Crucial in Software Development")
* **Insights from Real Users**: Obtaining feedback from actual users in varied real-world scenarios.
* **Market Acceptance Evaluation**: Gauging the market's reaction and the software's readiness for launch.
* **Enhancement of Software Quality**: Identifying and fixing bugs, and polishing features to improve overall quality.
* **Building Early User Base**: Establishing an initial user community and fostering early adopter loyalty.
## Challenges in Beta Testing for Software and Solutions[](#challenges-in-beta-testing-for-software-and-solutions "Direct link to Challenges in Beta Testing for Software and Solutions")
* **Diverse User Scenarios**: Testers may have different usage patterns and environments. Solution: Carefully select a diverse group of beta testers.
* **Handling Feedback Effectively**: Managing a large volume of feedback can be challenging. Solution: Implement structured feedback collection tools and clear guidelines.
* **Maintaining Tester Engagement**: Keeping beta testers motivated and engaged throughout the process. Solution: Provide incentives for participation and maintain open, responsive communication channels.
## Conclusion[](#conclusion "Direct link to Conclusion")
Beta testing in software development is more than just a phase; it's a strategic approach to ensuring that the software not only functions but also resonates with its intended audience. It’s a vital step in the journey towards launching a software product that is not just functional, but also aligned with user expectations and market demands. Through beta testing, software developers can pave the way for a successful product launch, grounded in quality, user satisfaction, and market readiness.
---
# Source: https://configcat.com/docs/advanced/code-references/bitbucket-pipe.md
# Bitbucket Pipe - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [Bitbucket Pipe](https://bitbucket.org/product/features/pipelines/integrations?p=configcat/scan-repository-pipe) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about Bitbucket Pipelines [here](https://bitbucket.org/product/features/pipelines).
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in secure pipeline variables with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Add the following snippet to the script section of your `bitbucket-pipelines.yml` file. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- pipe: configcat/scan-repository-pipe:1.8.1
variables:
CONFIG_ID: 'PASTE-YOUR-CONFIG-ID-HERE'
# LINE_COUNT: '3' # optional
# TIMEOUT: '1800' # optional
# SUB_FOLDER: '/src' # optional
# EXCLUDE_KEYS: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# ALIAS_PATTERNS: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) # optional
# USAGE_PATTERNS: feature_flags\.enabled\(:CC_KEY\)
# VERBOSE: 'true' # optional
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
## Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `CONFIG_ID` | ID of the ConfigCat config to scan against. | ☑ | |
| `CONFIGCAT_API_HOST` | ConfigCat Management API host. | | `api.configcat.com` |
| `LINE_COUNT` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `TIMEOUT` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `SUB_FOLDER` | Sub-folder to scan, relative to the repository root folder. | | |
| `EXCLUDE_KEYS` | List of feature flag keys that must be excluded from the scan report. | | |
| `ALIAS_PATTERNS` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `USAGE_PATTERNS` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `VERBOSE` | Turns on detailed logging. | | false |
---
# Source: https://configcat.com/docs/integrations/bitbucket.md
# Bitbucket - Scan your code for feature flag usages
Copy page
ConfigCat's [Bitbucket Pipe](https://bitbucket.org/product/features/pipelines/integrations?p=configcat/scan-repository-pipe) has the ability to scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
This feature makes the elimination of the technical debt easier, as it can show which repositories reference your feature flags and settings in one centralized place on your [Dashboard](https://app.configcat.com).
[Here](https://configcat.com/docs/advanced/code-references/overview.md) you can find more details about how this feature works.
This section describes how to use ConfigCat's [Bitbucket Pipe](https://bitbucket.org/product/features/pipelines/integrations?p=configcat/scan-repository-pipe) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about Bitbucket Pipelines [here](https://bitbucket.org/product/features/pipelines).
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in secure pipeline variables with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Add the following snippet to the script section of your `bitbucket-pipelines.yml` file. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- pipe: configcat/scan-repository-pipe:1.8.1
variables:
CONFIG_ID: 'PASTE-YOUR-CONFIG-ID-HERE'
# LINE_COUNT: '3' # optional
# TIMEOUT: '1800' # optional
# SUB_FOLDER: '/src' # optional
# EXCLUDE_KEYS: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# ALIAS_PATTERNS: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) # optional
# USAGE_PATTERNS: feature_flags\.enabled\(:CC_KEY\)
# VERBOSE: 'true' # optional
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
## Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `CONFIG_ID` | ID of the ConfigCat config to scan against. | ☑ | |
| `CONFIGCAT_API_HOST` | ConfigCat Management API host. | | `api.configcat.com` |
| `LINE_COUNT` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `TIMEOUT` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `SUB_FOLDER` | Sub-folder to scan, relative to the repository root folder. | | |
| `EXCLUDE_KEYS` | List of feature flag keys that must be excluded from the scan report. | | |
| `ALIAS_PATTERNS` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `USAGE_PATTERNS` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `VERBOSE` | Turns on detailed logging. | | false |
---
# Source: https://configcat.com/docs/advanced/code-references/bitrise-step.md
# Bitrise - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [Bitrise Step](https://www.bitrise.io/integrations/steps/configcat-feature-flag-sync) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. [Bitrise](https://www.bitrise.io/) is full-featured mobile CI/CD platform. You can find more information about Bitrise Steps [here](https://devcenter.bitrise.io/en/steps-and-workflows/introduction-to-steps.html).
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in secure pipeline variables with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Add the following step to the workflows section of your `bitrise.yml` file. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- configcat-feature-flag-sync@0:
inputs:
- configcat_config_id: 'PASTE-YOUR-CONFIG-ID-HERE' # required
# - line-count: 3 # optional
# - sub-folder: 'src' # optional
# - exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# - alias-patterns: "(\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\)" # optional
# - usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional
# - verbose: true # optional
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
## Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `configcat_config_id` | The [config ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id) tells the step which feature flags it should search for in your source code. | ☑ | |
| `configcat_api_host` | ConfigCat Management API host. | | `api.configcat.com` |
| `line_count` | Code snippet line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `sub_folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
# Source: https://configcat.com/docs/integrations/bitrise.md
# Bitrise - Scan your code for feature flag usages
Copy page
ConfigCat's [Bitrise Step](https://www.bitrise.io/integrations/steps/configcat-feature-flag-sync) has the ability to scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
This feature makes the elimination of the technical debt easier, as it can show which repositories reference your feature flags and settings in one centralized place on your [Dashboard](https://app.configcat.com).
[Here](https://configcat.com/docs/advanced/code-references/overview.md) you can find more details about how this feature works.
This section describes how to use ConfigCat's [Bitrise Step](https://www.bitrise.io/integrations/steps/configcat-feature-flag-sync) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. [Bitrise](https://www.bitrise.io/) is full-featured mobile CI/CD platform. You can find more information about Bitrise Steps [here](https://devcenter.bitrise.io/en/steps-and-workflows/introduction-to-steps.html).
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in secure pipeline variables with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Add the following step to the workflows section of your `bitrise.yml` file. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
- configcat-feature-flag-sync@0:
inputs:
- configcat_config_id: 'PASTE-YOUR-CONFIG-ID-HERE' # required
# - line-count: 3 # optional
# - sub-folder: 'src' # optional
# - exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# - alias-patterns: "(\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\)" # optional
# - usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional
# - verbose: true # optional
```
4. Commit & push your changes.
Scan reports are uploaded for each branch of your repository that triggers the job.
## Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------- |
| `configcat_config_id` | The [config ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id) tells the step which feature flags it should search for in your source code. | ☑ | |
| `configcat_api_host` | ConfigCat Management API host. | | `api.configcat.com` |
| `line_count` | Code snippet line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `sub_folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
# Source: https://configcat.com/docs/glossary/blue-green-deployment.md
# Blue/Green Deployment - Streamlining Software Releases
Copy page
## Introduction[](#introduction "Direct link to Introduction")
In the dynamic realm of software development, deploying updates without disrupting user experience is paramount. Blue/Green Deployment emerges as a strategic method that enables this seamless transition. Let's delve into its mechanics and recognize its significance in software deployment.
## What is Blue/Green Deployment?[](#what-is-bluegreen-deployment "Direct link to What is Blue/Green Deployment?")
Blue/Green Deployment is a strategy used to reduce downtime and risk by running two identical production environments. Simply put, the 'Blue' environment is the active one, while the 'Green' is a clone, ready to be switched over at any moment. This approach allows for testing in the production environment itself without affecting users.
## Objectives of Blue/Green Deployment[](#objectives-of-bluegreen-deployment "Direct link to Objectives of Blue/Green Deployment")
* **Minimal Downtime**: Achieve nearly zero downtime during deployments.
* **Risk Reduction**: Mitigate risks associated with the release of new features or updates.
* **Rapid Rollback**: Provide the ability to quickly revert to the previous version if issues arise post-deployment.
* **Continuous Delivery**: Facilitate a smoother continuous delivery pipeline.
## The Blue/Green Deployment Process[](#the-bluegreen-deployment-process "Direct link to The Blue/Green Deployment Process")
* **Preparation**: Setting up two identical environments — Blue (current) and Green (new).
* **Testing**: Validating the Green environment to ensure it's ready for live traffic.
* **Routing Traffic**: Shifting user traffic from Blue to Green seamlessly.
* **Monitoring**: Keeping a close watch on the Green environment for any issues.
* **Finalization or Rollback**: If successful, decommission the Blue environment, or if problems are detected, revert traffic back to Blue.
## Why Blue/Green Deployment is Essential[](#why-bluegreen-deployment-is-essential "Direct link to Why Blue/Green Deployment is Essential")
* **Enhanced Reliability**: Increases the reliability of the deployment process.
* **User Experience**: Ensures uninterrupted service to users during updates.
* **Simplified Troubleshooting**: Allows easy identification and resolution of issues.
* **Flexibility**: Offers flexibility in managing and scheduling deployments.
## Challenges in Blue/Green Deployment and Solutions[](#challenges-in-bluegreen-deployment-and-solutions "Direct link to Challenges in Blue/Green Deployment and Solutions")
* **Resource Intensiveness**: Requires duplicating the production environment. Solution: Efficient resource management and cloud-based solutions.
* **Data Synchronization**: Keeping data in sync between Blue and Green environments. Solution: Robust data management strategies and tools.
* **Complex Configuration**: Managing complex configurations during the switch. Solution: Automation tools and thorough planning.
## Conclusion[](#conclusion "Direct link to Conclusion")
Blue/Green Deployment serves as a cornerstone for modern software delivery, ensuring that updates and new features are rolled out smoothly, without disturbing the end-user experience. By integrating this strategy into deployment practices, organizations can enhance the reliability and efficiency of their software delivery process, ultimately leading to greater user satisfaction and business success.
---
# Source: https://configcat.com/docs/sdk-reference/js/browser.md
# Browser (JavaScript) SDK
Copy page
[](https://github.com/configcat/js-unified-sdk/stargazers) [](https://github.com/configcat/js-unified-sdk/actions/workflows/js-sdk-ci.yml) [](https://sonarcloud.io/project/overview?id=configcat_js-unified-sdk) [](https://snyk.io/test/github/configcat/js-unified-sdk?targetFile=package.json) [](https://sonarcloud.io/dashboard?id=configcat_js-sdk) [](https://data.jsdelivr.com/v1/package/npm/@configcat/sdk/badge)
info
This SDK supersedes the legacy [JavaScript SDK](https://configcat.com/docs/sdk-reference/js.md) and [JavaScript (SSR) SDK](https://configcat.com/docs/sdk-reference/js-ssr.md).
It is suitable for the following types of browser applications:
* Static HTML websites
* Server-side rendered Multi-Page Applications (MPA), e.g. PHP, ASP.NET Core Razor Pages, Spring MVC, etc.
* Client-side rendered Single-Page Applications (SPA), e.g. Angular, React, Vue.js, etc.
* Server-side rendered Single-Page Applications (SSR), e.g. Angular SSR, Next.js, Nuxt, etc.
* Prerendered Single/Multi-Page Applications (SSG), e.g. Angular SSG, Vue.js SSG, Astro, etc.
* Web Workers
[ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Install and import package[](#1-install-and-import-package "Direct link to 1. Install and import package")
* via NPM
* via CDN
First install the [NPM package](https://npmjs.com/package/@configcat/sdk):
```bash
npm i @configcat/sdk
```
Then import it into your application:
```js
import * as configcat from "@configcat/sdk/browser";
```
info
**In SSR/SSG applications**, you can either import from `@configcat/sdk/node` or `@configcat/sdk/browser` depending on whether your code executes in a server or client context, or import from the uniform main entry point `@configcat/sdk` if your code needs to run in both contexts.
info
For subpath imports to work **in TypeScript**, you must set the [moduleResolution](https://www.typescriptlang.org/tsconfig/#moduleResolution) option to `node16`, `nodenext` or `bundler` in your `tsconfig.json`. For TypeScript versions older than 4.7, where these options are not available, you need to fall back to module resolution `node` and importing from the main entry point `@configcat/sdk`.
info
Please note that subpath imports require your bundler to support the [exports](https://nodejs.org/api/packages.html#exports) package.json field, introduced in Node.js v12.7. **In the unlikely case of bundler compatibility issues**, you can fall back to importing from the main entry point `@configcat/sdk` as long as your bundler recognizes the [browser](https://github.com/defunctzombie/package-browser-field-spec) package.json field.
Import the package directly from a CDN server into your application:
```html
```
or
```html
```
### 2. Create the *ConfigCat* client with your SDK Key[](#2-create-the-configcat-client-with-your-sdk-key "Direct link to 2-create-the-configcat-client-with-your-sdk-key")
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
```
### 3. Get your setting value[](#3-get-your-setting-value "Direct link to 3. Get your setting value")
The async/await way:
```js
const value = await configCatClient.getValueAsync(
'isMyAwesomeFeatureEnabled',
false,
);
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
```
info
Please note that [top-level await in modules](https://exploringjs.com/js/book/ch_modules.html#top-level-await) may not be available [in older browsers](https://caniuse.com/mdn-javascript_operators_await_top_level). If you need to target such browser versions, you will need to use Promises, wrap your code in an async function or configure your build tools to downlevel this language feature.
The Promise way:
```js
configCatClient
.getValueAsync('isMyAwesomeFeatureEnabled', false)
.then((value) => {
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
});
```
The *ConfigCat SDK* also offers a synchronous API for feature flag evaluation. Read more [here](#snapshots-and-synchronous-feature-flag-evaluation).
### 4. Dispose the *ConfigCat* client[](#4-dispose-the-configcat-client "Direct link to 4-dispose-the-configcat-client")
You can safely dispose all clients at once or individually and release all associated resources on application exit.
```js
configcat.disposeAllClients(); // disposes all clients
// -or-
configCatClient.dispose(); // disposes a specific client
```
## Demo on CodePen[](#demo-on-codepen "Direct link to Demo on CodePen")
See the Pen [ConfigCat Feature Flag Demo](https://codepen.io/configcat/pen/myemzYW) on [CodePen](https://codepen.io).
## Creating the *ConfigCat* Client[](#creating-the-configcat-client "Direct link to creating-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`configcat.getClient('')` returns a client with default options.
The `getClient` function has optional parameters, which can be used to adjust the behavior of the client.
| Parameters | Description | Default |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
| `sdkKey` | **REQUIRED.** SDK Key to access your feature flags and settings. Get it from *ConfigCat Dashboard*. | - |
| `pollingMode` | Optional. The polling mode to use to fetch the config data from the ConfigCat CDN. [More about polling modes](#polling-modes). | `PollingMode.AutoPoll` |
| `options` | Optional. The options object. See the table below. | - |
The available options depends on the chosen polling mode. However, there are some common options which can be set in the case of every polling mode:
| Option Parameter | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `configFetcher` | Custom [`IConfigCatConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigFetcher.ts) instance for downloading a config. | [`XmlHttpRequestConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/browser/XmlHttpRequestConfigFetcher.ts) |
| `cache` | Custom [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) implementation for caching the downloaded config. | [`LocalStorageConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/browser/LocalStorageConfigCache.ts) or e [`IndexedDBConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/shared/IndexedDBConfigCache.ts) |
| `logger` | Custom [`IConfigCatLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) implementation for tracing. | [`ConfigCatConsoleLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) (with WARN level) |
| `logFilter` | Sets a custom log filter. [More about log filtering](#log-filtering). | `undefined` (none) |
| `baseUrl` | Sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. | |
| `requestTimeoutMs` | The amount of milliseconds the SDK waits for a response from the ConfigCat servers before returning values from the cache. | 30000 |
| `flagOverrides` | Local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). | |
| `dataGovernance` | Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `DataGovernance.Global`, `DataGovernance.EuOnly`. | `DataGovernance.Global` |
| `defaultUser` | Sets the default user. [More about default user](#default-user). | `undefined` (none) |
| `offline` | Determines whether the client should be initialized to offline mode. [More about offline mode](#online--offline-mode). | `false` |
Options also include a property named `setupHook`, which you can use to subscribe to the hooks (events) at the time of initialization. [More about hooks](#hooks).
For example:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
setupHooks: (hooks) => hooks.on('clientReady', function() {
const keys = this.configCatClient.snapshot().getAllKeys();
console.log(`Client is ready! Number of available feature flags: ${keys.length}`);
}),
},
);
```
info
You can acquire singleton client instances for your SDK keys using the `configcat.getClient(sdkKey: "")` factory function. (However, please keep in mind that subsequent calls to `getClient()` with the *same SDK Key* return a *shared* client instance, which was set up by the first call.)
You can close all open clients at once using the `configcat.disposeAllClients()` function or do it individually using the `configCatClient.dispose()` method.
## Anatomy of `getValueAsync()`[](#anatomy-of-getvalueasync "Direct link to anatomy-of-getvalueasync")
Returns a Promise with the value.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((value) => {
console.log(value);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | `typeof defaultValue` |
| -------------- | --------------------- |
| On/Off Toggle | `boolean` |
| Text | `string` |
| Whole Number | `number` |
| Decimal Number | `number` |
In addition to the types mentioned above, you also have the option to provide `null` or `undefined` for the `defaultValue` parameter regardless of the setting kind. However, if you do so, the return type of the `getValue` method will be
* `boolean | string | number | null` when `defaultValue` is `null` or
* `boolean | string | number | undefined` when `defaultValue` is `undefined`.
This is because in these cases the exact return type cannot be determined at compile-time as the TypeScript compiler has no information about the setting type.
It's important to note that providing any other type for the `defaultValue` parameter will result in a `TypeError`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
## Anatomy of `getValueDetailsAsync()`[](#anatomy-of-getvaluedetailsasync "Direct link to anatomy-of-getvaluedetailsasync")
`getValueDetailsAsync()` is similar to `getValueAsync()` but instead of returning the evaluated value only, it provides more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const details = await configCatClient.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((details) => {
console.log(details);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `key` | `string` | The key of the evaluated feature flag or setting. |
| `value` | `boolean` / `string` / `number` | The evaluated value of the feature flag or setting. |
| `user` | `User` | The User Object used for the evaluation. |
| `isDefaultValue` | `boolean` | True when the default value passed to `getValueDetailsAsync()` is returned due to an error. |
| `errorCode` | `EvaluationErrorCode` | In case of an error, this property contains a code that identifies the reason for the error. |
| `errorMessage` | `string` | In case of an error, this property contains the error message. |
| `errorException` | `any` | In case of an error, this property contains the related exception object (if any). |
| `matchedTargetingRule` | `TargetingRule` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matchedPercentageOption` | `PercentageOption` | The Percentage Option (if any) that was used to select the evaluated value. |
| `fetchTime` | `Date` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
For simple targeting:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
```
```js
const userObject = { identifier: 'john@example.com' };
```
| Parameters | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any `string` value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
For advanced targeting:
```js
const userObject = {
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
SubscriptionType: 'Pro',
UserRole: 'Admin',
},
};
```
The `custom` dictionary also allows attribute values other than `string` values:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
userObject.custom = {
Rating: 4.5,
RegisteredAt: new Date('2023-11-22T12:34:56.000Z'),
Roles: ['Role1', 'Role2'],
};
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `string` values,
* all other values are automatically converted to `string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `number` values,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `Date` values, which are automatically converted to a second-based Unix timestamp,
* accept `number` values representing a second-based Unix timestamp,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept arrays of `string`,
* accept `string` values containing a valid JSON string which can be deserialized to an array of `string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
It's possible to set a default User Object that will be used on feature flag and setting evaluation. It can be useful when your application has a single user only or rarely switches users.
You can set the default User Object either on SDK initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
defaultUser: { identifier: 'john@example.com' },
},
);
```
...or using the `setDefaultUser()` method of the `configCatClient` object:
```js
configCatClient.setDefaultUser({ identifier: 'john@example.com' });
```
Whenever the evaluation methods like `getValueAsync()`, `getValueDetailsAsync()`, etc. are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
// The default user will be used in the evaluation process.
const value = await configCatClient.getValueAsync('keyOfMyFeatureFlag', false);
```
When a `user` parameter is passed to the evaluation methods, it takes precedence over the default user.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
const otherUser = { identifier: 'brian@example.com' };
// otherUser will be used in the evaluation process.
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag',
false,
otherUser,
);
```
You can also remove the default user by doing the following:
```js
configCatClient.clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValueAsync()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle. [More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `pollIntervalSeconds` option parameter to change the polling interval.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
pollIntervalSeconds: 95,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------------------------------------------------------------------------------------- | ------- |
| `pollIntervalSeconds` | Polling interval in seconds. | 60s |
| `maxInitWaitTimeSeconds` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5s |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `getValueAsync()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValueAsync()` will return the setting value after the cache is updated.
Use `cacheTimeToLiveSeconds` option parameter to set cache lifetime.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.LazyLoad,
{
cacheTimeToLiveSeconds: 600,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------- | ------- |
| `cacheTimeToLiveSeconds` | Cache TTL in seconds. | 60s |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefreshAsync()` is your application's responsibility.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
await configCatClient.forceRefreshAsync();
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
> `getValueAsync()` returns `defaultValue` if the cache is empty. Call `forceRefreshAsync()` to update the cache.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value); // console: "my default value"
await configCatClient.forceRefreshAsync();
value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `clientReady: [cacheState: ClientCacheState]`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after the initial sync with the external cache (if any) completes.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTimeSeconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the `cacheState` argument.
* `configFetched: [result: RefreshResult, isInitiatedByUser: boolean]`: This event is emitted each time the client attempts to refresh the cached config by fetching the latest version from the ConfigCat CDN. It is emitted not only when `ForceRefreshAsync` is called but also when the refresh is initiated by the client automatically. Thus, this event allows you to observe potential network issues that occur under the hood.
* `configChanged: [newConfig: IConfig]`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `flagEvaluated: [evaluationDetails: IEvaluationDetails]`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetailsAsync()`](#anatomy-of-getvaluedetailsasync).
* `clientError: [message: string, exception?: any]`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', function() {
/* handle the event */
}),
},
);
```
...or directly on the `ConfigCatClient` instance:
```js
configCatClient.on('flagEvaluated', function() {
/* handle the event */
});
```
caution
Some events (e.g. `clientReady`, `configChanged` and `clientError`) may be emitted before `getClient` returns. This means you may miss them unless you subscribe on initialization.
However, even if you do, there's another gotcha: it's not safe to use the outer `configCatClient` variable in your event handler because it may not yet be assigned when the handler is called. Instead, you can safely access the client instance via `this.configCatClient` - provided that the event handler is a normal function, not an arrow function.
## Snapshots and synchronous feature flag evaluation[](#snapshots-and-synchronous-feature-flag-evaluation "Direct link to Snapshots and synchronous feature flag evaluation")
On JavaScript platforms, the *ConfigCat* client provides only asynchronous methods for evaluating feature flags and settings because these operations may involve network communication (e.g. downloading config data from the ConfigCat CDN servers), which is necessarily an asynchronous operation in JavaScript.
However, there can be circumstances where synchronous evaluation is preferable, thus, since v8.1.0, the JavaScript SDK provides a way to synchronously evaluate feature flags and settings via *snapshots*.
Using the `snapshot()` method, you can capture the current state of the *ConfigCat* client (including the latest downloaded config data) and use the resulting snapshot object to synchronously evaluate feature flags and settings based on the captured state:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
);
// Wait for the client to initialize.
await configCatClient.waitForReady();
const snapshot = configCatClient.snapshot();
const user = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
for (const key of snapshot.getAllKeys()) {
const value = snapshot.getValue(key, null, user);
console.log(`${key}: ${value}`);
}
```
Creating a snapshot is a cheap operation. This is possible because snapshots capture the client's internal (in-memory) cache. No attempt is made to refresh the internal cache, even if it's empty or expired.
caution
Please note that creating and using a snapshot
* won't trigger a sync with the external cache when working with [shared caching](https://configcat.com/docs/advanced/caching.md#shared-cache),
* won't fetch the latest config data from the ConfigCat CDN when the internally cached config data is empty or expired.
For the above reasons, it's recommended to use snapshots in conjunction with the Auto Polling mode, where the SDK automatically updates the internal cache in the background. (For other polling modes, you'll need to manually initiate a cache refresh by calling `forceRefreshAsync`.)
Because of this behavior, it's important to make sure that the client has completed initialization and populated its internal cache before creating snapshots. Otherwise the snapshot's evaluation methods won't have the data to do actual evaluation, but will just return the default value you pass to them. Which behavior is usually not what you want in your application.
In Auto Polling mode, you can use the `waitForReady` method to wait for the latest config data to become available locally. This is an asynchronous operation, which completes as soon as the client reaches the ready state, i.e. completes initialization (or the time specified via the `maxInitWaitTimeSeconds` option passes).
(Please note that this doesn't apply to other polling modes. In those cases, the client doesn't contact the ConfigCat CDN during initialization, so the ready state is reached as soon as the first sync with the external cache completes.)
Typically, you call `waitForReady` and wait for its completion only once, in the initialization phase of your application.
caution
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the return value.
```js
const clientCacheState = await configCatClient.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
// Handle initialization failure (see below).
console.warn('ConfigCat client failed to obtain the config data during initialization.');
}
```
You have the following options to handle unsuccessful initialization:
* If it's acceptable for your application to start up and use the default values passed to the evaluation methods, you may log some warning (or skip the check altogether as the client will log warnings anyway), and let the application continue.
* Otherwise, you need to either terminate the application or continue waiting. The latter is an option because the client might be able to obtain the config data later, in the case of a transient problem like some temporary network issue. However, the *ConfigCat SDK* doesn't provide out-of-the-box support for this case currently. You can implement this logic by subscribing to the `configChanged` hook and waiting for the first event.
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases where you want to prevent the SDK from making HTTP calls, you can switch it to offline mode:
```js
configCatClient.setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To switch the SDK back to online mode, do the following:
```js
configCatClient.setOnline();
```
Using the `configCatClient.isOffline` property you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a `{ [key: string]: boolean | string | number }` object, from the current query string or from a custom flag override data source.
### Map[](#map "Direct link to Map")
You can specify simple feature flag & setting overrides using a `{ [key: string]: boolean | string | number }` map.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: configcat.createFlagOverridesFromMap(
{
enabledFeature: true,
disabledFeature: false,
intSetting: 5,
doubleSetting: 3.14,
stringSetting: 'test',
},
configcat.OverrideBehaviour.LocalOnly,
),
},
);
```
### Query string[](#query-string "Direct link to Query string")
It is also possible to override feature flags & settings using query string parameters.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: createFlagOverridesFromQueryParams(configcat.OverrideBehaviour.LocalOverRemote),
},
);
```
With that setup, you can override feature flags and settings by appending query string parameters to the URL of your application in the following form: `https://app.example.com/?cc-myBooleanFlag=true&cc-myStringSetting=abc&...`
The setting type is automatically inferred from the value. Please pay attention to this behavior. The inferred type of the value must match the type of the feature flag or setting you override (see also [this table](#setting-type-mapping)). In case you want to force a boolean or number value to be interpreted as a string value, use the `;str` suffix: `&cc-myStringSetting;str=true`.
If the default prefix used to differentiate between normal and flag override query string parameters (`cc-`) is not suitable for you, you can set a custom prefix using the corresponding optional parameter of `createFlagOverridesFromQueryParams`.
### Custom data source implementation[](#custom-data-source-implementation "Direct link to Custom data source implementation")
You can create a custom flag override data source by implementing `IOverrideDataSource`.
The SDK provides the `createSettingFromValue` function to create `Setting` objects from simple `boolean`, `string` and `number` values. In case you need complex (full-featured) flag overrides, you can use the `deserializeConfig` function to obtain `Setting` objects from a config JSON conforming to the [config JSON v6 format](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
```ts
class MyCustomOverrideDataSource implements IOverrideDataSource {
private settings: Record;
constructor(configJson: string) {
this.settings = deserializeConfig(configJson).f ?? {};
}
getOverrides(): Record {
return this.settings;
}
}
```
or
```js
function MyCustomOverrideDataSource(configJson) {
this.settings = deserializeConfig(configJson).f ?? {};
}
MyCustomOverrideDataSource.prototype.getOverrides = function () {
return this.settings;
};
```
then
```js
// Set the `MyCustomOverrideDataSource` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: {
dataSource: new MyCustomOverrideDataSource('{ "f": { ... } }'),
behaviour: configcat.OverrideBehaviour.LocalOnly,
}
},
);
```
## Logging[](#logging "Direct link to Logging")
### Setting log levels[](#setting-log-levels "Direct link to Setting log levels")
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: configcat.createConsoleLogger(configcat.LogLevel.Info), // Setting log level to Info
},
);
```
Available log levels:
| Level | Description |
| ----- | ------------------------------------------------------- |
| Off | Nothing gets logged. |
| Error | Only error level events are logged. |
| Warn | Default. Errors and Warnings are logged. |
| Info | Errors, Warnings and feature flag evaluation is logged. |
| Debug | All of the above plus debug info is logged. |
Info level logging helps to inspect the feature flag evaluation process:
```bash
ConfigCat - INFO - [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"#SOME-USER-ID#","Email":"configcat@example.com"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
The SDK provides a simple logger implementation that logs to [the debugging console](https://developer.mozilla.org/en-US/docs/Web/API/console) (`configcat.createConsoleLogger(...)`) but it also allows you to inject any custom implementation of `IConfigCatLogger`.
```ts
class MyCustomLogger implements IConfigCatLogger {
/**
* Writes an event into the log.
* @param level Event severity level.
* @param eventId Event identifier.
* @param message Message.
* @param exception The exception object related to the message (if any).
*/
log(
level: LogLevel,
eventId: LogEventId,
message: LogMessage,
exception?: any,
): void {
// insert your custom log logic
}
}
```
or
```js
function MyCustomLogger() {}
MyCustomLogger.prototype.log = function (level, eventId, message, exception) {
// insert your custom log logic
};
```
then
```js
// Set the `MyCustomLogger` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: new MyCustomLogger(),
},
);
```
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by providing a callback function via the `logFilter` option. The callback will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `IConfigCatLogger.level` property). That is, the callback allows you to filter log events by `level`, `eventId`, `message` or `exception`. The formatted message string can be obtained via `message.toString()`. If the callback function returns `true`, the event will be logged, otherwise it will be skipped.
```js
// Filter out events with id 1001 from the log.
const logFilter = (level, eventId, message, exception) => eventId != 1001;
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{
logFilter: logFilter
}
);
```
caution
Please make sure that your log filter logic doesn't perform heavy computation. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## `getAllKeysAsync()`[](#getallkeysasync "Direct link to getallkeysasync")
You can get the keys for all available feature flags and settings by calling the `getAllKeysAsync()` method.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
const keys = await configCatClient.getAllKeysAsync();
console.log(keys);
```
## `getAllValuesAsync()`[](#getallvaluesasync "Direct link to getallvaluesasync")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValuesAsync();
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValuesAsync(userObject);
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
```
## `getAllValueDetailsAsync()`[](#getallvaluedetailsasync "Direct link to getallvaluedetailsasync")
Evaluates and returns the values along with evaluation details of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValueDetailsAsync();
settingValues.forEach((details) => console.log(details));
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValueDetailsAsync(userObject);
settingValues.forEach((details) => console.log(details));
```
## Using custom cache implementation[](#using-custom-cache-implementation "Direct link to Using custom cache implementation")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) interface and set the `cache` property in the options passed to `getClient`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
```ts
class MyCustomCache implements IConfigCatCache {
set(key: string, value: string): Promise | void {
// insert your cache write logic here
}
get(
key: string,
): Promise | string | null | undefined {
// insert your cache read logic here
}
}
```
or
```js
function MyCustomCache() {}
MyCustomCache.prototype.set = function (key, value) {
// insert your cache write logic here
};
MyCustomCache.prototype.get = function (key) {
// insert your cache read logic here
};
```
then
```js
// Set the `MyCustomCache` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
cache: new MyCustomCache(),
},
);
```
info
The JavaScript SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the *ConfigCat SDK* that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Platform compatibility[](#platform-compatibility "Direct link to Platform compatibility")
The SDK should be compatible with all modern, widely used browsers and bundlers.
The SDK is [tested](https://github.com/configcat/js-unified-sdk/blob/master/.github/workflows/js-sdk-ci.yml) against the following browsers:
* Chrome (stable, latest, beta)
* Chromium (71.0.3556.0, 72.0.3626.0, 80.0.3987.0)
* Firefox (84.0, latest, latest-beta)
* Safari (latest)
The SDK is compatible with TypeScript v4.0.2 or newer. Earlier versions may work but those are not tested, thus, not supported officially.
These tests are running on each pull request, before each deploy, and on a daily basis.
You can view a sample run [here](https://github.com/configcat/js-unified-sdk/actions/runs/11745259578).
## Best practices[](#best-practices "Direct link to Best practices")
### Choosing polling mode for serverless functions[](#choosing-polling-mode-for-serverless-functions "Direct link to Choosing polling mode for serverless functions")
In most cases, Auto polling is a good choice, but it's not ideal for short-lived serverless functions like AWS Lambdas, Azure Functions, Cloudflare Workers, etc.
For example, if the SDK is running in a Next.js application that is hosted on Vercel (AWS Lambda), or your application is hosted directly in AWS Lambdas, it is recommended to use the SDK in Lazy loading or Manual polling mode instead of the default Auto polling mode.
As AWS Lambdas try to minimize their uptime, the applications are terminated as soon as the sytem detects inactivity in the application.
Auto polling mode is implemented using an asynchronous background loop to periodically get the config data from the ConfigCat servers, however the AWS Lambda doesn't detect it as a running application and terminates it.
So it can easily happen that there is an ongoing HTTP GET request towards our servers and this termination can cause errors. The most likely error message in this case is `Request timed out while trying to fetch config JSON.`
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
* [Plain HTML + JS](https://github.com/configcat/js-unified-sdk/tree/master/samples/html)
* [Plain HTML + JS using ECMAScript module system](https://github.com/configcat/js-unified-sdk/tree/master/samples/html-esm)
* [Plain HTML + TS running the SDK in a Web Worker](https://github.com/configcat/js-unified-sdk/tree/master/samples/web-worker)
* [Sample Angular web application](https://github.com/configcat/js-unified-sdk/tree/master/samples/angular-sample)
* [Sample React web application](https://github.com/configcat/js-unified-sdk/tree/master/samples/react-sample)
* [Sample React Native application](https://github.com/configcat/js-unified-sdk/tree/master/samples/react-native-sample)
* [Sample Vue SSR web application](https://github.com/configcat/js-unified-sdk/tree/master/samples/vue-ssr-sample)
## Guides[](#guides "Direct link to Guides")
See the guides on how to use ConfigCat's JavaScript SDK with the following libraries and frameworks:
info
Some of these guides may use legacy SDKs. However, the parts beyond NPM package installation and import should still work with modern SDKs.
Client-side frontend frameworks:
* [Angular](https://configcat.com/blog/2022/08/09/using-feature-flags-in-angular/)
* [React](https://configcat.com/blog/2021/12/13/feature-flags-in-react/)
* [Vue.js](https://configcat.com/blog/2022/01/28/how-to-use-feature-flag-in-vuejs/)
* [Ionic](https://configcat.com/blog/2022/07/29/how-to-use-feature-flags-in-ionic-js/)
* [Phaser](https://configcat.com/blog/2022/02/04/feature-flags-in-phaser/)
* [Solid.js](https://configcat.com/blog/2022/11/11/how-to-use-feature-flags-in-solidjs/)
* [melonJS](https://configcat.com/blog/2022/02/19/feature-flags-in-melonjs/)
SSR frontend frameworks:
* [Nuxt](https://configcat.com/blog/2022/07/01/how-to-use-feature-flags-in-nuxtjs/)
* [Next.js](https://configcat.com/blog/2022/04/22/how-to-use-feature-flags-in-nextjs/)
* [Remix](https://configcat.com/blog/2022/04/01/feature-flags-in-remix/)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
* [ConfigCat SDK for JavaScript in NPM](https://www.npmjs.com/package/@configcat/sdk)
---
# Source: https://configcat.com/docs/sdk-reference/js/bun.md
# Bun SDK
Copy page
[](https://github.com/configcat/js-unified-sdk/stargazers) [](https://github.com/configcat/js-unified-sdk/actions/workflows/js-sdk-ci.yml) [](https://sonarcloud.io/project/overview?id=configcat_js-unified-sdk) [](https://snyk.io/test/github/configcat/js-unified-sdk?targetFile=package.json) [](https://sonarcloud.io/dashboard?id=configcat_js-sdk) [](https://data.jsdelivr.com/v1/package/npm/@configcat/sdk/badge)
[ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Install and import package[](#1-install-and-import-package "Direct link to 1. Install and import package")
First install the [NPM package](https://npmjs.com/package/@configcat/sdk):
```bash
npm i @configcat/sdk
```
Then import it into your application:
```js
import * as configcat from "@configcat/sdk/bun";
```
### 2. Create the *ConfigCat* client with your SDK Key[](#2-create-the-configcat-client-with-your-sdk-key "Direct link to 2-create-the-configcat-client-with-your-sdk-key")
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
```
### 3. Get your setting value[](#3-get-your-setting-value "Direct link to 3. Get your setting value")
The async/await way:
```js
const value = await configCatClient.getValueAsync(
'isMyAwesomeFeatureEnabled',
false,
);
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
```
The Promise way:
```js
configCatClient
.getValueAsync('isMyAwesomeFeatureEnabled', false)
.then((value) => {
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
});
```
The *ConfigCat SDK* also offers a synchronous API for feature flag evaluation. Read more [here](#snapshots-and-synchronous-feature-flag-evaluation).
### 4. Dispose the *ConfigCat* client[](#4-dispose-the-configcat-client "Direct link to 4-dispose-the-configcat-client")
You can safely dispose all clients at once or individually and release all associated resources on application exit.
```js
configcat.disposeAllClients(); // disposes all clients
// -or-
configCatClient.dispose(); // disposes a specific client
```
## Creating the *ConfigCat* Client[](#creating-the-configcat-client "Direct link to creating-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`configcat.getClient('')` returns a client with default options.
The `getClient` function has optional parameters, which can be used to adjust the behavior of the client.
| Parameters | Description | Default |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
| `sdkKey` | **REQUIRED.** SDK Key to access your feature flags and settings. Get it from *ConfigCat Dashboard*. | - |
| `pollingMode` | Optional. The polling mode to use to fetch the config data from the ConfigCat CDN. [More about polling modes](#polling-modes). | `PollingMode.AutoPoll` |
| `options` | Optional. The options object. See the table below. | - |
The available options depends on the chosen polling mode. However, there are some common options which can be set in the case of every polling mode:
| Option Parameter | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `configFetcher` | Custom [`IConfigCatConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigFetcher.ts) instance for downloading a config. | [`NodeHttpConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/node/NodeHttpConfigFetcher.ts) |
| `cache` | Custom [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) implementation for caching the downloaded config. | [`InMemoryConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) |
| `logger` | Custom [`IConfigCatLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) implementation for tracing. | [`ConfigCatConsoleLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) (with WARN level) |
| `logFilter` | Sets a custom log filter. [More about log filtering](#log-filtering). | `undefined` (none) |
| `baseUrl` | Sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. | |
| `httpAgent` | The [`http.Agent`](https://nodejs.org/api/http.html#class-httpagent) instance to use for non-secure HTTP communication. Can be used to route `http://...` requests made by the SDK through an HTTP, HTTPS or SOCKS proxy (see also [this section](#using-configcat-behind-a-proxy)). | |
| `httpsAgent` | The [`https.Agent`](https://nodejs.org/api/https.html#class-httpsagent) instance to use for secure HTTP communication. Can be used to route `https://...` requests made by the SDK through an HTTP, HTTPS or SOCKS proxy (see also [this section](#using-configcat-behind-a-proxy)). | |
| `requestTimeoutMs` | The amount of milliseconds the SDK waits for a response from the ConfigCat servers before returning values from the cache. | 30000 |
| `flagOverrides` | Local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). | |
| `dataGovernance` | Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `DataGovernance.Global`, `DataGovernance.EuOnly`. | `DataGovernance.Global` |
| `defaultUser` | Sets the default user. [More about default user](#default-user). | `undefined` (none) |
| `offline` | Determines whether the client should be initialized to offline mode. [More about offline mode](#online--offline-mode). | `false` |
Options also include a property named `setupHook`, which you can use to subscribe to the hooks (events) at the time of initialization. [More about hooks](#hooks).
For example:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
setupHooks: (hooks) => hooks.on('clientReady', function() {
const keys = this.configCatClient.snapshot().getAllKeys();
console.log(`Client is ready! Number of available feature flags: ${keys.length}`);
}),
},
);
```
info
You can acquire singleton client instances for your SDK keys using the `configcat.getClient(sdkKey: "")` factory function. (However, please keep in mind that subsequent calls to `getClient()` with the *same SDK Key* return a *shared* client instance, which was set up by the first call.)
You can close all open clients at once using the `configcat.disposeAllClients()` function or do it individually using the `configCatClient.dispose()` method.
## Anatomy of `getValueAsync()`[](#anatomy-of-getvalueasync "Direct link to anatomy-of-getvalueasync")
Returns a Promise with the value.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((value) => {
console.log(value);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | `typeof defaultValue` |
| -------------- | --------------------- |
| On/Off Toggle | `boolean` |
| Text | `string` |
| Whole Number | `number` |
| Decimal Number | `number` |
In addition to the types mentioned above, you also have the option to provide `null` or `undefined` for the `defaultValue` parameter regardless of the setting kind. However, if you do so, the return type of the `getValue` method will be
* `boolean | string | number | null` when `defaultValue` is `null` or
* `boolean | string | number | undefined` when `defaultValue` is `undefined`.
This is because in these cases the exact return type cannot be determined at compile-time as the TypeScript compiler has no information about the setting type.
It's important to note that providing any other type for the `defaultValue` parameter will result in a `TypeError`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
## Anatomy of `getValueDetailsAsync()`[](#anatomy-of-getvaluedetailsasync "Direct link to anatomy-of-getvaluedetailsasync")
`getValueDetailsAsync()` is similar to `getValueAsync()` but instead of returning the evaluated value only, it provides more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const details = await configCatClient.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((details) => {
console.log(details);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `key` | `string` | The key of the evaluated feature flag or setting. |
| `value` | `boolean` / `string` / `number` | The evaluated value of the feature flag or setting. |
| `user` | `User` | The User Object used for the evaluation. |
| `isDefaultValue` | `boolean` | True when the default value passed to `getValueDetailsAsync()` is returned due to an error. |
| `errorCode` | `EvaluationErrorCode` | In case of an error, this property contains a code that identifies the reason for the error. |
| `errorMessage` | `string` | In case of an error, this property contains the error message. |
| `errorException` | `any` | In case of an error, this property contains the related exception object (if any). |
| `matchedTargetingRule` | `TargetingRule` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matchedPercentageOption` | `PercentageOption` | The Percentage Option (if any) that was used to select the evaluated value. |
| `fetchTime` | `Date` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
For simple targeting:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
```
```js
const userObject = { identifier: 'john@example.com' };
```
| Parameters | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any `string` value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
For advanced targeting:
```js
const userObject = {
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
SubscriptionType: 'Pro',
UserRole: 'Admin',
},
};
```
The `custom` dictionary also allows attribute values other than `string` values:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
userObject.custom = {
Rating: 4.5,
RegisteredAt: new Date('2023-11-22T12:34:56.000Z'),
Roles: ['Role1', 'Role2'],
};
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `string` values,
* all other values are automatically converted to `string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `number` values,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `Date` values, which are automatically converted to a second-based Unix timestamp,
* accept `number` values representing a second-based Unix timestamp,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept arrays of `string`,
* accept `string` values containing a valid JSON string which can be deserialized to an array of `string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
It's possible to set a default User Object that will be used on feature flag and setting evaluation. It can be useful when your application has a single user only or rarely switches users.
You can set the default User Object either on SDK initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
defaultUser: { identifier: 'john@example.com' },
},
);
```
...or using the `setDefaultUser()` method of the `configCatClient` object:
```js
configCatClient.setDefaultUser({ identifier: 'john@example.com' });
```
Whenever the evaluation methods like `getValueAsync()`, `getValueDetailsAsync()`, etc. are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
// The default user will be used in the evaluation process.
const value = await configCatClient.getValueAsync('keyOfMyFeatureFlag', false);
```
When a `user` parameter is passed to the evaluation methods, it takes precedence over the default user.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
const otherUser = { identifier: 'brian@example.com' };
// otherUser will be used in the evaluation process.
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag',
false,
otherUser,
);
```
You can also remove the default user by doing the following:
```js
configCatClient.clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValueAsync()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle. [More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `pollIntervalSeconds` option parameter to change the polling interval.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
pollIntervalSeconds: 95,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------------------------------------------------------------------------------------- | ------- |
| `pollIntervalSeconds` | Polling interval in seconds. | 60s |
| `maxInitWaitTimeSeconds` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5s |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `getValueAsync()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValueAsync()` will return the setting value after the cache is updated.
Use `cacheTimeToLiveSeconds` option parameter to set cache lifetime.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.LazyLoad,
{
cacheTimeToLiveSeconds: 600,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------- | ------- |
| `cacheTimeToLiveSeconds` | Cache TTL in seconds. | 60s |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefreshAsync()` is your application's responsibility.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
await configCatClient.forceRefreshAsync();
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
> `getValueAsync()` returns `defaultValue` if the cache is empty. Call `forceRefreshAsync()` to update the cache.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value); // console: "my default value"
await configCatClient.forceRefreshAsync();
value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `clientReady: [cacheState: ClientCacheState]`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after the initial sync with the external cache (if any) completes.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTimeSeconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the `cacheState` argument.
* `configFetched: [result: RefreshResult, isInitiatedByUser: boolean]`: This event is emitted each time the client attempts to refresh the cached config by fetching the latest version from the ConfigCat CDN. It is emitted not only when `ForceRefreshAsync` is called but also when the refresh is initiated by the client automatically. Thus, this event allows you to observe potential network issues that occur under the hood.
* `configChanged: [newConfig: IConfig]`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `flagEvaluated: [evaluationDetails: IEvaluationDetails]`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetailsAsync()`](#anatomy-of-getvaluedetailsasync).
* `clientError: [message: string, exception?: any]`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', function() {
/* handle the event */
}),
},
);
```
...or directly on the `ConfigCatClient` instance:
```js
configCatClient.on('flagEvaluated', function() {
/* handle the event */
});
```
caution
Some events (e.g. `clientReady`, `configChanged` and `clientError`) may be emitted before `getClient` returns. This means you may miss them unless you subscribe on initialization.
However, even if you do, there's another gotcha: it's not safe to use the outer `configCatClient` variable in your event handler because it may not yet be assigned when the handler is called. Instead, you can safely access the client instance via `this.configCatClient` - provided that the event handler is a normal function, not an arrow function.
## Snapshots and synchronous feature flag evaluation[](#snapshots-and-synchronous-feature-flag-evaluation "Direct link to Snapshots and synchronous feature flag evaluation")
On JavaScript platforms, the *ConfigCat* client provides only asynchronous methods for evaluating feature flags and settings because these operations may involve network communication (e.g. downloading config data from the ConfigCat CDN servers), which is necessarily an asynchronous operation in JavaScript.
However, there can be circumstances where synchronous evaluation is preferable, thus, since v8.1.0, the JavaScript SDK provides a way to synchronously evaluate feature flags and settings via *snapshots*.
Using the `snapshot()` method, you can capture the current state of the *ConfigCat* client (including the latest downloaded config data) and use the resulting snapshot object to synchronously evaluate feature flags and settings based on the captured state:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
);
// Wait for the client to initialize.
await configCatClient.waitForReady();
const snapshot = configCatClient.snapshot();
const user = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
for (const key of snapshot.getAllKeys()) {
const value = snapshot.getValue(key, null, user);
console.log(`${key}: ${value}`);
}
```
Creating a snapshot is a cheap operation. This is possible because snapshots capture the client's internal (in-memory) cache. No attempt is made to refresh the internal cache, even if it's empty or expired.
caution
Please note that creating and using a snapshot
* won't trigger a sync with the external cache when working with [shared caching](https://configcat.com/docs/advanced/caching.md#shared-cache),
* won't fetch the latest config data from the ConfigCat CDN when the internally cached config data is empty or expired.
For the above reasons, it's recommended to use snapshots in conjunction with the Auto Polling mode, where the SDK automatically updates the internal cache in the background. (For other polling modes, you'll need to manually initiate a cache refresh by calling `forceRefreshAsync`.)
Because of this behavior, it's important to make sure that the client has completed initialization and populated its internal cache before creating snapshots. Otherwise the snapshot's evaluation methods won't have the data to do actual evaluation, but will just return the default value you pass to them. Which behavior is usually not what you want in your application.
In Auto Polling mode, you can use the `waitForReady` method to wait for the latest config data to become available locally. This is an asynchronous operation, which completes as soon as the client reaches the ready state, i.e. completes initialization (or the time specified via the `maxInitWaitTimeSeconds` option passes).
(Please note that this doesn't apply to other polling modes. In those cases, the client doesn't contact the ConfigCat CDN during initialization, so the ready state is reached as soon as the first sync with the external cache completes.)
Typically, you call `waitForReady` and wait for its completion only once, in the initialization phase of your application.
caution
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the return value.
```js
const clientCacheState = await configCatClient.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
// Handle initialization failure (see below).
console.warn('ConfigCat client failed to obtain the config data during initialization.');
}
```
You have the following options to handle unsuccessful initialization:
* If it's acceptable for your application to start up and use the default values passed to the evaluation methods, you may log some warning (or skip the check altogether as the client will log warnings anyway), and let the application continue.
* Otherwise, you need to either terminate the application or continue waiting. The latter is an option because the client might be able to obtain the config data later, in the case of a transient problem like some temporary network issue. However, the *ConfigCat SDK* doesn't provide out-of-the-box support for this case currently. You can implement this logic by subscribing to the `configChanged` hook and waiting for the first event.
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases where you want to prevent the SDK from making HTTP calls, you can switch it to offline mode:
```js
configCatClient.setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To switch the SDK back to online mode, do the following:
```js
configCatClient.setOnline();
```
Using the `configCatClient.isOffline` property you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a `{ [key: string]: boolean | string | number }` object or from a custom flag override data source.
### Map[](#map "Direct link to Map")
You can specify simple feature flag & setting overrides using a `{ [key: string]: boolean | string | number }` map.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: configcat.createFlagOverridesFromMap(
{
enabledFeature: true,
disabledFeature: false,
intSetting: 5,
doubleSetting: 3.14,
stringSetting: 'test',
},
configcat.OverrideBehaviour.LocalOnly,
),
},
);
```
### Custom data source implementation[](#custom-data-source-implementation "Direct link to Custom data source implementation")
You can create a custom flag override data source by implementing `IOverrideDataSource`.
The SDK provides the `createSettingFromValue` function to create `Setting` objects from simple `boolean`, `string` and `number` values. In case you need complex (full-featured) flag overrides, you can use the `deserializeConfig` function to obtain `Setting` objects from a config JSON conforming to the [config JSON v6 format](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
```ts
class MyCustomOverrideDataSource implements IOverrideDataSource {
private settings: Record;
constructor(configJson: string) {
this.settings = deserializeConfig(configJson).f ?? {};
}
getOverrides(): Record {
return this.settings;
}
}
```
or
```js
function MyCustomOverrideDataSource(configJson) {
this.settings = deserializeConfig(configJson).f ?? {};
}
MyCustomOverrideDataSource.prototype.getOverrides = function () {
return this.settings;
};
```
then
```js
// Set the `MyCustomOverrideDataSource` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: {
dataSource: new MyCustomOverrideDataSource('{ "f": { ... } }'),
behaviour: configcat.OverrideBehaviour.LocalOnly,
}
},
);
```
## Logging[](#logging "Direct link to Logging")
### Setting log levels[](#setting-log-levels "Direct link to Setting log levels")
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: configcat.createConsoleLogger(configcat.LogLevel.Info), // Setting log level to Info
},
);
```
Available log levels:
| Level | Description |
| ----- | ------------------------------------------------------- |
| Off | Nothing gets logged. |
| Error | Only error level events are logged. |
| Warn | Default. Errors and Warnings are logged. |
| Info | Errors, Warnings and feature flag evaluation is logged. |
| Debug | All of the above plus debug info is logged. |
Info level logging helps to inspect the feature flag evaluation process:
```bash
ConfigCat - INFO - [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"#SOME-USER-ID#","Email":"configcat@example.com"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
The SDK provides a simple logger implementation that logs to [the debugging console](https://developer.mozilla.org/en-US/docs/Web/API/console) (`configcat.createConsoleLogger(...)`) but it also allows you to inject any custom implementation of `IConfigCatLogger`.
```ts
class MyCustomLogger implements IConfigCatLogger {
/**
* Writes an event into the log.
* @param level Event severity level.
* @param eventId Event identifier.
* @param message Message.
* @param exception The exception object related to the message (if any).
*/
log(
level: LogLevel,
eventId: LogEventId,
message: LogMessage,
exception?: any,
): void {
// insert your custom log logic
}
}
```
or
```js
function MyCustomLogger() {}
MyCustomLogger.prototype.log = function (level, eventId, message, exception) {
// insert your custom log logic
};
```
then
```js
// Set the `MyCustomLogger` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: new MyCustomLogger(),
},
);
```
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by providing a callback function via the `logFilter` option. The callback will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `IConfigCatLogger.level` property). That is, the callback allows you to filter log events by `level`, `eventId`, `message` or `exception`. The formatted message string can be obtained via `message.toString()`. If the callback function returns `true`, the event will be logged, otherwise it will be skipped.
```js
// Filter out events with id 1001 from the log.
const logFilter = (level, eventId, message, exception) => eventId != 1001;
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{
logFilter: logFilter
}
);
```
caution
Please make sure that your log filter logic doesn't perform heavy computation. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## `getAllKeysAsync()`[](#getallkeysasync "Direct link to getallkeysasync")
You can get the keys for all available feature flags and settings by calling the `getAllKeysAsync()` method.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
const keys = await configCatClient.getAllKeysAsync();
console.log(keys);
```
## `getAllValuesAsync()`[](#getallvaluesasync "Direct link to getallvaluesasync")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValuesAsync();
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValuesAsync(userObject);
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
```
## `getAllValueDetailsAsync()`[](#getallvaluedetailsasync "Direct link to getallvaluedetailsasync")
Evaluates and returns the values along with evaluation details of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValueDetailsAsync();
settingValues.forEach((details) => console.log(details));
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValueDetailsAsync(userObject);
settingValues.forEach((details) => console.log(details));
```
## Using custom cache implementation[](#using-custom-cache-implementation "Direct link to Using custom cache implementation")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) interface and set the `cache` property in the options passed to `getClient`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
```ts
class MyCustomCache implements IConfigCatCache {
set(key: string, value: string): Promise | void {
// insert your cache write logic here
}
get(
key: string,
): Promise | string | null | undefined {
// insert your cache read logic here
}
}
```
or
```js
function MyCustomCache() {}
MyCustomCache.prototype.set = function (key, value) {
// insert your cache write logic here
};
MyCustomCache.prototype.get = function (key) {
// insert your cache read logic here
};
```
then
```js
// Set the `MyCustomCache` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
cache: new MyCustomCache(),
},
);
```
info
The JavaScript SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Using ConfigCat behind a proxy[](#using-configcat-behind-a-proxy "Direct link to Using ConfigCat behind a proxy")
It is possible to set up the SDK to route HTTP requests through a HTTP, HTTPS or SOCKS proxy.
```bash
npm i https-proxy-agent
```
```js
import { HttpsProxyAgent } from 'https-proxy-agent';
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
httpsAgent: new HttpsProxyAgent("http://192.168.1.1:8080"),
},
);
```
info
By default, you need to specify the `httpsAgent` option because the SDK always uses HTTPS to access the ConfigCat CDN. However, if you set the `baseUrl` to a `http://...` URL, you will need to install `http-proxy-agent` and set the `httpAgent` option instead.
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the *ConfigCat SDK* that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Platform compatibility[](#platform-compatibility "Direct link to Platform compatibility")
The SDK should be compatible with newer versions of Bun.
The SDK is [tested](https://github.com/configcat/js-unified-sdk/blob/master/.github/workflows/js-sdk-ci.yml) against the following runtimes:
* Bun (v1.1.0, latest stable) on Windows / Ubuntu / macOS
The SDK is compatible with TypeScript v4.0.2 or newer. Earlier versions may work but those are not tested, thus, not supported officially.
These tests are running on each pull request, before each deploy, and on a daily basis.
You can view a sample run [here](https://github.com/configcat/js-unified-sdk/actions/runs/11745259578).
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
* [Sample Bun console application](https://github.com/configcat/js-unified-sdk/tree/master/samples/bun-console)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
* [ConfigCat SDK for JavaScript in NPM](https://www.npmjs.com/package/@configcat/sdk)
---
# Source: https://configcat.com/docs/advanced/caching.md
# Polling modes & Caching
Copy page
There are 3 different ways (polling modes) to control caching.
## Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
In auto polling mode, the ConfigCat SDK downloads the latest feature flags and settings from the ConfigCat CDN automatically and stores them in the cache. By default, this happens every 60 seconds. You can set the polling interval to any value between 1 and 2,147,483 seconds.
## Lazy loading[](#lazy-loading "Direct link to Lazy loading")
In lazy loading mode, the ConfigCat SDK downloads the latest feature flags and settings from the ConfigCat CDN only if they are not already present in the cache, or if the cache has expired. By default, the cache Time To Live (TTL) value is 60 seconds. You can set it to any value between 1 and 2,147,483,647 seconds.
## Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the feature flags and settings are downloaded from the ConfigCat CDN. The ConfigCat SDK will not download them automatically. You can (and should) update the cache manually, by calling a `forceRefresh()` - this will download the latest feature flags and settings and update the cache.
This animation explains the different polling modes:
## Caching[](#caching "Direct link to Caching")
ConfigCat SDKs in their default setup store all the information they need for feature flag evaluation in memory. This behavior is extendable with custom cache implementations that you can use for pointing the SDK to your own data storage.
The main reason for caching is to accelerate serving feature flag evaluation requests when your application is in a stateless environment or frequently restarts. When the SDK notices that it has a valid cache entry to work with, it will use the data from the cache rather than initiating a new HTTP request towards ConfigCat. The cache's validity is based on the polling interval in case of [auto polling](#auto-polling-default) or on the TTL in case of [lazy loading](#lazy-loading).
info
See the [SDK specific docs](https://configcat.com/docs/sdk-reference/overview.md) for your desired platform to learn how to use custom cache implementations.
### Offline mode[](#offline-mode "Direct link to Offline mode")
ConfigCat SDKs have the capability to go offline. In offline mode, they work only from the configured cache and never communicate with ConfigCat over HTTP.
This allows you to set up a centralized cache that only one online ConfigCat SDK writes, but serves many offline ones.
info
See the [SDK specific docs](https://configcat.com/docs/sdk-reference/overview.md) for your desired platform to learn how to enable offline mode.
### Shared cache[](#shared-cache "Direct link to Shared cache")
As of certain versions, ConfigCat SDKs support using a shared cache. To achieve that, each SDK constructs the key for identifying a specific cache entry based on the SDK key passed at initialization. This means each platform specific SDK that uses the same SDK key will use the same cache entry.
Mixing this behavior with [offline mode](#offline-mode), you can have a centralized shared cache that serves many SDKs regardless of what platform they run on.
Support for shared caching was introduced in these SDK versions:
| SDK | Version |
| ------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| .NET | >= [v8.1.0](https://github.com/configcat/.net-sdk/releases) |
| Android (Java) | >= [v9.0.0](https://github.com/configcat/android-sdk/releases) |
| C++ | >= [v3.0.0](https://github.com/configcat/cpp-sdk/releases) |
| Dart (Flutter) | >= [v3.0.0](https://github.com/configcat/dart-sdk/releases) |
| Elixir | >= [v3.0.0](https://github.com/configcat/elixir-sdk/releases) |
| Go | >= [v8.0.0](https://github.com/configcat/go-sdk/releases) |
| Java | >= [v8.2.0](https://github.com/configcat/java-sdk/releases) |
| JavaScript (Browser, Bun, Chromium Extension, Cloudflare Worker, Deno, Node.js) | >= [v1.0.0](https://github.com/configcat/js-unified-sdk/releases) |
| JS - Legacy | >= [v8.0.0](https://github.com/configcat/js-sdk/releases) |
| JS SSR - Legacy | >= [v7.0.0](https://github.com/configcat/js-ssr-sdk/releases) |
| Kotlin | >= [v2.0.0](https://github.com/configcat/kotlin-sdk/releases) |
| Node.js - Legacy | >= [v10.0.0](https://github.com/configcat/node-sdk/releases) |
| PHP | >= [v8.0.0](https://github.com/configcat/php-sdk/releases) |
| Python | >= [v8.0.0](https://github.com/configcat/python-sdk/releases) |
| React | >= [v3.0.0](https://github.com/configcat/react-sdk/releases) |
| Ruby | >= [v7.0.0](https://github.com/configcat/ruby-sdk/releases) |
| Rust | >= [v0.1.0](https://github.com/configcat/rust-sdk/releases) |
| Swift (iOS) | >= [v10.0.0](https://github.com/configcat/swift-sdk/releases) |
---
# Source: https://configcat.com/docs/sdk-reference/js/chromium-extension.md
# Chromium Extension SDK
Copy page
[](https://github.com/configcat/js-unified-sdk/stargazers) [](https://github.com/configcat/js-unified-sdk/actions/workflows/js-sdk-ci.yml) [](https://sonarcloud.io/project/overview?id=configcat_js-unified-sdk) [](https://snyk.io/test/github/configcat/js-unified-sdk?targetFile=package.json) [](https://sonarcloud.io/dashboard?id=configcat_js-sdk) [](https://data.jsdelivr.com/v1/package/npm/@configcat/sdk/badge)
[ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Install and import package[](#1-install-and-import-package "Direct link to 1. Install and import package")
* via NPM
* via CDN
First install the [NPM package](https://npmjs.com/package/@configcat/sdk):
```bash
npm i @configcat/sdk
```
Then import it into your application:
```js
import * as configcat from "@configcat/sdk/chromium-extension";
```
info
For subpath imports to work **in TypeScript**, you must set the [moduleResolution](https://www.typescriptlang.org/tsconfig/#moduleResolution) option to `node16`, `nodenext` or `bundler` in your `tsconfig.json`. For TypeScript versions older than 4.7, where these options are not available, you need to fall back to module resolution `node` and importing from the main entry point `@configcat/sdk`.
info
Please note that subpath imports require your bundler to support the [exports](https://nodejs.org/api/packages.html#exports) package.json field, introduced in Node.js v12.7. **In the unlikely case of bundler compatibility issues**, you can fall back to importing from the main entry point `@configcat/sdk` as long as your bundler recognizes the [browser](https://github.com/defunctzombie/package-browser-field-spec) package.json field.
Import the package directly from a CDN server into your application:
```html
```
### 2. Create the *ConfigCat* client with your SDK Key[](#2-create-the-configcat-client-with-your-sdk-key "Direct link to 2-create-the-configcat-client-with-your-sdk-key")
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
```
### 3. Get your setting value[](#3-get-your-setting-value "Direct link to 3. Get your setting value")
The async/await way:
```js
const value = await configCatClient.getValueAsync(
'isMyAwesomeFeatureEnabled',
false,
);
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
```
The Promise way:
```js
configCatClient
.getValueAsync('isMyAwesomeFeatureEnabled', false)
.then((value) => {
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
});
```
The *ConfigCat SDK* also offers a synchronous API for feature flag evaluation. Read more [here](#snapshots-and-synchronous-feature-flag-evaluation).
### 4. Dispose the *ConfigCat* client[](#4-dispose-the-configcat-client "Direct link to 4-dispose-the-configcat-client")
You can safely dispose all clients at once or individually and release all associated resources on application exit.
```js
configcat.disposeAllClients(); // disposes all clients
// -or-
configCatClient.dispose(); // disposes a specific client
```
## Creating the *ConfigCat* Client[](#creating-the-configcat-client "Direct link to creating-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`configcat.getClient('')` returns a client with default options.
The `getClient` function has optional parameters, which can be used to adjust the behavior of the client.
| Parameters | Description | Default |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
| `sdkKey` | **REQUIRED.** SDK Key to access your feature flags and settings. Get it from *ConfigCat Dashboard*. | - |
| `pollingMode` | Optional. The polling mode to use to fetch the config data from the ConfigCat CDN. [More about polling modes](#polling-modes). | `PollingMode.AutoPoll` |
| `options` | Optional. The options object. See the table below. | - |
The available options depends on the chosen polling mode. However, there are some common options which can be set in the case of every polling mode:
| Option Parameter | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `configFetcher` | Custom [`IConfigCatConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigFetcher.ts) instance for downloading a config. | [`FetchApiConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/shared/FetchApiConfigFetcher.ts) |
| `cache` | Custom [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) implementation for caching the downloaded config. | [`ChromeLocalStorageConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/chromium-extension/ChromeLocalStorageConfigCache.ts) or [`IndexedDBConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/shared/IndexedDBConfigCache.ts) |
| `logger` | Custom [`IConfigCatLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) implementation for tracing. | [`ConfigCatConsoleLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) (with WARN level) |
| `logFilter` | Sets a custom log filter. [More about log filtering](#log-filtering). | `undefined` (none) |
| `baseUrl` | Sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. | |
| `requestTimeoutMs` | The amount of milliseconds the SDK waits for a response from the ConfigCat servers before returning values from the cache. | 30000 |
| `flagOverrides` | Local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). | |
| `dataGovernance` | Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `DataGovernance.Global`, `DataGovernance.EuOnly`. | `DataGovernance.Global` |
| `defaultUser` | Sets the default user. [More about default user](#default-user). | `undefined` (none) |
| `offline` | Determines whether the client should be initialized to offline mode. [More about offline mode](#online--offline-mode). | `false` |
Options also include a property named `setupHook`, which you can use to subscribe to the hooks (events) at the time of initialization. [More about hooks](#hooks).
For example:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
setupHooks: (hooks) => hooks.on('clientReady', function() {
const keys = this.configCatClient.snapshot().getAllKeys();
console.log(`Client is ready! Number of available feature flags: ${keys.length}`);
}),
},
);
```
info
You can acquire singleton client instances for your SDK keys using the `configcat.getClient(sdkKey: "")` factory function. (However, please keep in mind that subsequent calls to `getClient()` with the *same SDK Key* return a *shared* client instance, which was set up by the first call.)
You can close all open clients at once using the `configcat.disposeAllClients()` function or do it individually using the `configCatClient.dispose()` method.
## Anatomy of `getValueAsync()`[](#anatomy-of-getvalueasync "Direct link to anatomy-of-getvalueasync")
Returns a Promise with the value.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((value) => {
console.log(value);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | `typeof defaultValue` |
| -------------- | --------------------- |
| On/Off Toggle | `boolean` |
| Text | `string` |
| Whole Number | `number` |
| Decimal Number | `number` |
In addition to the types mentioned above, you also have the option to provide `null` or `undefined` for the `defaultValue` parameter regardless of the setting kind. However, if you do so, the return type of the `getValue` method will be
* `boolean | string | number | null` when `defaultValue` is `null` or
* `boolean | string | number | undefined` when `defaultValue` is `undefined`.
This is because in these cases the exact return type cannot be determined at compile-time as the TypeScript compiler has no information about the setting type.
It's important to note that providing any other type for the `defaultValue` parameter will result in a `TypeError`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
## Anatomy of `getValueDetailsAsync()`[](#anatomy-of-getvaluedetailsasync "Direct link to anatomy-of-getvaluedetailsasync")
`getValueDetailsAsync()` is similar to `getValueAsync()` but instead of returning the evaluated value only, it provides more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const details = await configCatClient.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((details) => {
console.log(details);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `key` | `string` | The key of the evaluated feature flag or setting. |
| `value` | `boolean` / `string` / `number` | The evaluated value of the feature flag or setting. |
| `user` | `User` | The User Object used for the evaluation. |
| `isDefaultValue` | `boolean` | True when the default value passed to `getValueDetailsAsync()` is returned due to an error. |
| `errorCode` | `EvaluationErrorCode` | In case of an error, this property contains a code that identifies the reason for the error. |
| `errorMessage` | `string` | In case of an error, this property contains the error message. |
| `errorException` | `any` | In case of an error, this property contains the related exception object (if any). |
| `matchedTargetingRule` | `TargetingRule` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matchedPercentageOption` | `PercentageOption` | The Percentage Option (if any) that was used to select the evaluated value. |
| `fetchTime` | `Date` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
For simple targeting:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
```
```js
const userObject = { identifier: 'john@example.com' };
```
| Parameters | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any `string` value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
For advanced targeting:
```js
const userObject = {
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
SubscriptionType: 'Pro',
UserRole: 'Admin',
},
};
```
The `custom` dictionary also allows attribute values other than `string` values:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
userObject.custom = {
Rating: 4.5,
RegisteredAt: new Date('2023-11-22T12:34:56.000Z'),
Roles: ['Role1', 'Role2'],
};
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `string` values,
* all other values are automatically converted to `string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `number` values,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `Date` values, which are automatically converted to a second-based Unix timestamp,
* accept `number` values representing a second-based Unix timestamp,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept arrays of `string`,
* accept `string` values containing a valid JSON string which can be deserialized to an array of `string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
It's possible to set a default User Object that will be used on feature flag and setting evaluation. It can be useful when your application has a single user only or rarely switches users.
You can set the default User Object either on SDK initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
defaultUser: { identifier: 'john@example.com' },
},
);
```
...or using the `setDefaultUser()` method of the `configCatClient` object:
```js
configCatClient.setDefaultUser({ identifier: 'john@example.com' });
```
Whenever the evaluation methods like `getValueAsync()`, `getValueDetailsAsync()`, etc. are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
// The default user will be used in the evaluation process.
const value = await configCatClient.getValueAsync('keyOfMyFeatureFlag', false);
```
When a `user` parameter is passed to the evaluation methods, it takes precedence over the default user.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
const otherUser = { identifier: 'brian@example.com' };
// otherUser will be used in the evaluation process.
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag',
false,
otherUser,
);
```
You can also remove the default user by doing the following:
```js
configCatClient.clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValueAsync()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle. [More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `pollIntervalSeconds` option parameter to change the polling interval.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
pollIntervalSeconds: 95,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------------------------------------------------------------------------------------- | ------- |
| `pollIntervalSeconds` | Polling interval in seconds. | 60s |
| `maxInitWaitTimeSeconds` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5s |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `getValueAsync()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValueAsync()` will return the setting value after the cache is updated.
Use `cacheTimeToLiveSeconds` option parameter to set cache lifetime.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.LazyLoad,
{
cacheTimeToLiveSeconds: 600,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------- | ------- |
| `cacheTimeToLiveSeconds` | Cache TTL in seconds. | 60s |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefreshAsync()` is your application's responsibility.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
await configCatClient.forceRefreshAsync();
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
> `getValueAsync()` returns `defaultValue` if the cache is empty. Call `forceRefreshAsync()` to update the cache.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value); // console: "my default value"
await configCatClient.forceRefreshAsync();
value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `clientReady: [cacheState: ClientCacheState]`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after the initial sync with the external cache (if any) completes.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTimeSeconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the `cacheState` argument.
* `configFetched: [result: RefreshResult, isInitiatedByUser: boolean]`: This event is emitted each time the client attempts to refresh the cached config by fetching the latest version from the ConfigCat CDN. It is emitted not only when `ForceRefreshAsync` is called but also when the refresh is initiated by the client automatically. Thus, this event allows you to observe potential network issues that occur under the hood.
* `configChanged: [newConfig: IConfig]`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `flagEvaluated: [evaluationDetails: IEvaluationDetails]`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetailsAsync()`](#anatomy-of-getvaluedetailsasync).
* `clientError: [message: string, exception?: any]`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', function() {
/* handle the event */
}),
},
);
```
...or directly on the `ConfigCatClient` instance:
```js
configCatClient.on('flagEvaluated', function() {
/* handle the event */
});
```
caution
Some events (e.g. `clientReady`, `configChanged` and `clientError`) may be emitted before `getClient` returns. This means you may miss them unless you subscribe on initialization.
However, even if you do, there's another gotcha: it's not safe to use the outer `configCatClient` variable in your event handler because it may not yet be assigned when the handler is called. Instead, you can safely access the client instance via `this.configCatClient` - provided that the event handler is a normal function, not an arrow function.
## Snapshots and synchronous feature flag evaluation[](#snapshots-and-synchronous-feature-flag-evaluation "Direct link to Snapshots and synchronous feature flag evaluation")
On JavaScript platforms, the *ConfigCat* client provides only asynchronous methods for evaluating feature flags and settings because these operations may involve network communication (e.g. downloading config data from the ConfigCat CDN servers), which is necessarily an asynchronous operation in JavaScript.
However, there can be circumstances where synchronous evaluation is preferable, thus, since v8.1.0, the JavaScript SDK provides a way to synchronously evaluate feature flags and settings via *snapshots*.
Using the `snapshot()` method, you can capture the current state of the *ConfigCat* client (including the latest downloaded config data) and use the resulting snapshot object to synchronously evaluate feature flags and settings based on the captured state:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
);
// Wait for the client to initialize.
await configCatClient.waitForReady();
const snapshot = configCatClient.snapshot();
const user = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
for (const key of snapshot.getAllKeys()) {
const value = snapshot.getValue(key, null, user);
console.log(`${key}: ${value}`);
}
```
Creating a snapshot is a cheap operation. This is possible because snapshots capture the client's internal (in-memory) cache. No attempt is made to refresh the internal cache, even if it's empty or expired.
caution
Please note that creating and using a snapshot
* won't trigger a sync with the external cache when working with [shared caching](https://configcat.com/docs/advanced/caching.md#shared-cache),
* won't fetch the latest config data from the ConfigCat CDN when the internally cached config data is empty or expired.
For the above reasons, it's recommended to use snapshots in conjunction with the Auto Polling mode, where the SDK automatically updates the internal cache in the background. (For other polling modes, you'll need to manually initiate a cache refresh by calling `forceRefreshAsync`.)
Because of this behavior, it's important to make sure that the client has completed initialization and populated its internal cache before creating snapshots. Otherwise the snapshot's evaluation methods won't have the data to do actual evaluation, but will just return the default value you pass to them. Which behavior is usually not what you want in your application.
In Auto Polling mode, you can use the `waitForReady` method to wait for the latest config data to become available locally. This is an asynchronous operation, which completes as soon as the client reaches the ready state, i.e. completes initialization (or the time specified via the `maxInitWaitTimeSeconds` option passes).
(Please note that this doesn't apply to other polling modes. In those cases, the client doesn't contact the ConfigCat CDN during initialization, so the ready state is reached as soon as the first sync with the external cache completes.)
Typically, you call `waitForReady` and wait for its completion only once, in the initialization phase of your application.
caution
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the return value.
```js
const clientCacheState = await configCatClient.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
// Handle initialization failure (see below).
console.warn('ConfigCat client failed to obtain the config data during initialization.');
}
```
You have the following options to handle unsuccessful initialization:
* If it's acceptable for your application to start up and use the default values passed to the evaluation methods, you may log some warning (or skip the check altogether as the client will log warnings anyway), and let the application continue.
* Otherwise, you need to either terminate the application or continue waiting. The latter is an option because the client might be able to obtain the config data later, in the case of a transient problem like some temporary network issue. However, the *ConfigCat SDK* doesn't provide out-of-the-box support for this case currently. You can implement this logic by subscribing to the `configChanged` hook and waiting for the first event.
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases where you want to prevent the SDK from making HTTP calls, you can switch it to offline mode:
```js
configCatClient.setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To switch the SDK back to online mode, do the following:
```js
configCatClient.setOnline();
```
Using the `configCatClient.isOffline` property you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a `{ [key: string]: boolean | string | number }` object, from the current query string or from a custom flag override data source.
### Map[](#map "Direct link to Map")
You can specify simple feature flag & setting overrides using a `{ [key: string]: boolean | string | number }` map.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: configcat.createFlagOverridesFromMap(
{
enabledFeature: true,
disabledFeature: false,
intSetting: 5,
doubleSetting: 3.14,
stringSetting: 'test',
},
configcat.OverrideBehaviour.LocalOnly,
),
},
);
```
### Query string[](#query-string "Direct link to Query string")
It is also possible to override feature flags & settings using query string parameters.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: createFlagOverridesFromQueryParams(configcat.OverrideBehaviour.LocalOverRemote),
},
);
```
With that setup, you can override feature flags and settings by appending query string parameters to the URL of your application in the following form: `https://app.example.com/?cc-myBooleanFlag=true&cc-myStringSetting=abc&...`
The setting type is automatically inferred from the value. Please pay attention to this behavior. The inferred type of the value must match the type of the feature flag or setting you override (see also [this table](#setting-type-mapping)). In case you want to force a boolean or number value to be interpreted as a string value, use the `;str` suffix: `&cc-myStringSetting;str=true`.
If the default prefix used to differentiate between normal and flag override query string parameters (`cc-`) is not suitable for you, you can set a custom prefix using the corresponding optional parameter of `createFlagOverridesFromQueryParams`.
### Custom data source implementation[](#custom-data-source-implementation "Direct link to Custom data source implementation")
You can create a custom flag override data source by implementing `IOverrideDataSource`.
The SDK provides the `createSettingFromValue` function to create `Setting` objects from simple `boolean`, `string` and `number` values. In case you need complex (full-featured) flag overrides, you can use the `deserializeConfig` function to obtain `Setting` objects from a config JSON conforming to the [config JSON v6 format](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
```ts
class MyCustomOverrideDataSource implements IOverrideDataSource {
private settings: Record;
constructor(configJson: string) {
this.settings = deserializeConfig(configJson).f ?? {};
}
getOverrides(): Record {
return this.settings;
}
}
```
or
```js
function MyCustomOverrideDataSource(configJson) {
this.settings = deserializeConfig(configJson).f ?? {};
}
MyCustomOverrideDataSource.prototype.getOverrides = function () {
return this.settings;
};
```
then
```js
// Set the `MyCustomOverrideDataSource` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: {
dataSource: new MyCustomOverrideDataSource('{ "f": { ... } }'),
behaviour: configcat.OverrideBehaviour.LocalOnly,
}
},
);
```
## Logging[](#logging "Direct link to Logging")
### Setting log levels[](#setting-log-levels "Direct link to Setting log levels")
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: configcat.createConsoleLogger(configcat.LogLevel.Info), // Setting log level to Info
},
);
```
Available log levels:
| Level | Description |
| ----- | ------------------------------------------------------- |
| Off | Nothing gets logged. |
| Error | Only error level events are logged. |
| Warn | Default. Errors and Warnings are logged. |
| Info | Errors, Warnings and feature flag evaluation is logged. |
| Debug | All of the above plus debug info is logged. |
Info level logging helps to inspect the feature flag evaluation process:
```bash
ConfigCat - INFO - [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"#SOME-USER-ID#","Email":"configcat@example.com"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
The SDK provides a simple logger implementation that logs to [the debugging console](https://developer.mozilla.org/en-US/docs/Web/API/console) (`configcat.createConsoleLogger(...)`) but it also allows you to inject any custom implementation of `IConfigCatLogger`.
```ts
class MyCustomLogger implements IConfigCatLogger {
/**
* Writes an event into the log.
* @param level Event severity level.
* @param eventId Event identifier.
* @param message Message.
* @param exception The exception object related to the message (if any).
*/
log(
level: LogLevel,
eventId: LogEventId,
message: LogMessage,
exception?: any,
): void {
// insert your custom log logic
}
}
```
or
```js
function MyCustomLogger() {}
MyCustomLogger.prototype.log = function (level, eventId, message, exception) {
// insert your custom log logic
};
```
then
```js
// Set the `MyCustomLogger` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: new MyCustomLogger(),
},
);
```
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by providing a callback function via the `logFilter` option. The callback will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `IConfigCatLogger.level` property). That is, the callback allows you to filter log events by `level`, `eventId`, `message` or `exception`. The formatted message string can be obtained via `message.toString()`. If the callback function returns `true`, the event will be logged, otherwise it will be skipped.
```js
// Filter out events with id 1001 from the log.
const logFilter = (level, eventId, message, exception) => eventId != 1001;
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{
logFilter: logFilter
}
);
```
caution
Please make sure that your log filter logic doesn't perform heavy computation. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## `getAllKeysAsync()`[](#getallkeysasync "Direct link to getallkeysasync")
You can get the keys for all available feature flags and settings by calling the `getAllKeysAsync()` method.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
const keys = await configCatClient.getAllKeysAsync();
console.log(keys);
```
## `getAllValuesAsync()`[](#getallvaluesasync "Direct link to getallvaluesasync")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValuesAsync();
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValuesAsync(userObject);
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
```
## `getAllValueDetailsAsync()`[](#getallvaluedetailsasync "Direct link to getallvaluedetailsasync")
Evaluates and returns the values along with evaluation details of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValueDetailsAsync();
settingValues.forEach((details) => console.log(details));
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValueDetailsAsync(userObject);
settingValues.forEach((details) => console.log(details));
```
## Using custom cache implementation[](#using-custom-cache-implementation "Direct link to Using custom cache implementation")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) interface and set the `cache` property in the options passed to `getClient`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
```ts
class MyCustomCache implements IConfigCatCache {
set(key: string, value: string): Promise | void {
// insert your cache write logic here
}
get(
key: string,
): Promise | string | null | undefined {
// insert your cache read logic here
}
}
```
or
```js
function MyCustomCache() {}
MyCustomCache.prototype.set = function (key, value) {
// insert your cache write logic here
};
MyCustomCache.prototype.get = function (key) {
// insert your cache read logic here
};
```
then
```js
// Set the `MyCustomCache` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
cache: new MyCustomCache(),
},
);
```
info
The JavaScript SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the *ConfigCat SDK* that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Platform compatibility[](#platform-compatibility "Direct link to Platform compatibility")
The SDK should be compatible with modern Chromium-based browsers and bundlers.
The SDK is [tested](https://github.com/configcat/js-unified-sdk/blob/master/.github/workflows/js-sdk-ci.yml) against the following browsers:
* Chrome (stable, latest, beta)
* Chromium (72.0.3626.0, 80.0.3987.0)
The SDK is compatible with TypeScript v4.0.2 or newer. Earlier versions may work but those are not tested, thus, not supported officially.
These tests are running on each pull request, before each deploy, and on a daily basis.
You can view a sample run [here](https://github.com/configcat/js-unified-sdk/actions/runs/11745259578).
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
* [Sample Chrome extension](https://github.com/configcat/js-unified-sdk/tree/master/samples/chrome-extension)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
* [ConfigCat SDK for JavaScript in NPM](https://www.npmjs.com/package/@configcat/sdk)
---
# Source: https://configcat.com/docs/glossary/ci-cd-pipeline.md
# CI/CD Pipeline - Streamlining Software Delivery
Copy page
## Introduction[](#introduction "Direct link to Introduction")
In the ever-evolving realm of software development, efficiency and speed are paramount. The CI/CD pipeline emerges as a cornerstone in achieving these goals, merging coding, testing, and deployment into a streamlined and automated process. Let’s unpack the components of CI/CD pipelines and their impact on software delivery.
## What is a CI/CD Pipeline?[](#what-is-a-cicd-pipeline "Direct link to What is a CI/CD Pipeline?")
CI/CD stands for Continuous Integration and Continuous Deployment/Delivery. This method introduces automation into the development process to enable frequent application delivery to customers. The primary concepts central to CI/CD include continuous integration, continuous delivery, and continuous deployment.
## The Objectives of a CI/CD Pipeline[](#the-objectives-of-a-cicd-pipeline "Direct link to The Objectives of a CI/CD Pipeline")
* **Rapid Deployment**: Facilitating frequent and reliable software updates.
* **Quality Assurance**: Ensuring consistent quality and performance through automated testing.
* **Risk Reduction**: Minimizing errors and issues in production through early detection.
* **Efficient Development**: Streamlining the development process for faster turnaround times.
## The CI/CD Pipeline Process[](#the-cicd-pipeline-process "Direct link to The CI/CD Pipeline Process")
* **Code Integration**: Developers merge their changes into a shared repository, triggering automated builds and tests.
* **Automated Testing**: The integrated code is automatically tested for bugs, performance issues, and other potential problems.
* **Deployment**: Upon successful testing, the code is deployed to a staging or production environment.
* **Monitoring and Feedback**: Continuous monitoring of the application's performance and gathering feedback for future improvements.
## Why CI/CD Pipelines are Essential[](#why-cicd-pipelines-are-essential "Direct link to Why CI/CD Pipelines are Essential")
* **Speedy Deliveries**: Accelerates the process of getting software improvements to end-users.
* **Enhanced Collaboration**: Fosters a collaborative environment where code integration and problem-solving happen in real-time.
* **Adaptability**: Allows for quick adaptation to market changes and user feedback.
* **Cost-Effectiveness**: Reduces costs associated with manual processes and delayed releases.
## Challenges in CI/CD Pipeline and Solutions[](#challenges-in-cicd-pipeline-and-solutions "Direct link to Challenges in CI/CD Pipeline and Solutions")
* **Complex Integration**: Integrating various tools and platforms can be challenging. Solution: Utilize versatile CI/CD tools that offer broad integration capabilities.
* **Security Concerns**: Continuous deployment could introduce security vulnerabilities. Solution: Implement robust security checks within the pipeline.
* **Managing Dependencies**: Handling dependencies in a constantly changing environment. Solution: Effective dependency management strategies and tools.
## Conclusion[](#conclusion "Direct link to Conclusion")
The CI/CD pipeline is more than just a development strategy; it’s a catalyst for agility, quality, and innovation in software development. By embracing the utility of CI/CD pipelines, organizations can ensure that they not only keep pace with market demands but also drive forward with efficiency and precision. As the backbone of modern DevOps practices, the CI/CD pipeline stands as an essential element in the journey towards streamlined, resilient, and customer-centric software delivery.
---
# Source: https://configcat.com/docs/advanced/code-references/circleci-orb.md
# CircleCI Orb - Scan your source code for feature flags
Copy page
This section describes how to use ConfigCat's [CircleCI Orb](https://circleci.com/developer/orbs/orb/configcat/scan-repository) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about CircleCI Orbs [here](https://circleci.com/orbs/).
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in [CircleCI Environment Variables](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new CircleCI YAML config in your repository under the `.circleci` folder, and put the following snippet into it. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
version: 2.1
orbs:
configcat: configcat/scan-repository@1.11.1
workflows:
main:
jobs:
- configcat/scan:
config-id: PASTE-YOUR-CONFIG-ID-HERE # required
file-url-template: 'https://github.com/your/repo/blob/{commitHash}/{filePath}#L{lineNumber}' # optional
commit-url-template: 'https://github.com/your/repo/commit/{commitHash}' # optional
# line-count: 3 # optional
# timeout: 1800 # optional
# sub-folder: 'src' # optional
# exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# alias-patterns: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) # optional
# usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional
# verbose: true # optional
```
4. Commit & push your changes.
The above example configures a workflow that executes the scan and code reference upload on every git `push` event. Scan reports are uploaded for each branch of your repository that triggers the workflow.
## Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------- |
| `config-id` | ID of the ConfigCat config to scan against. | ☑ | |
| `api-host` | ConfigCat Management API host. | | `api.configcat.com` |
| `api-user` | Name of the environment variable where the [ConfigCat Management API basic authentication username](https://app.configcat.com/my-account/public-api-credentials) is stored. | | CONFIGCAT\_API\_USER |
| `api-pass` | Name of the environment variable where the [ConfigCat Management API basic authentication password](https://app.configcat.com/my-account/public-api-credentials) is stored. | | CONFIGCAT\_API\_PASS |
| `file-url-template` | Template url used to generate VCS file links. Available template parameters: `commitHash`, `filePath`, `lineNumber`. Example: `https://github.com/my/repo/blob/{commitHash}/{filePath}#L{lineNumber}` | | |
| `commit-url-template` | Template url used to generate VCS commit links. Available template parameters: `commitHash`. Example: `https://github.com/my/repo/commit/{commitHash}` | | |
| `line-count` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `timeout` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `sub-folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
# Source: https://configcat.com/docs/integrations/circleci.md
# CircleCI - Scan your code for feature flag usages
Copy page
ConfigCat's [CircleCI Orb](https://circleci.com/developer/orbs/orb/configcat/scan-repository) has the ability to scan your source code for feature flag and setting usages and upload the found code references to ConfigCat.
This feature makes the elimination of the technical debt easier, as it can show which repositories reference your feature flags and settings in one centralized place on your [Dashboard](https://app.configcat.com).
[Here](https://configcat.com/docs/advanced/code-references/overview.md) you can find more details about how this feature works.
This section describes how to use ConfigCat's [CircleCI Orb](https://circleci.com/developer/orbs/orb/configcat/scan-repository) to automatically scan your source code for feature flag and setting usages and upload the found code references to ConfigCat. You can find more information about CircleCI Orbs [here](https://circleci.com/orbs/).
## Setup[](#setup "Direct link to Setup")
1. Create a new [ConfigCat Management API credential](https://app.configcat.com/my-account/public-api-credentials) and store its values in [CircleCI Environment Variables](https://circleci.com/docs/2.0/env-vars/#setting-an-environment-variable-in-a-project) with the following names: `CONFIGCAT_API_USER`, `CONFIGCAT_API_PASS`.

2. Get your selected [Config's ID](https://configcat.com/docs/advanced/code-references/overview.md#config-id).
3. Create a new CircleCI YAML config in your repository under the `.circleci` folder, and put the following snippet into it. Don't forget to replace the `PASTE-YOUR-CONFIG-ID-HERE` value with your actual Config ID.
```yaml
version: 2.1
orbs:
configcat: configcat/scan-repository@1.11.1
workflows:
main:
jobs:
- configcat/scan:
config-id: PASTE-YOUR-CONFIG-ID-HERE # required
file-url-template: 'https://github.com/your/repo/blob/{commitHash}/{filePath}#L{lineNumber}' # optional
commit-url-template: 'https://github.com/your/repo/commit/{commitHash}' # optional
# line-count: 3 # optional
# timeout: 1800 # optional
# sub-folder: 'src' # optional
# exclude-keys: > # optional
# flag_key_to_exclude_1
# flag_key_to_exclude_2
# alias-patterns: (\w+) = :CC_KEY,const (\w+) = feature_flags\.enabled\(:CC_KEY\) # optional
# usage-patterns: feature_flags\.enabled\(:CC_KEY\) # optional
# verbose: true # optional
```
4. Commit & push your changes.
The above example configures a workflow that executes the scan and code reference upload on every git `push` event. Scan reports are uploaded for each branch of your repository that triggers the workflow.
## Available Options[](#available-options "Direct link to Available Options")
| Parameter | Description | Required | Default |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------- |
| `config-id` | ID of the ConfigCat config to scan against. | ☑ | |
| `api-host` | ConfigCat Management API host. | | `api.configcat.com` |
| `api-user` | Name of the environment variable where the [ConfigCat Management API basic authentication username](https://app.configcat.com/my-account/public-api-credentials) is stored. | | CONFIGCAT\_API\_USER |
| `api-pass` | Name of the environment variable where the [ConfigCat Management API basic authentication password](https://app.configcat.com/my-account/public-api-credentials) is stored. | | CONFIGCAT\_API\_PASS |
| `file-url-template` | Template url used to generate VCS file links. Available template parameters: `commitHash`, `filePath`, `lineNumber`. Example: `https://github.com/my/repo/blob/{commitHash}/{filePath}#L{lineNumber}` | | |
| `commit-url-template` | Template url used to generate VCS commit links. Available template parameters: `commitHash`. Example: `https://github.com/my/repo/commit/{commitHash}` | | |
| `line-count` | Context line count before and after the reference line. (min: 1, max: 10) | | 4 |
| `timeout` | Scan timeout in seconds (default: 1800, min: 60). If the scan does not finish within this time, it is aborted. No partial results are returned. The command exits with a timeout error. | | 1800 |
| `sub-folder` | Sub-folder to scan, relative to the repository root folder. | | |
| `exclude-keys` | List of feature flag keys that must be excluded from the scan report. | | |
| `alias-patterns` | Comma delimited list of custom regex patterns used to search for additional aliases. | | |
| `usage-patterns` | Comma delimited list of custom regex patterns that describe additional feature flag key usages. | | |
| `verbose` | Turns on detailed logging. | | false |
---
# Source: https://configcat.com/docs/advanced/cli.md
# Command Line Interface (CLI)
Copy page
The [ConfigCat Command Line Interface (CLI)](https://github.com/configcat/cli) allows you to interact with the [Public Management API](https://configcat.com/docs/api/reference/configcat-public-management-api.md) via the command line. It supports most functionality found on the ConfigCat Dashboard. You can manage ConfigCat resources like Feature Flags, Targeting / Percentage rules, Products, Configs, Environments, and more.
The CLI also has the ability to [scan your source code](https://configcat.com/docs/advanced/code-references/overview.md) for feature flag and setting usage and upload the found code references to ConfigCat.
Finally, the CLI provides a few useful utilities, such as validating a config JSON file, downloading one from the ConfigCat CDN by SDK Key, etc. These can come in handy when you use [flag overrides](https://configcat.com/docs/sdk-reference/js/overview.md#flag-overrides) in your application.
```text
configcat
This is the Command Line Tool of ConfigCat.
ConfigCat is a hosted feature flag service: https://configcat.com
For more information, see the documentation here: https://configcat.com/docs/advanced/cli
Usage:
configcat [command] [options]
Options:
-v, --verbose Print detailed execution information
-ni, --non-interactive Turn off progress rendering and interactive features
--version Show version information
-?, -h, --help Show help and usage information
Commands:
setup Setup the CLI with Public Management API host and credentials
ls List all Product, Config, and Environment IDs
p, product Manage Products
c, config Manage Configs
webhook, wh Manage Webhooks
e, environment Manage Environments
f, flag, s, setting Manage Feature Flags & Settings
f2, flag-v2, s2, setting-v2 Manage V2 Feature Flags & Settings
seg, segment Manage Segments
permission-group, pg Manage Permission Groups
m, member Manage Members
t, tag Manage Tags
k, sdk-key List SDK Keys
scan Scan files for Feature Flag & Setting usages
eval Evaluate feature flags. In case of a single feature flag, by default, the command
writes only the evaluated value to the output. In case of multiple feature flags, the
command writes a table if no other format is specified
config-json Config JSON-related utilities
w, workspace Manage the CLI workspace. When set, the CLI's interactive mode filters Product and
Config selectors by the values set in the workspace
Use "configcat [command] -?" for more information about a command.
```
## Reference[](#reference "Direct link to Reference")
See the [command reference documentation](https://configcat.github.io/cli/) for more information about each available command.
## Getting started[](#getting-started "Direct link to Getting started")
The following instructions will guide you through the first steps to start using this tool.
### Installation[](#installation "Direct link to Installation")
You can install the CLI on multiple operating systems using the following sources.
**Homebrew (macOS / Linux)**
Install the CLI with [Homebrew](https://brew.sh) from [ConfigCat's tap](https://github.com/configcat/homebrew-tap) by executing the following command:
```bash
brew tap configcat/tap
brew install configcat
```
**Snap (Linux)**
Install the CLI with [Snapcraft](https://snapcraft.io) by executing the following command:
```bash
sudo snap install configcat
```
**Scoop (Windows)**
Install the CLI with [Scoop](https://scoop.sh) from [ConfigCat's bucket](https://github.com/configcat/scoop-configcat) by executing the following command:
```bash
scoop bucket add configcat https://github.com/configcat/scoop-configcat
scoop install configcat
```
**Chocolatey (Windows)**
Install the CLI with [Chocolatey](https://chocolatey.org/) by executing the following command:
```powershell
choco install configcat
```
**.NET tool / NuGet.org**
The CLI can be installed as a [.NET tool](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools) via the .NET SDK.
```bash
dotnet tool install -g configcat-cli
```
After installing, you can execute the CLI using the `configcat` command:
```bash
configcat scan "/repository" --print --config-id
```
**Docker**
The CLI can be executed from a [Docker](https://www.docker.com/) image.
```bash
docker pull configcat/cli
```
An example of how to scan a repository for feature flag & setting references with the docker image.
```bash
docker run --rm \
--env CONFIGCAT_API_HOST= \
--env CONFIGCAT_API_USER= \
--env CONFIGCAT_API_PASS= \
-v /path/to/repository:/repository \
configcat/cli scan "/repository" --print --config-id
```
**Install Script**
On Unix platforms, you can install the CLI by executing an install script.
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash
```
By default, the script downloads the OS specific artifact from the latest [GitHub Release](https://github.com/configcat/cli/releases) with `curl` and moves it into the `/usr/local/bin` directory.
It might happen that you don't have permissions to write into `/usr/local/bin`, then you should execute the install script with `sudo`.
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | sudo bash
```
The script accepts the following input parameters:
| Parameter | Description | Default value |
| ----------------- | ------------------------------------------------ | ---------------- |
| `-d`, `--dir` | The directory where the CLI should be installed. | `/usr/local/bin` |
| `-v`, `--version` | The desired version to install. | `latest` |
| `-a`, `--arch` | The desired architecture to install. | `x64` |
Available **architecture** values for Linux: `x64`, `musl-x64`, `arm`, `arm64`.
Available **architecture** values for macOS: `x64`, `arm64`.
**Script usage examples**:
*Custom installation directory*:
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash -s -- -d=/path/to/install
```
*Install a different version*:
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash -s -- -v=1.4.2
```
*Install with custom architecture*:
```bash
curl -fsSL "https://raw.githubusercontent.com/configcat/cli/main/scripts/install.sh" | bash -s -- -a=arm
```
**Standalone executables**
You can download the executables directly from [GitHub Releases](https://github.com/configcat/cli/releases) for your desired platform.
### Setup[](#setup "Direct link to Setup")
After a successful installation, the CLI must be set up with your [ConfigCat Public Management API credentials](https://app.configcat.com/my-account/public-api-credentials).
You can do this by using the `configcat setup` command.

#### Environment variables[](#environment-variables "Direct link to Environment variables")
Besides the `setup` command above, the CLI can read your credentials from the following environment variables.
| Name | Description |
| -------------------- | ---------------------------------------- |
| `CONFIGCAT_API_HOST` | API host (default: `api.configcat.com`). |
| `CONFIGCAT_API_USER` | API basic auth user name. |
| `CONFIGCAT_API_PASS` | API basic auth password. |
caution
When any of these environment variables are set, the CLI will use them over the local values set by the `configcat setup` command.
## Modes[](#modes "Direct link to Modes")
The CLI supports both interactive and argument driven execution. When no arguments provided for a command and user input is enabled (stdout is not redirected), the CLI automatically activates interactive mode.
### Interactive[](#interactive "Direct link to Interactive")

### With arguments[](#with-arguments "Direct link to With arguments")
The same operation with command arguments would look like this:
```bash
configcat flag-v2 create \
--config-id \
--name "My awesome feature" \
--hint "This is my awesome feature" \
--key my_awesome_feature
--type boolean \
--tag-ids \
--init-values-per-environment : \
```
info
Each `create` command writes the newly created resource's ID to the standard output so you can save that for further operations.
Example:
```bash
#!/bin/bash
ORGANIZATION_ID=""
PRODUCT_ID=$(configcat product create -o $ORGANIZATION_ID -n "")
CONFIG_ID=$(configcat config create -p $PRODUCT_ID -n "")
```
info
You can change the output format of several commands' result to JSON with the `--json` option, like: `configcat flag ls --json`. See more about these commands in the [command reference documentation](https://configcat.github.io/cli/).
## Scan & upload code references[](#scan--upload-code-references "Direct link to Scan & upload code references")
The CLI has the ability to scan your source code for feature flag and setting usage and upload the found code references to ConfigCat. You can read more about this feature [here](https://configcat.com/docs/advanced/code-references/overview.md).
## Examples[](#examples "Direct link to Examples")
Here are a few examples showing the true power of the CLI.
### Create a feature flag[](#create-a-feature-flag "Direct link to Create a feature flag")
The following example shows how you can create a feature flag in a specific config.

### Evaluate feature flags[](#evaluate-feature-flags "Direct link to Evaluate feature flags")
The following example shows how you can evaluate one or more feature flags.

### Feature flag value update[](#feature-flag-value-update "Direct link to Feature flag value update")
The following example shows how you can update the value of a feature flag in a specific environment.

### Add targeting rules[](#add-targeting-rules "Direct link to Add targeting rules")
The following example shows how you can add targeting rules to a feature flag.

### Add percentage options[](#add-percentage-options "Direct link to Add percentage options")
The following example shows how you can set percentage options in a feature flag.

---
# Source: https://configcat.com/docs/sdk-reference/js/cloudflare-worker.md
# Cloudflare Worker SDK
Copy page
[](https://github.com/configcat/js-unified-sdk/stargazers) [](https://github.com/configcat/js-unified-sdk/actions/workflows/js-sdk-ci.yml) [](https://sonarcloud.io/project/overview?id=configcat_js-unified-sdk) [](https://snyk.io/test/github/configcat/js-unified-sdk?targetFile=package.json) [](https://sonarcloud.io/dashboard?id=configcat_js-sdk) [](https://data.jsdelivr.com/v1/package/npm/@configcat/sdk/badge)
[ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Install and import package[](#1-install-and-import-package "Direct link to 1. Install and import package")
First install the [NPM package](https://npmjs.com/package/@configcat/sdk):
```bash
npm i @configcat/sdk
```
Then import it into your application:
```js
import * as configcat from "@configcat/sdk/cloudflare-worker";
```
### 2. Create the *ConfigCat* client with your SDK Key[](#2-create-the-configcat-client-with-your-sdk-key "Direct link to 2-create-the-configcat-client-with-your-sdk-key")
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#', configcat.PollingMode.LazyLoad);
```
### 3. Get your setting value[](#3-get-your-setting-value "Direct link to 3. Get your setting value")
The async/await way:
```js
const value = await configCatClient.getValueAsync(
'isMyAwesomeFeatureEnabled',
false,
);
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
```
The Promise way:
```js
configCatClient
.getValueAsync('isMyAwesomeFeatureEnabled', false)
.then((value) => {
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
});
```
The *ConfigCat SDK* also offers a synchronous API for feature flag evaluation. Read more [here](#snapshots-and-synchronous-feature-flag-evaluation).
### 4. Dispose the *ConfigCat* client[](#4-dispose-the-configcat-client "Direct link to 4-dispose-the-configcat-client")
You can safely dispose all clients at once or individually and release all associated resources on application exit.
```js
configcat.disposeAllClients(); // disposes all clients
// -or-
configCatClient.dispose(); // disposes a specific client
```
## Creating the *ConfigCat* Client[](#creating-the-configcat-client "Direct link to creating-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`configcat.getClient('')` returns a client with default options.
The `getClient` function has optional parameters, which can be used to adjust the behavior of the client.
| Parameters | Description | Default |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
| `sdkKey` | **REQUIRED.** SDK Key to access your feature flags and settings. Get it from *ConfigCat Dashboard*. | - |
| `pollingMode` | Optional. The polling mode to use to fetch the config data from the ConfigCat CDN. [More about polling modes](#polling-modes). | `PollingMode.AutoPoll` |
| `options` | Optional. The options object. See the table below. | - |
The available options depends on the chosen polling mode. However, there are some common options which can be set in the case of every polling mode:
| Option Parameter | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `configFetcher` | Custom [`IConfigCatConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigFetcher.ts) instance for downloading a config. | [`FetchApiConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/shared/FetchApiConfigFetcher.ts) |
| `cache` | Custom [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) implementation for caching the downloaded config. | [`CloudflareConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/cloudflare-worker/CloudflareConfigCache.ts) |
| `logger` | Custom [`IConfigCatLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) implementation for tracing. | [`ConfigCatConsoleLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) (with WARN level) |
| `logFilter` | Sets a custom log filter. [More about log filtering](#log-filtering). | `undefined` (none) |
| `baseUrl` | Sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. | |
| `requestTimeoutMs` | The amount of milliseconds the SDK waits for a response from the ConfigCat servers before returning values from the cache. | 30000 |
| `flagOverrides` | Local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). | |
| `dataGovernance` | Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `DataGovernance.Global`, `DataGovernance.EuOnly`. | `DataGovernance.Global` |
| `defaultUser` | Sets the default user. [More about default user](#default-user). | `undefined` (none) |
| `offline` | Determines whether the client should be initialized to offline mode. [More about offline mode](#online--offline-mode). | `false` |
Options also include a property named `setupHook`, which you can use to subscribe to the hooks (events) at the time of initialization. [More about hooks](#hooks).
For example:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
setupHooks: (hooks) => hooks.on('clientReady', function() {
const keys = this.configCatClient.snapshot().getAllKeys();
console.log(`Client is ready! Number of available feature flags: ${keys.length}`);
}),
},
);
```
info
You can acquire singleton client instances for your SDK keys using the `configcat.getClient(sdkKey: "")` factory function. (However, please keep in mind that subsequent calls to `getClient()` with the *same SDK Key* return a *shared* client instance, which was set up by the first call.)
You can close all open clients at once using the `configcat.disposeAllClients()` function or do it individually using the `configCatClient.dispose()` method.
## Anatomy of `getValueAsync()`[](#anatomy-of-getvalueasync "Direct link to anatomy-of-getvalueasync")
Returns a Promise with the value.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((value) => {
console.log(value);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | `typeof defaultValue` |
| -------------- | --------------------- |
| On/Off Toggle | `boolean` |
| Text | `string` |
| Whole Number | `number` |
| Decimal Number | `number` |
In addition to the types mentioned above, you also have the option to provide `null` or `undefined` for the `defaultValue` parameter regardless of the setting kind. However, if you do so, the return type of the `getValue` method will be
* `boolean | string | number | null` when `defaultValue` is `null` or
* `boolean | string | number | undefined` when `defaultValue` is `undefined`.
This is because in these cases the exact return type cannot be determined at compile-time as the TypeScript compiler has no information about the setting type.
It's important to note that providing any other type for the `defaultValue` parameter will result in a `TypeError`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
## Anatomy of `getValueDetailsAsync()`[](#anatomy-of-getvaluedetailsasync "Direct link to anatomy-of-getvaluedetailsasync")
`getValueDetailsAsync()` is similar to `getValueAsync()` but instead of returning the evaluated value only, it provides more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const details = await configCatClient.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((details) => {
console.log(details);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `key` | `string` | The key of the evaluated feature flag or setting. |
| `value` | `boolean` / `string` / `number` | The evaluated value of the feature flag or setting. |
| `user` | `User` | The User Object used for the evaluation. |
| `isDefaultValue` | `boolean` | True when the default value passed to `getValueDetailsAsync()` is returned due to an error. |
| `errorCode` | `EvaluationErrorCode` | In case of an error, this property contains a code that identifies the reason for the error. |
| `errorMessage` | `string` | In case of an error, this property contains the error message. |
| `errorException` | `any` | In case of an error, this property contains the related exception object (if any). |
| `matchedTargetingRule` | `TargetingRule` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matchedPercentageOption` | `PercentageOption` | The Percentage Option (if any) that was used to select the evaluated value. |
| `fetchTime` | `Date` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
For simple targeting:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
```
```js
const userObject = { identifier: 'john@example.com' };
```
| Parameters | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any `string` value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
For advanced targeting:
```js
const userObject = {
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
SubscriptionType: 'Pro',
UserRole: 'Admin',
},
};
```
The `custom` dictionary also allows attribute values other than `string` values:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
userObject.custom = {
Rating: 4.5,
RegisteredAt: new Date('2023-11-22T12:34:56.000Z'),
Roles: ['Role1', 'Role2'],
};
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `string` values,
* all other values are automatically converted to `string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `number` values,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `Date` values, which are automatically converted to a second-based Unix timestamp,
* accept `number` values representing a second-based Unix timestamp,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept arrays of `string`,
* accept `string` values containing a valid JSON string which can be deserialized to an array of `string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
It's possible to set a default User Object that will be used on feature flag and setting evaluation. It can be useful when your application has a single user only or rarely switches users.
You can set the default User Object either on SDK initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
defaultUser: { identifier: 'john@example.com' },
},
);
```
...or using the `setDefaultUser()` method of the `configCatClient` object:
```js
configCatClient.setDefaultUser({ identifier: 'john@example.com' });
```
Whenever the evaluation methods like `getValueAsync()`, `getValueDetailsAsync()`, etc. are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
// The default user will be used in the evaluation process.
const value = await configCatClient.getValueAsync('keyOfMyFeatureFlag', false);
```
When a `user` parameter is passed to the evaluation methods, it takes precedence over the default user.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
const otherUser = { identifier: 'brian@example.com' };
// otherUser will be used in the evaluation process.
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag',
false,
otherUser,
);
```
You can also remove the default user by doing the following:
```js
configCatClient.clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValueAsync()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle. [More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `pollIntervalSeconds` option parameter to change the polling interval.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
pollIntervalSeconds: 95,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------------------------------------------------------------------------------------- | ------- |
| `pollIntervalSeconds` | Polling interval in seconds. | 60s |
| `maxInitWaitTimeSeconds` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5s |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `getValueAsync()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValueAsync()` will return the setting value after the cache is updated.
Use `cacheTimeToLiveSeconds` option parameter to set cache lifetime.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.LazyLoad,
{
cacheTimeToLiveSeconds: 600,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------- | ------- |
| `cacheTimeToLiveSeconds` | Cache TTL in seconds. | 60s |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefreshAsync()` is your application's responsibility.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
await configCatClient.forceRefreshAsync();
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
> `getValueAsync()` returns `defaultValue` if the cache is empty. Call `forceRefreshAsync()` to update the cache.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value); // console: "my default value"
await configCatClient.forceRefreshAsync();
value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `clientReady: [cacheState: ClientCacheState]`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after the initial sync with the external cache (if any) completes.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTimeSeconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the `cacheState` argument.
* `configFetched: [result: RefreshResult, isInitiatedByUser: boolean]`: This event is emitted each time the client attempts to refresh the cached config by fetching the latest version from the ConfigCat CDN. It is emitted not only when `ForceRefreshAsync` is called but also when the refresh is initiated by the client automatically. Thus, this event allows you to observe potential network issues that occur under the hood.
* `configChanged: [newConfig: IConfig]`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `flagEvaluated: [evaluationDetails: IEvaluationDetails]`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetailsAsync()`](#anatomy-of-getvaluedetailsasync).
* `clientError: [message: string, exception?: any]`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', function() {
/* handle the event */
}),
},
);
```
...or directly on the `ConfigCatClient` instance:
```js
configCatClient.on('flagEvaluated', function() {
/* handle the event */
});
```
caution
Some events (e.g. `clientReady`, `configChanged` and `clientError`) may be emitted before `getClient` returns. This means you may miss them unless you subscribe on initialization.
However, even if you do, there's another gotcha: it's not safe to use the outer `configCatClient` variable in your event handler because it may not yet be assigned when the handler is called. Instead, you can safely access the client instance via `this.configCatClient` - provided that the event handler is a normal function, not an arrow function.
## Snapshots and synchronous feature flag evaluation[](#snapshots-and-synchronous-feature-flag-evaluation "Direct link to Snapshots and synchronous feature flag evaluation")
On JavaScript platforms, the *ConfigCat* client provides only asynchronous methods for evaluating feature flags and settings because these operations may involve network communication (e.g. downloading config data from the ConfigCat CDN servers), which is necessarily an asynchronous operation in JavaScript.
However, there can be circumstances where synchronous evaluation is preferable, thus, since v8.1.0, the JavaScript SDK provides a way to synchronously evaluate feature flags and settings via *snapshots*.
Using the `snapshot()` method, you can capture the current state of the *ConfigCat* client (including the latest downloaded config data) and use the resulting snapshot object to synchronously evaluate feature flags and settings based on the captured state:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
);
// Wait for the client to initialize.
await configCatClient.waitForReady();
const snapshot = configCatClient.snapshot();
const user = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
for (const key of snapshot.getAllKeys()) {
const value = snapshot.getValue(key, null, user);
console.log(`${key}: ${value}`);
}
```
Creating a snapshot is a cheap operation. This is possible because snapshots capture the client's internal (in-memory) cache. No attempt is made to refresh the internal cache, even if it's empty or expired.
caution
Please note that creating and using a snapshot
* won't trigger a sync with the external cache when working with [shared caching](https://configcat.com/docs/advanced/caching.md#shared-cache),
* won't fetch the latest config data from the ConfigCat CDN when the internally cached config data is empty or expired.
For the above reasons, it's recommended to use snapshots in conjunction with the Auto Polling mode, where the SDK automatically updates the internal cache in the background. (For other polling modes, you'll need to manually initiate a cache refresh by calling `forceRefreshAsync`.)
Because of this behavior, it's important to make sure that the client has completed initialization and populated its internal cache before creating snapshots. Otherwise the snapshot's evaluation methods won't have the data to do actual evaluation, but will just return the default value you pass to them. Which behavior is usually not what you want in your application.
In Auto Polling mode, you can use the `waitForReady` method to wait for the latest config data to become available locally. This is an asynchronous operation, which completes as soon as the client reaches the ready state, i.e. completes initialization (or the time specified via the `maxInitWaitTimeSeconds` option passes).
(Please note that this doesn't apply to other polling modes. In those cases, the client doesn't contact the ConfigCat CDN during initialization, so the ready state is reached as soon as the first sync with the external cache completes.)
Typically, you call `waitForReady` and wait for its completion only once, in the initialization phase of your application.
caution
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the return value.
```js
const clientCacheState = await configCatClient.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
// Handle initialization failure (see below).
console.warn('ConfigCat client failed to obtain the config data during initialization.');
}
```
You have the following options to handle unsuccessful initialization:
* If it's acceptable for your application to start up and use the default values passed to the evaluation methods, you may log some warning (or skip the check altogether as the client will log warnings anyway), and let the application continue.
* Otherwise, you need to either terminate the application or continue waiting. The latter is an option because the client might be able to obtain the config data later, in the case of a transient problem like some temporary network issue. However, the *ConfigCat SDK* doesn't provide out-of-the-box support for this case currently. You can implement this logic by subscribing to the `configChanged` hook and waiting for the first event.
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases where you want to prevent the SDK from making HTTP calls, you can switch it to offline mode:
```js
configCatClient.setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To switch the SDK back to online mode, do the following:
```js
configCatClient.setOnline();
```
Using the `configCatClient.isOffline` property you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a `{ [key: string]: boolean | string | number }` object, from the current query string or from a custom flag override data source.
### Map[](#map "Direct link to Map")
You can specify simple feature flag & setting overrides using a `{ [key: string]: boolean | string | number }` map.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: configcat.createFlagOverridesFromMap(
{
enabledFeature: true,
disabledFeature: false,
intSetting: 5,
doubleSetting: 3.14,
stringSetting: 'test',
},
configcat.OverrideBehaviour.LocalOnly,
),
},
);
```
### Query string[](#query-string "Direct link to Query string")
It is also possible to override feature flags & settings using query string parameters.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: createFlagOverridesFromQueryParams(configcat.OverrideBehaviour.LocalOverRemote, request),
},
);
```
With that setup, you can override feature flags and settings by appending query string parameters to the URL of your application in the following form: `https://app.example.com/?cc-myBooleanFlag=true&cc-myStringSetting=abc&...`
The setting type is automatically inferred from the value. Please pay attention to this behavior. The inferred type of the value must match the type of the feature flag or setting you override (see also [this table](#setting-type-mapping)). In case you want to force a boolean or number value to be interpreted as a string value, use the `;str` suffix: `&cc-myStringSetting;str=true`.
If the default prefix used to differentiate between normal and flag override query string parameters (`cc-`) is not suitable for you, you can set a custom prefix using the corresponding optional parameter of `createFlagOverridesFromQueryParams`.
### Custom data source implementation[](#custom-data-source-implementation "Direct link to Custom data source implementation")
You can create a custom flag override data source by implementing `IOverrideDataSource`.
The SDK provides the `createSettingFromValue` function to create `Setting` objects from simple `boolean`, `string` and `number` values. In case you need complex (full-featured) flag overrides, you can use the `deserializeConfig` function to obtain `Setting` objects from a config JSON conforming to the [config JSON v6 format](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
```ts
class MyCustomOverrideDataSource implements IOverrideDataSource {
private settings: Record;
constructor(configJson: string) {
this.settings = deserializeConfig(configJson).f ?? {};
}
getOverrides(): Record {
return this.settings;
}
}
```
or
```js
function MyCustomOverrideDataSource(configJson) {
this.settings = deserializeConfig(configJson).f ?? {};
}
MyCustomOverrideDataSource.prototype.getOverrides = function () {
return this.settings;
};
```
then
```js
// Set the `MyCustomOverrideDataSource` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: {
dataSource: new MyCustomOverrideDataSource('{ "f": { ... } }'),
behaviour: configcat.OverrideBehaviour.LocalOnly,
}
},
);
```
## Logging[](#logging "Direct link to Logging")
### Setting log levels[](#setting-log-levels "Direct link to Setting log levels")
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: configcat.createConsoleLogger(configcat.LogLevel.Info), // Setting log level to Info
},
);
```
Available log levels:
| Level | Description |
| ----- | ------------------------------------------------------- |
| Off | Nothing gets logged. |
| Error | Only error level events are logged. |
| Warn | Default. Errors and Warnings are logged. |
| Info | Errors, Warnings and feature flag evaluation is logged. |
| Debug | All of the above plus debug info is logged. |
Info level logging helps to inspect the feature flag evaluation process:
```bash
ConfigCat - INFO - [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"#SOME-USER-ID#","Email":"configcat@example.com"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
The SDK provides a simple logger implementation that logs to [the debugging console](https://developer.mozilla.org/en-US/docs/Web/API/console) (`configcat.createConsoleLogger(...)`) but it also allows you to inject any custom implementation of `IConfigCatLogger`.
```ts
class MyCustomLogger implements IConfigCatLogger {
/**
* Writes an event into the log.
* @param level Event severity level.
* @param eventId Event identifier.
* @param message Message.
* @param exception The exception object related to the message (if any).
*/
log(
level: LogLevel,
eventId: LogEventId,
message: LogMessage,
exception?: any,
): void {
// insert your custom log logic
}
}
```
or
```js
function MyCustomLogger() {}
MyCustomLogger.prototype.log = function (level, eventId, message, exception) {
// insert your custom log logic
};
```
then
```js
// Set the `MyCustomLogger` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: new MyCustomLogger(),
},
);
```
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by providing a callback function via the `logFilter` option. The callback will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `IConfigCatLogger.level` property). That is, the callback allows you to filter log events by `level`, `eventId`, `message` or `exception`. The formatted message string can be obtained via `message.toString()`. If the callback function returns `true`, the event will be logged, otherwise it will be skipped.
```js
// Filter out events with id 1001 from the log.
const logFilter = (level, eventId, message, exception) => eventId != 1001;
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{
logFilter: logFilter
}
);
```
caution
Please make sure that your log filter logic doesn't perform heavy computation. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## `getAllKeysAsync()`[](#getallkeysasync "Direct link to getallkeysasync")
You can get the keys for all available feature flags and settings by calling the `getAllKeysAsync()` method.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
const keys = await configCatClient.getAllKeysAsync();
console.log(keys);
```
## `getAllValuesAsync()`[](#getallvaluesasync "Direct link to getallvaluesasync")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValuesAsync();
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValuesAsync(userObject);
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
```
## `getAllValueDetailsAsync()`[](#getallvaluedetailsasync "Direct link to getallvaluedetailsasync")
Evaluates and returns the values along with evaluation details of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValueDetailsAsync();
settingValues.forEach((details) => console.log(details));
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValueDetailsAsync(userObject);
settingValues.forEach((details) => console.log(details));
```
## Using custom cache implementation[](#using-custom-cache-implementation "Direct link to Using custom cache implementation")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) interface and set the `cache` property in the options passed to `getClient`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
```ts
class MyCustomCache implements IConfigCatCache {
set(key: string, value: string): Promise | void {
// insert your cache write logic here
}
get(
key: string,
): Promise | string | null | undefined {
// insert your cache read logic here
}
}
```
or
```js
function MyCustomCache() {}
MyCustomCache.prototype.set = function (key, value) {
// insert your cache write logic here
};
MyCustomCache.prototype.get = function (key) {
// insert your cache read logic here
};
```
then
```js
// Set the `MyCustomCache` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
cache: new MyCustomCache(),
},
);
```
info
The JavaScript SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the *ConfigCat SDK* that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Platform compatibility[](#platform-compatibility "Direct link to Platform compatibility")
The SDK should be compatible with latest versions of [workerd](https://github.com/cloudflare/workerd).
The SDK is [tested](https://github.com/configcat/js-unified-sdk/blob/master/.github/workflows/js-sdk-ci.yml) against the following runtimes:
* Workerd (2023-02-28)
The SDK is compatible with TypeScript v4.0.2 or newer. Earlier versions may work but those are not tested, thus, not supported officially.
These tests are running on each pull request, before each deploy, and on a daily basis.
You can view a sample run [here](https://github.com/configcat/js-unified-sdk/actions/runs/11745259578).
## Best practices[](#best-practices "Direct link to Best practices")
### Choosing polling mode for serverless functions[](#choosing-polling-mode-for-serverless-functions "Direct link to Choosing polling mode for serverless functions")
Auto polling is not ideal for short-lived serverless functions like Cloudflare Workers.
It is recommended to use the SDK in Lazy loading or Manual polling mode instead of the default Auto polling mode.
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
* [Sample Cloudflare Worker](https://github.com/configcat/js-unified-sdk/tree/master/samples/cloudflare-worker)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
* [ConfigCat SDK for JavaScript in NPM](https://www.npmjs.com/package/@configcat/sdk)
---
# Source: https://configcat.com/docs/advanced/team-management/saml/identity-providers/cloudflare.md
# Cloudflare Zero Trust
Copy page
Connect ConfigCat with Cloudflare Zero Trust via SAML.
## Introduction[](#introduction "Direct link to Introduction")
Each SSO Identity Provider requires specific information to configure a SAML integration. The following guide will walk you through how you can connect ConfigCat with Cloudflare Zero Trust as a SAML Identity Provider.
## 1. Create an Application in Cloudflare[](#1-create-an-application-in-cloudflare "Direct link to 1. Create an Application in Cloudflare")
* Log in to [CloudFlare](https://dash.cloudflare.com/), go to the Zero Trust Dashboard, and select `Applications` under the `Access` menu.
Then click on `Add an application`.

* Select `SaaS`.

* Enter a descriptive name in the `Application` field.

The next step will guide you on how to collect the information required for the appearing configuration section.
## 2. Configure SAML for the Cloudflare Application[](#2-configure-saml-for-the-cloudflare-application "Direct link to 2. Configure SAML for the Cloudflare Application")
* Open your organization's authentication settings on the [ConfigCat Dashboard](https://app.configcat.com/organization/authentication).

* Click `ADD SAML IDENTITY PROVIDER`.

* Give a name for your Identity Provider, and click `Create`.

* From the next section of the dialog, copy the following values and paste them into the Cloudflare application.
* `Entity ID` -> `Entity ID`
* `Assertion Consumer Service` -> `Assertion Consumer Service URL`
 
* Set the `Name ID Format` to `Email`.

* Click `Next` at the bottom of the page.
## 3. Configure policies for the Cloudflare Application[](#3-configure-policies-for-the-cloudflare-application "Direct link to 3. Configure policies for the Cloudflare Application")
To let users authenticate via SAML, you need to assign groups to the Cloudflare application.
* Give a name for the Cloudflare Application's policy and check those groups that you want to assign.

* Click `Next` at the bottom of the page.
## 4. Configure ConfigCat with SAML Details from Cloudflare[](#4-configure-configcat-with-saml-details-from-cloudflare "Direct link to 4. Configure ConfigCat with SAML Details from Cloudflare")
* Copy the value of `SSO endpoint` and `Public key` fields.

* On the ConfigCat Dashboard, select the `3. Set up ConfigCat` step, click `Manual Configuration`, then paste the copied values into the appearing fields.
* `SSO endpoint` -> `Sign-on URL`
* `Public key` -> `X.509 Certificate`

## 5. Select Trusted Domains on the SAML Configuration Dialog[](#5-select-trusted-domains-on-the-saml-configuration-dialog "Direct link to 5. Select Trusted Domains on the SAML Configuration Dialog")
* Only user accounts from trusted domains can login with SAML SSO. You can bind multiple verified domains to a SAML Identity Provider.

* Click `Save`.
## 5. Sign In[](#5-sign-in "Direct link to 5. Sign In")
* Go to the [ConfigCat Log In](https://app.configcat.com) page, and click `COMPANY ACCOUNT - SAML`.

* Sign in with your company email address assigned to the Cloudflare application.

* ConfigCat will redirect you to Cloudflare's sign in page.

## 6. Next Steps[](#6-next-steps "Direct link to 6. Next Steps")
* Configure the [auto-assignment of users](https://configcat.com/docs/advanced/team-management/auto-assign-users.md).
---
# Source: https://configcat.com/docs/api/reference/code-references.md
# Code References
Copy page
With this endpoint you can upload Feature Flag and Setting usage references that will be shown on the ConfigCat Dashboard.
[Here](https://configcat.com/docs/advanced/code-references/overview.md) you can read more about the concept of Code References.
## [📄️ Get References for Feature Flag or Setting](https://configcat.com/docs/api/reference/get-references-for-feature-flag-or-setting.md)
## [📄️ Delete Reference reports](https://configcat.com/docs/api/reference/delete-reference-reports.md)
## [📄️ Upload References](https://configcat.com/docs/api/reference/upload-references.md)
---
# Source: https://configcat.com/docs/advanced/config-v2-migration-guide.md
# Config V2 Migration Guide
Copy page
This guide will help you migrate from Config V1 to Config V2.
## What is Config V2?[](#what-is-config-v2 "Direct link to What is Config V2?")
**Config V2 is the next generation of ConfigCat.** It comes with a new Dashboard, Public Management API and SDKs.
**Config V2 supports all the features of V1**, so you can continue using those, but **it offers interesting new features as well**. However, you won't be able to use the new features with the V1 versions of the Dashboard, Public Management API and SDKs.
Read more about the new features in the [Config V2 Overview](https://configcat.com/docs/advanced/config-v2.md).
## A few things to consider before migration[](#a-few-things-to-consider-before-migration "Direct link to A few things to consider before migration")
* **Migration from Config V1 means that a V2 config will be copied from the V1 config. The V1 config will remain unchanged and accessible.** The V2 version will have a new SDK key for each environment.
* **Config V2 and V1 are completely separate.** They don't affect each other in any way. You can use them side by side.
* **There is no automatic sync between the V1 and V2 configs.** If you want to keep them in sync, you have to manually update the V2 config when you make changes to the V1 config and vice versa.
* There is no pressure to migrate. Although we have plans to phase out V1 eventually, you can stay on it for a long time.
* Once the migration process is started, it's recommended to migrate your V1 configs to V2 as quickly as possible to avoid confusion.
* Keep in mind that the [integrations](https://app.configcat.com/integrations) and [webhooks](https://app.configcat.com/product/webhooks) connected to V1 configs are not migrated automatically and you have to set them up manually for the migrated V2 configs.
* Every newly created config will be a V2 config by default.
## Migrating from Config V1 to Config V2[](#migrating-from-config-v1-to-config-v2 "Direct link to Migrating from Config V1 to Config V2")
The migration process starts with copying your V1 config to a new V2 one and updating your applications to use the new config. The complete process is the following:
### Step 1: Create the V2 config[](#step-1-create-the-v2-config "Direct link to Step 1: Create the V2 config")
1. Open the ConfigCat Dashboard and click on the `Start migration` button on top of a V1 config.
2. Click `Create V2 config` to create a new config with the same settings as the V1 config.
It's important to note that the V2 config will be created with the same settings as the V1 config and the V1 config will still be accessible and unchanged.
### Step 2: Upgrade the ConfigCat SDK version[](#step-2-upgrade-the-configcat-sdk-version "Direct link to Step 2: Upgrade the ConfigCat SDK version")
In your application, upgrade the ConfigCat SDK to the latest version. Old versions of the SDK will not be able to access the new config. Make sure you upgrade every application that uses the migrated V2 config.
Here is a list of the SDKs that support Config V2: [See the supported SDK versions.](https://configcat.com/docs/advanced/config-v2-sdk-compatibility.md)
### Step 3: Update the ConfigCat SDK Key[](#step-3-update-the-configcat-sdk-key "Direct link to Step 3: Update the ConfigCat SDK Key")
In your application, replace the old ConfigCat SDK Key with the new one (i.e. with the one that belongs to the V2 version of the config) in every environment. The new key can be found on the ConfigCat Dashboard on the V2 config's page.
### Step 4: Deploy your application[](#step-4-deploy-your-application "Direct link to Step 4: Deploy your application")
Deploy your application to production and wait until all your users upgrade to the new version. You can check the migration status on the ConfigCat Dashboard under the migration status page that is available from a config's context menu in the sidebar.
### Step 5: Clean up[](#step-5-clean-up "Direct link to Step 5: Clean up")
After confirming that all your users have transitioned to the latest version of your application, you can finalize the migration by removing the V1 config.
To verify that the V1 configs haven't been accessed for a significant period, check the migration status page accessible via a config's context menu in the sidebar. This step helps eliminate any mix-ups and prevents the unintended use of outdated configurations.
caution
Once you delete the V1 config, you won't be able to restore it.
---
# Source: https://configcat.com/docs/advanced/config-v2-sdk-compatibility.md
# Config V2 SDK Compatibility
Copy page
This table shows which SDK versions support Config V2. Read more about [Config V2](https://configcat.com/docs/advanced/config-v2.md)
| SDK | Version | Release Notes |
| ------------------------------------------------------------------------------- | ---------- | ----------------------------------------------------------------- |
| .NET | >= v9.1.0 | |
| Android (Java) | >= v10.1.0 | |
| C++ | >= v4.0.0 | |
| Dart (Flutter) | >= v4.1.0 | |
| Elixir | >= v4.0.0 | |
| Go | >= v9.0.3 | |
| Java | >= v9.1.0 | |
| JavaScript (Browser, Bun, Chromium Extension, Cloudflare Worker, Deno, Node.js) | >= v1.0.0 | |
| JavaScript - Legacy | >= v9.5.0 | |
| JavaScript (Chromium Extension) - Legacy | >= v2.4.0 | |
| JavaScript (SSR) - Legacy | >= v8.4.0 | |
| Kotlin Multiplatform | >= v3.0.0 | |
| Node.js - Legacy | >= v11.3.0 | |
| PHP 8.1+ | >= v9.1.0 | |
| PHP 7.1+ | >= v3.0.0 | |
| Python | >= v9.0.3 | |
| React | >= v4.6.0 | |
| Ruby | >= v8.0.0 | |
| Rust | >= v0.1.0 | |
| Swift (iOS) | >= v11.0.0 | |
| Unreal Engine | >= v2.0.0 | |
---
# Source: https://configcat.com/docs/advanced/config-v2.md
# Config V2 Overview
Copy page
Config V2 is a new version of ConfigCat. It comes with a new Dashboard, Public Management API, SDKs, and features.
## What's new?[](#whats-new "Direct link to What's new?")
* A bunch of new features and improvements listed below.
* New config editor UI on the Dashboard.
* [New and improved config JSON schema.](https://github.com/configcat/config-json)
* New API: [See the API Docs.](https://configcat.com/docs/api/reference/configcat-public-management-api.md)
* New SDKs: [See the supported SDK versions.](https://configcat.com/docs/advanced/config-v2-sdk-compatibility.md)
## How to migrate from Config V1 to Config V2?[](#how-to-migrate-from-config-v1-to-config-v2 "Direct link to How to migrate from Config V1 to Config V2?")
See the [Config V2 Migration Guide](https://configcat.com/docs/advanced/config-v2-migration-guide.md). If you get stuck or have any questions about the migration, feel free to [contact us](https://configcat.com/support/).
## New features[](#new-features "Direct link to New features")
### AND conditions[](#and-conditions "Direct link to AND conditions")
With AND conditions, you can define more complex Targeting Rules, such as "serve this value for the users who use my Android app AND whose email domain is '@example.com'".
You can add multiple conditions to a Targeting Rule and they will be evaluated with an AND connection between them.

### New comparators[](#new-comparators "Direct link to New comparators")
With the new comparators, you can create Targeting Rules based on date comparisons, array comparisons, and more.
* New text and confidential text comparators: `EQUALS`, `NOT EQUALS`, `STARTS WITH ANY OF`, `ENDS WITH ANY OF`, `NOT STARTS WITH ANY OF`, `NOT ENDS WITH ANY OF`.
* New array comparators: `ARRAY CONTAINS ANY OF`, `ARRAY NOT CONTAINS ANY OF`.
* New date comparators: `BEFORE`, `AFTER`.

### Prerequisite flags[](#prerequisite-flags "Direct link to Prerequisite flags")
With prerequisite flags, you can create feature flags that depend on other feature flags. Prerequisite feature flags (aka. master feature flag, inter-dependent feature flag, global toggle) are particularly useful for managing complex feature dependencies and ensuring a smooth user experience during feature rollouts.

### Comparison value hints[](#comparison-value-hints "Direct link to Comparison value hints")
With comparison value hints, you can associate arbitrary text with your comparison values. This way you can add a description to your comparison value list items that helps you remember what they are for.
### Percentage Options within Targeting Rules[](#percentage-options-within-targeting-rules "Direct link to Percentage Options within Targeting Rules")
You can add Percentage Options to your Targeting Rules. This is useful if you want to create more complex Targeting Rules, such as "turn on the feature for 20% of the users who are on iOS, and off for 80%".

### Custom Percentage Attributes[](#custom-percentage-attributes "Direct link to Custom Percentage Attributes")
With custom Percentage Attributes, you can create Percentage Options based on custom attributes. This way you can create Percentage Options based on any of your user attributes. For example, you can create a Percentage Option that is based on the user's company or organization. So you can serve a value for 20% of the users from company A and serve another value for 80% of the users from company B.

---
# Source: https://configcat.com/docs/api/reference/configcat-public-management-api.md
Version: v1
# ConfigCat Public Management API
Copy page
The purpose of this API is to access the ConfigCat platform programmatically. You can **Create**, **Read**, **Update** and **Delete** any entities like **Feature Flags, Configs, Environments** or **Products** within ConfigCat.
**Base API URL**:
If you prefer the swagger documentation, you can find it here: [Swagger UI](https://api.configcat.com/swagger).
The API is based on HTTP REST, uses resource-oriented URLs, status codes and supports JSON format.
**Important:** Do not use this API for accessing and evaluating feature flag values. Use the [SDKs](https://configcat.com/docs/sdk-reference/overview.md) or the [ConfigCat Proxy](https://configcat.com/docs/advanced/proxy/proxy-overview.md) instead.
## OpenAPI Specification[](#openapi-specification "Direct link to OpenAPI Specification")
The complete specification is publicly available in the following formats:
* [OpenAPI v3](https://api.configcat.com/docs/v1/swagger.json)
* [Swagger v2](https://api.configcat.com/docs/v1/swagger.v2.json)
You can use it to generate client libraries in various languages with [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) or [Swagger Codegen](https://swagger.io/tools/swagger-codegen/) to interact with this API.
## Throttling and rate limits[](#throttling-and-rate-limits "Direct link to Throttling and rate limits")
All the rate limited API calls are returning information about the current rate limit period in the following HTTP headers:
| Header | Description |
| ---------------------- | -------------------------------------------------------------------------- |
| X-Rate-Limit-Remaining | The maximum number of requests remaining in the current rate limit period. |
| X-Rate-Limit-Reset | The time when the current rate limit period resets. |
When the rate limit is exceeded by a request, the API returns with a `HTTP 429 - Too many requests` status along with a `Retry-After` HTTP header.
## Authentication[](#authentication "Direct link to Authentication")
* HTTP: Basic Auth
To authenticate with the API you have to fill the `Authorization` HTTP request header with your Public API credentials.
You can create your credentials on the [Public API credentials management page](https://app.configcat.com/my-account/public-api-credentials).
| Security Scheme Type: | http |
| -------------------------- | ----- |
| HTTP Authorization Scheme: | basic |
### Contact
ConfigCat:
URL:
### Terms of Service
---
# Source: https://configcat.com/docs/api/scim/configcat-user-provisioning-scim-api.md
Version: v1
# ConfigCat User Provisioning (SCIM) API
Copy page
The purpose of this API is to allow user and group synchronization from your Identity Provider into a ConfigCat Organization via the SCIM protocol.
[Here](https://configcat.com/docs/advanced/team-management/scim/scim-overview/) you can read more about the user provisioning process.
**Base API URL**: `https://scim-api.configcat.com`
## OpenAPI Specification[](#openapi-specification "Direct link to OpenAPI Specification")
The complete specification is publicly available in the following formats:
* [OpenAPI v3](https://scim-api.configcat.com/openapi/v1/openapi.json)
## Throttling and rate limits[](#throttling-and-rate-limits "Direct link to Throttling and rate limits")
All the rate limited API calls are returning information about the current rate limit period in the following HTTP headers:
| Header | Description |
| ---------------------- | -------------------------------------------------------------------------- |
| X-Rate-Limit-Remaining | The maximum number of requests remaining in the current rate limit period. |
| X-Rate-Limit-Reset | The time when the current rate limit period resets. |
When the rate limit is exceeded by a request, the API returns with a `HTTP 429 - Too many requests` status along with a `Retry-After` HTTP header.
## Authentication[](#authentication "Direct link to Authentication")
* HTTP: Bearer Auth
To authenticate with the API you have to fill the `Authorization` HTTP request header with your SCIM token.
You can retrieve your credentials on the [Authentication & Provisioning page](https://app.configcat.com/organization/authentication). Example: `Bearer 12345abcdef`
| Security Scheme Type: | http |
| -------------------------- | ------ |
| HTTP Authorization Scheme: | bearer |
### Contact
ConfigCat:
URL:
### Terms of Service
---
# Source: https://configcat.com/docs/api/reference/configs.md
# Configs
Copy page
With these endpoints you can manage your Configs. This also can be used to manage [Feature Flags and Settings](https://configcat.com/docs/api/reference/feature-flags-settings.md) and their [served values](https://configcat.com/docs/api/reference/feature-flag-setting-values.md) through this API.
[Here](https://configcat.com/docs/main-concepts.md#config) you can read more about the concept of Configs.
## [📄️ List Configs](https://configcat.com/docs/api/reference/get-configs.md)
[This endpoint returns the list of the Configs that belongs to the given Product identified by the](https://configcat.com/docs/api/reference/get-configs.md)
## [📄️ Create Config](https://configcat.com/docs/api/reference/create-config.md)
[This endpoint creates a new Config in a specified Product](https://configcat.com/docs/api/reference/create-config.md)
## [📄️ Get Config](https://configcat.com/docs/api/reference/get-config.md)
[This endpoint returns the metadata of a Config](https://configcat.com/docs/api/reference/get-config.md)
## [📄️ Update Config](https://configcat.com/docs/api/reference/update-config.md)
[This endpoint updates a Config identified by the \`configId\` parameter.](https://configcat.com/docs/api/reference/update-config.md)
## [📄️ Delete Config](https://configcat.com/docs/api/reference/delete-config.md)
[This endpoint removes a Config identified by the \`configId\` parameter.](https://configcat.com/docs/api/reference/delete-config.md)
---
# Source: https://configcat.com/docs/glossary/continuous-integration.md
# Continuous Integration - The Backbone of Modern Software Development
Copy page
## Introduction[](#introduction "Direct link to Introduction")
In the rapidly evolving landscape of software development, Continuous Integration (CI) has emerged as an essential practice. It represents a fundamental shift in the approach to software building and testing, emphasizing speed, efficiency, and early error detection. Here, we explore the ins and outs of Continuous Integration and its pivotal role in modern software development.
## What is Continuous Integration?[](#what-is-continuous-integration "Direct link to What is Continuous Integration?")
Continuous Integration is a development practice where developers frequently merge their code changes into a central repository, usually several times a day. After each merge, automated builds and tests are run, ensuring that the new code integrates seamlessly with the existing codebase.
## The Objectives of Continuous Integration[](#the-objectives-of-continuous-integration "Direct link to The Objectives of Continuous Integration")
* **Early Problem Detection**: Identifying and resolving issues promptly, reducing the risk of compounded problems.
* **Streamlined Development**: Facilitating smoother collaboration and integration among team members.
* **Quality Assurance**: Maintaining a high standard of code quality through automated testing.
* **Reduced Integration Costs**: Lowering the time and resources spent on fixing integration issues.
## The Continuous Integration Process[](#the-continuous-integration-process "Direct link to The Continuous Integration Process")
* **Commit Code Regularly**: Developers regularly commit small code changes to the central repository.
* **Automated Builds**: Automated systems build the software with each new code commit.
* **Automated Testing**: Running a suite of tests to ensure code quality and functionality.
* **Immediate Feedback**: Providing developers with immediate feedback on the integration process.
* **Rapid Issue Resolution**: Quickly addressing any integration or test failures.
## Why Continuous Integration is Essential[](#why-continuous-integration-is-essential "Direct link to Why Continuous Integration is Essential")
* **Improved Collaboration**: Encourages more frequent code integration, leading to better team collaboration.
* **Increased Efficiency**: Reduces manual integration efforts, making the development process more efficient.
* **Enhanced Code Quality**: Consistent testing ensures high code quality and reduces bugs in production.
* **Faster Release Cycles**: Accelerates the process from development to deployment, enabling faster release cycles.
## Challenges in Continuous Integration and Solutions[](#challenges-in-continuous-integration-and-solutions "Direct link to Challenges in Continuous Integration and Solutions")
* **Maintaining Quality with Speed**: Balancing rapid integration with maintaining code quality. Solution: Implement robust automated testing frameworks.
* **Managing Build Failures**: Addressing and preventing frequent build failures. Solution: Enforce coding standards and regular code reviews.
* **Infrastructure Overheads**: Managing the infrastructure required for CI. Solution: Use cloud-based CI tools and services.
## Conclusion[](#conclusion "Direct link to Conclusion")
Continuous Integration stands as a transformative approach in software development. By automating the integration and testing process, it not only enhances efficiency and quality but also fosters a more collaborative and agile development environment. Embracing Continuous Integration is not just a choice but a necessity for teams aiming to excel in the competitive world of software development.
---
# Source: https://configcat.com/docs/sdk-reference/cpp.md
# C++ SDK Reference
Copy page
[](https://github.com/configcat/cpp-sdk/stargazers) [](https://github.com/configcat/cpp-sdk/actions/workflows/cpp-ci.yml) [](https://codecov.io/gh/configcat/cpp-sdk)
[ConfigCat C++ SDK on GitHub](https://github.com/configcat/cpp-sdk)
## Getting Started[](#getting-started "Direct link to Getting Started")
### 1. Add the ConfigCat SDK to your project[](#1-add-the-configcat-sdk-to-your-project "Direct link to 1. Add the ConfigCat SDK to your project")
With **[Vcpkg](https://github.com/microsoft/vcpkg)**
* On Windows:
```cmd
git clone https://github.com/microsoft/vcpkg
.\vcpkg\bootstrap-vcpkg.bat
.\vcpkg\vcpkg install configcat
```
In order to use vcpkg with Visual Studio, run the following command (may require administrator elevation):
```cmd
.\vcpkg\vcpkg integrate install
```
After this, you can create a New non-CMake Project (or open an existing one). All installed libraries are immediately ready to be `#include`d and used in your project without additional setup.
* On Linux/Mac:
```bash
git clone https://github.com/microsoft/vcpkg
./vcpkg/bootstrap-vcpkg.sh
./vcpkg/vcpkg install configcat
```
### 2. Include *configcat.h* header in your application code[](#2-include-configcath-header-in-your-application-code "Direct link to 2-include-configcath-header-in-your-application-code")
```cpp
#include
using namespace configcat;
```
### 3. Create the *ConfigCat* client with your *SDK Key*[](#3-create-the-configcat-client-with-your-sdk-key "Direct link to 3-create-the-configcat-client-with-your-sdk-key")
```cpp
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#");
```
### 4. Get your setting value[](#4-get-your-setting-value "Direct link to 4. Get your setting value")
```cpp
bool isMyAwesomeFeatureEnabled = client->getValue("isMyAwesomeFeatureEnabled", false);
if (isMyAwesomeFeatureEnabled) {
doTheNewThing();
} else {
doTheOldThing();
}
```
### 5. Close *ConfigCat* client[](#5-close-configcat-client "Direct link to 5-close-configcat-client")
You can safely shut down all clients at once or individually and release all associated resources on application exit.
```cpp
ConfigCatClient::closeAll(); // closes all clients
ConfigCatClient::close(client); // closes a specific client
```
## Setting up the *ConfigCat Client*[](#setting-up-the-configcat-client "Direct link to setting-up-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`ConfigCatClient::get("#YOUR-SDK-KEY#")` returns a client with default options.
| Properties | Description |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `baseUrl` | Optional, sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. |
| `dataGovernance` | Optional, defaults to `Global`. Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `Global`, `EuOnly`. |
| `connectTimeoutMs` | Optional, defaults to `8000ms`. Sets the amount of milliseconds to wait for the server to make the initial connection (i.e. completing the TCP connection handshake). `0` means it never times out during transfer |
| `readTimeoutMs` | Optional, defaults to `5000ms`. Sets the amount of milliseconds to wait for the server to respond before giving up. `0` means it never times out during transfer. |
| `pollingMode` | Optional, sets the polling mode for the client. [More about polling modes](#polling-modes). |
| `configCache` | Optional, sets a custom cache implementation for the client. [More about cache](#custom-cache). |
| `logger` | Optional, sets the internal logger and log level. [More about logging](#logging). |
| `flagOverrides` | Optional, sets the local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). |
| `defaultUser` | Optional, sets the default user. [More about default user](#default-user). |
| `offline` | Optional, defaults to `false`. Indicates whether the SDK should be initialized in offline mode. [More about offline mode](#online--offline-mode). |
| `hooks` | Optional, used to subscribe events that the SDK sends in specific scenarios. [More about hooks](#hooks). |
```cpp
ConfigCatOptions options;
options.pollingMode = PollingMode::manualPoll();
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
caution
We strongly recommend you to use the `ConfigCatClient` as a Singleton object in your application. The `ConfigCatClient` constructs singleton client instances for your SDK keys with its `ConfigCatClient::get()` static factory method. These clients can be closed all at once with `ConfigCatClient::closeAll()` method or individually with the `ConfigCatClient::close(client)`.
## Anatomy of `getValue()`[](#anatomy-of-getvalue "Direct link to anatomy-of-getvalue")
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```cpp
auto user = ConfigCatUser::create("#USER-IDENTIFIER#");
auto value = client->getValue(
"keyOfMySetting", // key
false, // defaultValue
user, // Optional User Object
);
```
caution
It is important to choose the correct `getValue` overload, where the type of the `defaultValue` parameter matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | Type of `defaultValue` |
| -------------- | ----------------------------- |
| On/Off Toggle | `bool` |
| Text | `std::string` / `const char*` |
| Whole Number | `int32_t` |
| Decimal Number | `double` |
In addition to the overloads mentioned above, you also have the option to choose an overload that doesn't expect a default value. In that case any setting kind is allowed, and in case of error, the return value will be `std::nullopt`.
If you specify a default value whose type mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
## Anatomy of `getValueDetails()`[](#anatomy-of-getvaluedetails "Direct link to anatomy-of-getvaluedetails")
`getValueDetails()` is similar to `getValue()` but instead of returning the evaluated value only, it gives more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```cpp
auto user = ConfigCatUser::create("#USER-IDENTIFIER#");
auto details = client->getValueDetails(
"keyOfMySetting", // key
false, // defaultValue
user, // Optional User Object
);
```
caution
It is important to choose the correct `getValueDetails` overload, where the type of the `defaultValue` parameter matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ----------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `value` | `std::optional` | The evaluated value of the feature flag or setting. |
| `key` | `std::string` | The key of the evaluated feature flag or setting. |
| `isDefaultValue` | `bool` | True when the default value passed to `getValueDetails()` is returned due to an error. |
| `errorMessage` | `std::optional` | In case of an error, this field contains the error message. |
| `errorException` | `std::exception_ptr` | In case of an error, this property contains the related exception object (if any). |
| `user` | `std::shared_ptr` | The User Object that was used for evaluation. |
| `matchedTargetingRule` | `std::optional` | The targeting rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matchedPercentageRule` | `std::optional` | The percentage option (if any) that was used to select the evaluated value. |
| `fetchTime` | `std::chrono::time_point` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
```cpp
auto user = ConfigCatUser::create("#UNIQUE-USER-IDENTIFIER#");
```
```cpp
auto user = ConfigCatUser::create("john@example.com");
```
### Customized User Object creation[](#customized-user-object-creation "Direct link to Customized User Object creation")
| Argument | Description |
| --------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `id` | **REQUIRED.** Unique identifier of a user in your application. Can be any value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. e.g. User role, Subscription type. |
```cpp
auto user = ConfigCatUser::create(
"#UNIQUE-USER-IDENTIFIER#", // userID
"john@example.com", // email
"United Kingdom", // country
{
{ "SubscriptionType", "Pro" },
{ "UserRole", "Admin" }
} // custom
);
```
The `custom` dictionary also allows attribute values other than `std::string` values:
```cpp
auto user = ConfigCatUser::create(
"#UNIQUE-USER-IDENTIFIER#", // userID
"john@example.com", // email
"United Kingdom", // country
{
{ "Rating", 4.5 },
{ "RegisteredAt", make_datetime(2023, 11, 22, 12, 34, 56) },
{ "Roles", std::vector{"Role1", "Role2"} }
} // custom
)
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `std::string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS\_ONE\_OF, etc.)
* accept `std::string` values,
* all other values are automatically converted to `std::string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS\_ONE\_OF\_SEMVER, LESS\_THAN\_SEMVER, GREATER\_THAN\_SEMVER, etc.)
* accept `std::string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (EQUALS\_NUMBER, LESS\_THAN\_NUMBER, GREATER\_THAN\_OR\_EQUAL\_NUMBER, etc.)
* accept `double` values and all other numeric values which can safely be converted to `double`,
* accept `std::string` values containing a properly formatted, valid `double` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE\_DATETIME / AFTER\_DATETIME)
* accept `configcat::date_time_t` (`std::chrono::system_clock::time_point`) values, which are automatically converted to a second-based Unix timestamp,
* accept `double` values representing a second-based Unix timestamp and all other numeric values which can safely be converted to `double`,
* accept `std::string` values containing a properly formatted, valid `double` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY\_CONTAINS\_ANY\_OF / ARRAY\_NOT\_CONTAINS\_ANY\_OF)
* accept lists of `std::string` (i.e. `std::vector`),
* accept `std::string` values containing a valid JSON string which can be deserialized to an array of `std::string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
There's an option to set a default User Object that will be used at feature flag and setting evaluation. It can be useful when your application has a single user only, or rarely switches users.
You can set the default User Object either on SDK initialization:
```cpp
ConfigCatOptions options;
options.defaultUser = ConfigCatUser::create("john@example.com");
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
or with the `setDefaultUser()` method of the ConfigCat client.
```cpp
client->setDefaultUser(ConfigCatUser::create("john@example.com"));
```
Whenever the `getValue()`, `getValueDetails()`, `getAllValues()`, or `getAllValueDetails()` methods are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```cpp
auto user = ConfigCatUser::create("john@example.com");
client->setDefaultUser(user);
// The default user will be used at the evaluation process.
auto value = client->getValue("keyOfMySetting", false);
```
When the `user` parameter is specified on the requesting method, it takes precedence over the default user.
```cpp
auto user = ConfigCatUser::create("john@example.com");
client->setDefaultUser(user);
auto otherUser = ConfigCatUser::create("brian@example.com");
// otherUser will be used at the evaluation process.
auto value = client->getValue("keyOfMySetting", false, otherUser.get());
```
For deleting the default user, you can do the following:
```cpp
client->clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValue()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle.
[More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `autoPollIntervalInSeconds` option parameter of the `PollingMode::autoPoll()` to change the polling interval.
```cpp
auto autoPollIntervalInSeconds = 100;
ConfigCatOptions options;
options.pollingMode = PollingMode::autoPoll(autoPollIntervalInSeconds);
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
Available options:
| Option Parameter | Description | Default |
| --------------------------- | --------------------------------------------------------------------------------------------------- | ------- |
| `autoPollIntervalInSeconds` | Polling interval. | 60 |
| `maxInitWaitTimeInSeconds` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5 |
### Lazy Loading[](#lazy-loading "Direct link to Lazy Loading")
When calling `getValue()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValue()` will return the setting value after the cache is updated.
Use the `cacheRefreshIntervalInSeconds` option parameter of the `PollingMode::lazyLoad()` to set cache lifetime.
```cpp
auto cacheRefreshIntervalInSeconds = 100;
ConfigCatOptions options;
options.pollingMode = PollingMode::lazyLoad(cacheRefreshIntervalInSeconds);
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
Available options:
| Parameter | Description | Default |
| ------------------------------- | ----------- | ------- |
| `cacheRefreshIntervalInSeconds` | Cache TTL. | 60 |
### Manual Polling[](#manual-polling "Direct link to Manual Polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefresh()` is your application's responsibility.
```cpp
ConfigCatOptions options;
options.pollingMode = PollingMode::manualPoll();
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
client->forceRefresh();
```
> `getValue()` returns `defaultValue` if the cache is empty. Call `forceRefresh()` to update the cache.
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `onClientReady()`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after instantiation.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTimeInSeconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. Alternatively, in Auto Polling mode, you can wait for the first `onConfigChanged` event to be notified when the internal cache is actually populated with config data.
* `onConfigChanged(std::shared_ptr)`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `onFlagEvaluated(const EvaluationDetailsBase&)`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetails()`](#anatomy-of-getvaluedetails).
* `onError(const std::string&, const std::exception_ptr&)`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on SDK initialization:
```cpp
ConfigCatOptions options;
options.pollingMode = PollingMode::manualPoll();
options.hooks = std::make_shared(
[]() { /* onClientReady callback */ },
[](std::shared_ptr config) { /* onConfigChanged callback */ },
[](const EvaluationDetailsBase& details) { /* onFlagEvaluated callback */ },
[](const std::string& error, const std::exception_ptr& exception) { /* onError callback */ }
);
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
or with the `getHooks()` method of the ConfigCat client:
```cpp
client->getHooks->addOnFlagEvaluated([](const EvaluationDetailsBase& details) { /* onFlagEvaluated callback */ });
```
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases when you'd want to prevent the SDK from making HTTP calls, you can put it in offline mode:
```cpp
client->setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To put the SDK back in online mode, you can do the following:
```cpp
client->setOnline();
```
> With `client->isOffline()` you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour::LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour::LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour::RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a file or a map.
### JSON File[](#json-file "Direct link to JSON File")
The SDK can be set up to load your feature flag & setting overrides from a file.
#### File[](#file "Direct link to File")
```cpp
ConfigCatOptions options;
options.flagOverrides = std::make_shared("path/to/the/local_flags.json", LocalOnly);
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
#### JSON File Structure[](#json-file-structure "Direct link to JSON File Structure")
The SDK supports 2 types of JSON structures to describe feature flags & settings.
##### 1. Simple (key-value) structure[](#1-simple-key-value-structure "Direct link to 1. Simple (key-value) structure")
```json
{
"flags": {
"enabledFeature": true,
"disabledFeature": false,
"intSetting": 5,
"doubleSetting": 3.14,
"stringSetting": "test"
}
}
```
##### 2. Complex (full-featured) structure[](#2-complex-full-featured-structure "Direct link to 2. Complex (full-featured) structure")
This is the same format that the SDK downloads from the ConfigCat CDN. It allows the usage of all features that are available on the ConfigCat Dashboard.
You can download your current config JSON from ConfigCat's CDN and use it as a baseline.
A convenient way to get the config JSON for a specific SDK Key is to install the [ConfigCat CLI](https://github.com/configcat/cli) tool and execute the following command:
```bash
configcat config-json get -f v6 -p {YOUR-SDK-KEY} > config.json
```
(Depending on your [Data Governance](https://configcat.com/docs/advanced/data-governance.md) settings, you may need to add the `--eu` switch.)
Alternatively, you can download the config JSON manually, based on your [Data Governance](https://configcat.com/docs/advanced/data-governance.md) settings:
* GLOBAL: `https://cdn-global.configcat.com/configuration-files/{YOUR-SDK-KEY}/config_v6.json`
* EU: `https://cdn-eu.configcat.com/configuration-files/{YOUR-SDK-KEY}/config_v6.json`
```json
{
"p": {
// hash salt, required only when confidential text comparator(s) are used
"s": "80xCU/SlDz1lCiWFaxIBjyJeJecWjq46T4eu6GtozkM="
},
"s": [ // array of segments
{
"n": "Beta Users", // segment name
"r": [ // array of User Conditions (there is a logical AND relation between the elements)
{
"a": "Email", // comparison attribute
"c": 0, // comparator (see below)
"l": [ // comparison value (see below)
"john@example.com", "jane@example.com"
]
}
]
}
],
"f": { // key-value map of feature flags & settings
"isFeatureEnabled": { // key of a particular flag / setting
"t": 0, // setting type, possible values:
// 0 -> on/off setting (feature flag)
// 1 -> text setting
// 2 -> whole number setting
// 3 -> decimal number setting
"r": [ // array of Targeting Rules (there is a logical OR relation between the elements)
{
"c": [ // array of conditions (there is a logical AND relation between the elements)
{
"u": { // User Condition
"a": "Email", // comparison attribute
"c": 2, // comparator, possible values and required comparison value types:
// 0 -> IS ONE OF (cleartext) + string array comparison value ("l")
// 1 -> IS NOT ONE OF (cleartext) + string array comparison value ("l")
// 2 -> CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 3 -> NOT CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 4 -> IS ONE OF (semver) + semver string array comparison value ("l")
// 5 -> IS NOT ONE OF (semver) + semver string array comparison value ("l")
// 6 -> < (semver) + semver string comparison value ("s")
// 7 -> <= (semver + semver string comparison value ("s")
// 8 -> > (semver) + semver string comparison value ("s")
// 9 -> >= (semver + semver string comparison value ("s")
// 10 -> = (number) + number comparison value ("d")
// 11 -> <> (number + number comparison value ("d")
// 12 -> < (number) + number comparison value ("d")
// 13 -> <= (number + number comparison value ("d")
// 14 -> > (number) + number comparison value ("d")
// 15 -> >= (number) + number comparison value ("d")
// 16 -> IS ONE OF (hashed) + string array comparison value ("l")
// 17 -> IS NOT ONE OF (hashed) + string array comparison value ("l")
// 18 -> BEFORE (UTC datetime) + second-based Unix timestamp number comparison value ("d")
// 19 -> AFTER (UTC datetime) + second-based Unix timestamp number comparison value ("d")
// 20 -> EQUALS (hashed) + string comparison value ("s")
// 21 -> NOT EQUALS (hashed) + string comparison value ("s")
// 22 -> STARTS WITH ANY OF (hashed) + string array comparison value ("l")
// 23 -> NOT STARTS WITH ANY OF (hashed) + string array comparison value ("l")
// 24 -> ENDS WITH ANY OF (hashed) + string array comparison value ("l")
// 25 -> NOT ENDS WITH ANY OF (hashed) + string array comparison value ("l")
// 26 -> ARRAY CONTAINS ANY OF (hashed) + string array comparison value ("l")
// 27 -> ARRAY NOT CONTAINS ANY OF (hashed) + string array comparison value ("l")
// 28 -> EQUALS (cleartext) + string comparison value ("s")
// 29 -> NOT EQUALS (cleartext) + string comparison value ("s")
// 30 -> STARTS WITH ANY OF (cleartext) + string array comparison value ("l")
// 31 -> NOT STARTS WITH ANY OF (cleartext) + string array comparison value ("l")
// 32 -> ENDS WITH ANY OF (cleartext) + string array comparison value ("l")
// 33 -> NOT ENDS WITH ANY OF (cleartext + string array comparison value ("l")
// 34 -> ARRAY CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 35 -> ARRAY NOT CONTAINS ANY OF (cleartext) + string array comparison value ("l")
"l": [ // comparison value - depending on the comparator, another type of value may need
// to be specified (see above):
// "s": string
// "d": number
"@example.com"
]
}
},
{
"p": { // Flag Condition (Prerequisite)
"f": "mainIntFlag", // key of prerequisite flag
"c": 0, // comparator, possible values: 0 -> EQUALS, 1 -> NOT EQUALS
"v": { // comparison value (value's type must match the prerequisite flag's type)
"i": 42
}
}
},
{
"s": { // Segment Condition
"s": 0, // segment index, a valid index into the top-level segment array ("s")
"c": 1 // comparator, possible values: 0 -> IS IN SEGMENT, 1 -> IS NOT IN SEGMENT
}
}
],
"s": { // alternatively, an array of Percentage Options ("p", see below) can also be specified
"v": { // the value served when the rule is selected during evaluation
"b": true
},
"i": "bcfb84a7"
}
}
],
"p": [ // array of Percentage Options
{
"p": 10, // % value
"v": { // the value served when the Percentage Option is selected during evaluation
"b": true
},
"i": "bcfb84a7"
},
{
"p": 90,
"v": {
"b": false
},
"i": "bddac6ae"
}
],
"v": { // fallback value, served when none of the Targeting Rules match,
// no Percentage Options are defined or evaluation of these is not possible
"b": false // depending on the setting type, another type of value may need to be specified:
// text setting -> "s": string
// whole number setting -> "i": number
// decimal number setting -> "d": number
},
"i": "430bded3" // variation id (for analytical purposes)
}
}
}
```
For a more comprehensive specification of the config JSON v6 format, you may refer to [this JSON schema document](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
### Map[](#map "Direct link to Map")
You can set up the SDK to load your feature flag & setting overrides from a map.
```cpp
const std::unordered_map& map = {
{ "enabledFeature", true },
{ "disabledFeature", false },
{ "intSetting", 5 },
{ "doubleSetting", 3.14 },
{ "stringSetting", "test" }
};
ConfigCatOptions options;
options.flagOverrides = std::make_shared(map, LocalOnly);
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
## `getAllKeys()`[](#getallkeys "Direct link to getallkeys")
You can get the keys for all available feature flags and settings by calling the `getAllKeys()` method.
```cpp
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#");
auto keys = client->getAllKeys();
```
## `getAllValues()`[](#getallvalues "Direct link to getallvalues")
Evaluates and returns the values of all feature flags and settings. Passing a User Object is optional.
```cpp
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#");
auto settingValues = client->getAllValues();
// invoke with User Object
auto user = ConfigCatUser::create("#UNIQUE-USER-IDENTIFIER#");
auto settingValuesTargeting = client->getAllValues(user);
```
## `getAllValueDetails`[](#getallvaluedetails "Direct link to getallvaluedetails")
Evaluates and returns the detailed values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```cpp
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#");
// invoke with User Object
auto user = ConfigCatUser::create("#UNIQUE-USER-IDENTIFIER#");
auto allValueDetails = client->getAllValueDetails(user)
```
## Custom Cache[](#custom-cache "Direct link to Custom Cache")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`ConfigCache`](https://github.com/configcat/cpp-sdk/blob/main/include/configcat/configcache.h#L8) interface and set the `configCache` parameter in the options passed to `ConfigCatClient::get`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
You have the option to inject your custom cache implementation into the client. All you have to do is to inherit from the `ConfigCatCache` abstract class:
```cpp
class MyCustomCache : public ConfigCatCache {
public:
const std::string& read(const std::string& key) override {
// here you have to return with the cached value
}
void write(const std::string& key, const std::string& value) override {
// here you have to store the new value in the cache
}
};
```
Then use your custom cache implementation:
```cpp
ConfigCatOptions options;
options.configCache = std::make_shared();
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
info
The C++ SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Force refresh[](#force-refresh "Direct link to Force refresh")
Call the `forceRefresh()` method on the client to download the latest config JSON and update the cache.
## Using ConfigCat behind a proxy[](#using-configcat-behind-a-proxy "Direct link to Using ConfigCat behind a proxy")
Provide your own network credentials (username/password), and proxy server settings (proxy server/port) in the `ConfigCatOptions`.
```cpp
ConfigCatOptions options;
options.proxies = {{"https", "proxyhost:port"}}; // Protocol, Proxy
options.proxyAuthentications = {
{"https", ProxyAuthentication{"user", "password"}} // Protocol, ProxyAuthentication
};
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
## Changing the default HTTP timeout[](#changing-the-default-http-timeout "Direct link to Changing the default HTTP timeout")
Set the maximum wait time for a ConfigCat HTTP response by changing the *connectTimeoutMs* or *readTimeoutMs* in the `ConfigCatOptions`. The default *connectTimeoutMs* is 8 seconds. The default *readTimeoutMs* is 5 seconds.
```cpp
ConfigCatOptions options;
options.connectTimeoutMs = 10000; // Timeout in milliseconds for establishing a HTTP connection with the server
options.readTimeoutMs = 8000; // Timeout in milliseconds for reading the server's HTTP response
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
## Logging[](#logging "Direct link to Logging")
### Setting log levels[](#setting-log-levels "Direct link to Setting log levels")
```cpp
#include
#include
auto logger = std::make_shared(LOG_LEVEL_WARNING);
ConfigCatOptions options;
options.logger = logger;
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
You can change the verbosity of the logs by setting the `LogLevel`.
```cpp
logger->setLogLevel(LOG_LEVEL_INFO);
```
Available log levels:
| Level | Description |
| ------------------- | --------------------------------------------------------------------------------------- |
| `LOG_LEVEL_ERROR` | Only error level events are logged. |
| `LOG_LEVEL_WARNING` | Default. Errors and Warnings are logged. |
| `LOG_LEVEL_INFO` | Errors, Warnings and feature flag evaluation is logged. |
| `LOG_LEVEL_DEBUG` | All of the above plus debug info is logged. Debug logs can be different for other SDKs. |
Info level logging helps to inspect how a feature flag was evaluated:
```bash
[INFO]:[5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"","Email":"configcat@example.com","Country":"US","SubscriptionType":"Pro","Role":"Admin","version":"1.0.0"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
In the ConfigCat SDK, the default logger (`ConsoleLogger`) writes logs to the standard output, but you can override it with your implementation via the `logger` client option. The custom logger must implement the `ILogger` abstract class.
```cpp
#include "log.h"
class CustomLogger : public ILogger {
public:
void log(LogLevel level, const std::string& message, const std::exception_ptr& exception) override {
// Write the logs
std::cout << logLevelAsString(level) << ": " << message << std::endl;
if (exception) {
std::cout << "Exception details: " << unwrap_exception_message(exception) << std::endl;
}
}
};
```
```cpp
auto logger = std::make_shared();
logger->setLogLevel(LOG_LEVEL_INFO);
ConfigCatOptions options;
options.logger = logger;
auto client = ConfigCatClient::get("#YOUR-SDK-KEY#", &options);
```
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the ConfigCat SDK that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
Check out our Sample Application how they use the ConfigCat SDK
* [ConfigCat C++ Console Sample App](https://github.com/configcat/cpp-sdk/tree/main/samples/)
## Guides[](#guides "Direct link to Guides")
See [this](https://configcat.com/blog/2022/10/21/configcat-cpp-sdk-announcement/) guide on how to use ConfigCat's C++ SDK.
## Look Under the Hood[](#look-under-the-hood "Direct link to Look Under the Hood")
* [ConfigCat C++ SDK's repository on GitHub](https://github.com/configcat/cpp-sdk)
---
# Source: https://configcat.com/docs/api/reference/create-config.md
# Create Config
Copy page
This endpoint creates a new Config in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-environment.md
# Create Environment
Copy page
This endpoint creates a new Environment in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/scim/create-group.md
# Create Group
Copy page
This endpoint creates a new group with the given attributes.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 401
* 409
* 429
Unauthorized. In case of the SCIM token is invalid.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-integration.md
# Create Integration
Copy page
This endpoint creates a new Integration in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
The Parameters dictionary differs for each IntegrationType:
* Datadog
* `apikey`: Required. Datadog API key.
* `site`: Datadog site. Available values: `Us`, `Eu`, `Us1Fed`, `Us3`, `Us5`. Default: `Us`.
* Slack
Connecting the Slack integration through the Public Management API will not post messages with the ConfigCat Feature Flags Slack app but with an incoming webhook.
* `incoming_webhook.url`: Required. The [incoming webhook URL](https://api.slack.com/messaging/webhooks) where the integration should post messages.
* `includeSensitiveData`: Set to "true" to include [sensitive (hashed) comparison values](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators). By default, the integration will mask these values in the posted messages. We recommend hiding sensitive comparison values for shared or public Slack channels.
* Amplitude
* `apiKey`: Required. Amplitude API Key.
* `secretKey`: Required. Amplitude Secret Key.
* Mixpanel
* `serviceAccountUserName`: Required. Mixpanel Service Account Username.
* `serviceAccountSecret`: Required. Mixpanel Service Account Secret.
* `projectId`: Required. Mixpanel Project ID.
* `server`: Mixpanel Server. Available values: `StandardServer`, `EUResidencyServer`. Default: `StandardServer`.
* Twilio Segment
* `writeKey`: Required. Twilio Segment Write Key.
* `server`: Twilio Segment Server. Available values: `Us`, `Eu`. Default: `Us`.
* PubNub (work in progress)
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-permission-group.md
# Create Permission Group
Copy page
This endpoint creates a new Permission Group in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-product.md
# Create Product
Copy page
This endpoint creates a new Product in a specified Organization identified by the `organizationId` parameter, which can be obtained from the [List Organizations](https://configcat.com/docs/api/reference/get-organizations.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-proxy-profile.md
# Create Proxy Profile
Copy page
This endpoint creates a new Proxy Profile in the given Organization identified by the `organizationId` parameter, which can be obtained from the [List Organizations](https://configcat.com/docs/api/reference/get-organizations.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-segment.md
# Create Segment
Copy page
This endpoint creates a new Segment in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-setting.md
# Create Flag
Copy page
This endpoint creates a new Feature Flag or Setting in a specified Config identified by the `configId` parameter.
**Important:** The `key` attribute must be unique within the given Config.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-tag.md
# Create Tag
Copy page
This endpoint creates a new Tag in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/scim/create-user.md
# Create User
Copy page
This endpoint creates a new user with the given attributes.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 401
* 409
* 429
Unauthorized. In case of the SCIM token is invalid.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/create-webhook.md
# Create Webhook
Copy page
This endpoint creates a new Webhook in a specified Product identified by the `productId` parameter, which can be obtained from the [List Products](https://configcat.com/docs/api/reference/get-products.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 201
* 400
* 404
* 429
When the creation was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/sdk-reference/dart.md
# Dart (Flutter) SDK Reference
Copy page
[](https://github.com/configcat/dart-sdk/stargazers) [](https://pub.dev/packages/configcat_client) [](https://github.com/configcat/dart-sdk/actions/workflows/dart-ci.yml)
[ConfigCat Dart (Flutter) SDK on GitHub](https://github.com/configcat/dart-sdk)
## Getting Started[](#getting-started "Direct link to Getting Started")
### 1. Add the ConfigCat SDK to your project[](#1-add-the-configcat-sdk-to-your-project "Direct link to 1. Add the ConfigCat SDK to your project")
* Dart
* Flutter
```bash
dart pub add configcat_client
```
```bash
flutter pub add configcat_client
```
Or put the following directly to your `pubspec.yml` and run `dart pub get` or `flutter pub get`.
pubspec.yml
```yaml
dependencies:
configcat_client: ^4.0.0
```
### 2. Import the ConfigCat SDK[](#2-import-the-configcat-sdk "Direct link to 2. Import the ConfigCat SDK")
```dart
import 'package:configcat_client/configcat_client.dart';
```
### 3. Create the *ConfigCat* client with your *SDK Key*[](#3-create-the-configcat-client-with-your-sdk-key "Direct link to 3-create-the-configcat-client-with-your-sdk-key")
```dart
final client = ConfigCatClient.get(sdkKey: '#YOUR-SDK-KEY#');
```
### 4. (Optional) Set up Flutter caching[](#4-optional-set-up-flutter-caching "Direct link to 4. (Optional) Set up Flutter caching")
If you're using the SDK in a Flutter application, it's recommended to use the [Flutter Preferences Cache](https://github.com/configcat/flutter-preferences-cache) implementation for caching. It stores the downloaded `config JSON` using the [shared\_preferences](https://pub.dev/packages/shared_preferences) package.
```dart
import 'package:configcat_preferences_cache/configcat_preferences_cache.dart';
```
```dart
final client = ConfigCatClient.get(
sdkKey: '#YOUR-SDK-KEY#',
options: ConfigCatOptions(cache: ConfigCatPreferencesCache()));
```
### 5. Get your setting value[](#5-get-your-setting-value "Direct link to 5. Get your setting value")
```dart
final isMyAwesomeFeatureEnabled = await client.getValue(key: 'isMyAwesomeFeatureEnabled', defaultValue: false);
if (isMyAwesomeFeatureEnabled) {
doTheNewThing();
} else {
doTheOldThing();
}
```
### 6. Close *ConfigCat* client[](#6-close-configcat-client "Direct link to 6-close-configcat-client")
You can safely shut down all clients at once or individually and release all associated resources on application exit.
```dart
ConfigCatClient.closeAll(); // closes all clients
client.close(); // closes the specific client
```
## Setting up the *ConfigCat Client*[](#setting-up-the-configcat-client "Direct link to setting-up-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`ConfigCatClient.get(sdkKey: )` returns a client with default options.
### Customizing the *ConfigCat Client*[](#customizing-the-configcat-client "Direct link to customizing-the-configcat-client")
To customize the SDK's behavior, you can pass an additional `ConfigCatOptions` parameter to the `get()` static factory method where the `ConfigCatOptions` class is used to set up the *ConfigCat Client*.
```dart
final client = ConfigCatClient.get(
sdkKey: '#YOUR-SDK-KEY#',
options: ConfigCatOptions(
pollingMode: PollingMode.manualPoll(),
logger: ConfigCatLogger(level: LogLevel.info)
)
);
```
These are the available options on the `ConfigCatOptions` class:
| Properties | Description |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dataGovernance` | Optional, defaults to `global`. Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `global`, `euOnly`. |
| `baseUrl` | Optional, sets the CDN base url (forward proxy, dedicated subscription) from where the sdk will download the config JSON. |
| `connectTimeout` | Optional, sets the underlying [Dio](https://github.com/flutterchina/dio) HTTP client's connect timeout. [More about the HTTP Client](#httpclient). |
| `receiveTimeout` | Optional, sets the underlying [Dio](https://github.com/flutterchina/dio) HTTP client's receive timeout. [More about the HTTP Client](#httpclient). |
| `sendTimeout` | Optional, sets the underlying [Dio](https://github.com/flutterchina/dio) HTTP client's send timeout. [More about the HTTP Client](#httpclient). |
| `cache` | Optional, sets a custom cache implementation for the client. [More about cache](#custom-cache). |
| `pollingMode` | Optional, sets the polling mode for the client. [More about polling modes](#polling-modes). |
| `logger` | Optional, sets the internal logger and log level. [More about logging](#logging). |
| `override` | Optional, sets local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). |
| `defaultUser` | Optional, sets the default user. [More about default user](#default-user). |
| `offline` | Optional, defaults to `false`. Indicates whether the SDK should be initialized in offline mode. [More about offline mode](#online--offline-mode). |
| `hooks` | Optional, used to subscribe events that the SDK sends in specific scenarios. [More about hooks](#hooks). |
caution
We strongly recommend you to use the `ConfigCatClient` as a Singleton object in your application. The `ConfigCatClient.get(sdkKey: )` static factory method constructs singleton client instances for your SDK keys. These clients can be closed all at once with the `ConfigCatClient.closeAll()` method or individually with `client.close()`.
## Anatomy of `getValue()`[](#anatomy-of-getvalue "Direct link to anatomy-of-getvalue")
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```dart
final value = await client.getValue(
key: 'keyOfMySetting',
defaultValue: false,
user: ConfigCatUser(identifier: '#USER-IDENTIFIER#'), // Optional User Object
);
```
caution
It is important to provide an argument for the `defaultValue` parameter, specifically for the `T` generic type parameter, that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | Type parameter `T` |
| -------------- | ------------------ |
| On/Off Toggle | `bool`/`bool?` |
| Text | `String`/`String?` |
| Whole Number | `int`/`int?` |
| Decimal Number | `double`/`double?` |
In addition to the types mentioned above, you also have the option to provide `object`, `object?` or `dynamic` for the type parameter regardless of the setting kind.
It's important to note that providing any other type for the type parameter will result in an `ArgumentError`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
When relying on type inference and not explicitly specifying the type parameter, be mindful of potential type mismatch issues, especially with number types. For example, `client.getValue(key: "keyOfMyDecimalSetting", defaultValue: 0)` will return `defaultValue` (`0`) instead of the actual value of the decimal setting because the compiler infers the type as `int` instead of `double`, that is, the call is equivalent to `client.getValue("keyOfMyDecimalSetting", 0)`, which is a type mismatch.
To correctly evaluate a decimal setting, you should use:
```dart
var value = client.getValue("keyOfMyDecimalSetting", 0.0);
// -or-
var value = client.getValue("keyOfMyDecimalSetting", 0);
```
## Anatomy of `getValueDetails()`[](#anatomy-of-getvaluedetails "Direct link to anatomy-of-getvaluedetails")
`getValueDetails()` is similar to `getValue()` but instead of returning the evaluated value only, it gives more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```dart
final details = await client.getValueDetails(
key: 'keyOfMySetting',
defaultValue: false,
user: ConfigCatUser(identifier: '#USER-IDENTIFIER#'), // Optional User Object
);
```
caution
It is important to provide an argument for the `defaultValue` parameter, specifically for the `T` generic type parameter, that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `value` | `bool` / `String` / `int` / `double` | The evaluated value of the feature flag or setting. |
| `key` | `String` | The key of the evaluated feature flag or setting. |
| `isDefaultValue` | `bool` | True when the default value passed to `getValueDetails()` is returned due to an error. |
| `error` | `String?` | In case of an error, this property contains the error message. |
| `user` | `ConfigCatUser?` | The User Object that was used for evaluation. |
| `matchedPercentageOption` | `PercentageOption?` | The Percentage Option (if any) that was used to select the evaluated value. |
| `matchedTargetingRule` | `TargetingRule?` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `fetchTime` | `DateTime` | The last download time of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
```dart
final user = ConfigCatUser(identifier: '#UNIQUE-USER-IDENTIFIER#');
```
```dart
final user = ConfigCatUser(identifier: 'john@example.com');
```
### Customized User Object creation[](#customized-user-object-creation "Direct link to Customized User Object creation")
| Argument | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. e.g. User role, Subscription type. |
```dart
final user = ConfigCatUser(
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
'SubscriptionType': 'Pro',
'UserRole': 'Admin'
}
);
```
The `custom` map also allows attribute values other than `String` values:
```dart
final user = ConfigCatUser(
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
'Rating': 4.5,
'RegisteredAt': DateTime.parse('2023-11-22 12:34:56 +00:00'),
'Roles': {"Role1", "Role2"}
}
);
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `String` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `String` values,
* all other values are automatically converted to `String` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `String` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `double` values and all other numeric values which can safely be converted to `double`,
* accept `String` values containing a properly formatted, valid `double` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `DateTime` values, which are automatically converted to a second-based Unix timestamp,
* accept `double` values representing a second-based Unix timestamp and all other numeric values which can safely be converted to `Double`,
* accept `String` values containing a properly formatted, valid `double` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept lists or sets of `String`,
* accept `String` values containing a valid JSON string which can be deserialized to an array of `String`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
There's an option to set a default User Object that will be used at feature flag and setting evaluation. It can be useful when your application has a single user only, or rarely switches users.
You can set the default User Object either on SDK initialization:
```dart
final client = ConfigCatClient.get(
sdkKey: '#YOUR-SDK-KEY#',
options: ConfigCatOptions(
defaultUser: ConfigCatUser(identifier: 'john@example.com')
)
);
```
or with the `setDefaultUser()` method of the ConfigCat client.
```dart
client.setDefaultUser(ConfigCatUser(identifier: 'john@example.com'));
```
Whenever the `getValue()`, `getValueDetails()`, `getAllValues()`, or `getAllVariationIds()` methods are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```dart
final user = ConfigCatUser(identifier: 'john@example.com');
client.setDefaultUser(user);
// The default user will be used at the evaluation process.
final value = await client.getValue(key: 'keyOfMySetting', defaultValue: false);
```
When the `user` parameter is specified on the requesting method, it takes precedence over the default user.
```dart
final user = ConfigCatUser(identifier: 'john@example.com');
client.setDefaultUser(user);
final otherUser = ConfigCatUser(identifier: 'brian@example.com');
// otherUser will be used at the evaluation process.
final value = await client.getValue(key: 'keyOfMySetting', defaultValue: false, user: otherUser);
```
For deleting the default user, you can do the following:
```dart
client.clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValue()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle.
[More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the the `autoPollInterval` option parameter of the `PollingMode.autoPoll()` to change the polling interval.
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(
pollingMode: PollingMode.autoPoll(
autoPollInterval: Duration(seconds: 100),
),
)
);
```
Available options:
| Option Parameter | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------- | ------- |
| `autoPollInterval` | Polling interval. | 60 |
| `maxInitWaitTime` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5 |
### Lazy Loading[](#lazy-loading "Direct link to Lazy Loading")
When calling `getValue()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValue()` will return the setting value after the cache is updated.
Use the `cacheRefreshInterval` option parameter of the `PollingMode.lazyLoad()` to set cache lifetime.
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(
pollingMode: PollingMode.lazyLoad(
// the cache will expire in 100 seconds
cacheRefreshInterval: Duration(seconds: 100),
),
)
);
```
Available options:
| Parameter | Description | Default |
| ---------------------- | ----------- | ------- |
| `cacheRefreshInterval` | Cache TTL. | 60 |
### Manual Polling[](#manual-polling "Direct link to Manual Polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefresh()` is your application's responsibility.
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(
pollingMode: PollingMode.manualPoll(),
)
);
client.forceRefresh();
```
> `getValue()` returns `defaultValue` if the cache is empty. Call `forceRefresh()` to update the cache.
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `onClientReady()`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after instantiation.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTime` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. Alternatively, in Auto Polling mode, you can wait for the first `onConfigChanged` event to be notified when the internal cache is actually populated with config data.
* `onConfigChanged(Map)`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `onFlagEvaluated(EvaluationDetails)`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetails()`](#anatomy-of-getvaluedetails).
* `onError(String)`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on SDK initialization:
```dart
final client = ConfigCatClient.get(
sdkKey: '#YOUR-SDK-KEY#',
options: ConfigCatOptions(
pollingMode: PollingMode.manualPoll(),
hooks: Hooks(
onFlagEvaluated: (details) => /* handle the event */
)
)
);
```
or with the `hooks` property of the ConfigCat client:
```dart
client.hooks.addOnFlagEvaluated((details) => /* handle the event */);
```
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases when you'd want to prevent the SDK from making HTTP calls, you can put it in offline mode:
```dart
client.setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To put the SDK back in online mode, you can do the following:
```dart
client.setOnline();
```
> With `client.isOffline()` you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.localOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.localOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.remoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a `Map`.
```dart
final client = ConfigCatClient.get(
sdkKey: 'localhost',
options: ConfigCatOptions(
override: FlagOverrides(
dataSource: OverrideDataSource.map({
'enabledFeature': true,
'disabledFeature': false,
'intSetting': 5,
'doubleSetting': 3.14,
'stringSetting': 'test',
}),
behaviour: OverrideBehaviour.localOnly
)
)
);
```
## `getAllKeys()`[](#getallkeys "Direct link to getallkeys")
You can get the keys for all available feature flags and settings by calling the `getAllKeys()` method.
```dart
final client = ConfigCatClient.get(sdkKey: '#YOUR-SDK-KEY#');
final keys = await client.getAllKeys();
```
## `getAllValues()`[](#getallvalues "Direct link to getallvalues")
Evaluates and returns the values of all feature flags and settings. Passing a User Object is optional.
```dart
final client = ConfigCatClient.get(sdkKey: '#YOUR-SDK-KEY#');
final settingValues = await client.getAllValues();
// invoke with User Object
final user = ConfigCatUser(identifier: '#UNIQUE-USER-IDENTIFIER#');
final settingValuesTargeting = await client.getAllValues(user);
```
## Cache[](#cache "Direct link to Cache")
The SDK caches the downloaded `config JSON` only in memory by default. In case you have a Flutter application, you can use the [Flutter Preferences Cache](https://github.com/configcat/flutter-preferences-cache) for caching.
It's based on the [shared\_preferences](https://pub.dev/packages/shared_preferences) package that uses the following storage locations by platform:
* **Web**: Browser `LocalStorage`.
* **iOS / macOS**: `NSUserDefaults`.
* **Android**: `SharedPreferences`.
* **Linux**: File in `XDG_DATA_HOME` directory.
* **Windows**: File in roaming `AppData` directory.
```dart
final client = ConfigCatClient.get(
sdkKey: '#YOUR-SDK-KEY#',
options: ConfigCatOptions(cache: ConfigCatPreferencesCache()));
```
### Custom Cache[](#custom-cache "Direct link to Custom Cache")
You have the option to inject your custom cache implementation into the client. All you have to do is to inherit from the `ConfigCatCache` abstract class:
```dart
class MyCustomCache extends ConfigCatCache {
@override
Future read(String key) {
// here you have to return with the cached value
}
@override
Future write(String key, String value) {
// here you have to store the new value in the cache
}
}
```
Then use your custom cache implementation:
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(cache: MyCustomCache()));
```
info
The Dart (Flutter) SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## HttpClient[](#httpclient "Direct link to HttpClient")
The ConfigCat SDK internally uses a [Dio HTTP client](https://github.com/flutterchina/dio) instance to download the latest config JSON over HTTP. You have the option to customize the internal HTTP client.
### HTTP Timeout[](#http-timeout "Direct link to HTTP Timeout")
You can set the maximum wait time for a ConfigCat HTTP response by using Dio's timeouts.
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(
connectTimeout: Duration(seconds: 10), // timeout for establishing a HTTP connection with the server
sendTimeout: Duration(seconds: 10), // timeout for sending a HTTP request to the server
receiveTimeout: Duration(seconds: 10), // timeout for reading the server's HTTP response
)
);
```
Default timeout values:
* `connectTimeout`: 10 seconds
* `sendTimeout`: 20 seconds
* `receiveTimeout`: 20 seconds
### HTTP Proxy[](#http-proxy "Direct link to HTTP Proxy")
If your application runs behind a proxy you can do the following:
```dart
import 'package:dio/adapter.dart';
(client.httpClient.httpClientAdapter as DefaultHttpClientAdapter)
.onHttpClientCreate = (client) {
client.findProxy = (uri) {
return 'PROXY proxyHost:proxyPort';
};
};
```
## Force refresh[](#force-refresh "Direct link to Force refresh")
Call the `forceRefresh()` method on the client to download the latest config JSON and update the cache.
## Logging[](#logging "Direct link to Logging")
The default logger used by the SDK simply outputs the log messages with `print()`, but you can override it with your implementation via the `logger` client option. The custom implementation must satisfy the [Logger](https://github.com/configcat/dart-sdk/blob/main/lib/src/log/logger.dart) abstract class.
```dart
class MyCustomLogger implements Logger {
@override
void close() {
// close the logger
}
@override
void debug(message, [error, StackTrace? stackTrace]) {
// write the debug logs
}
@override
void error(message, [error, StackTrace? stackTrace]) {
// write the error logs
}
@override
void info(message, [error, StackTrace? stackTrace]) {
// write the info logs
}
@override
void warning(message, [error, StackTrace? stackTrace]) {
// write the warning logs
}
}
```
Then you can use your custom logger implementation at the SDK's initialization:
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(
logger: ConfigCatLogger(internalLogger: MyCustomLogger()),
)
);
```
You can change the verbosity of the logs by passing a `LogLevel` parameter to the `logger` option.
```dart
final client = ConfigCatClient.get(
sdkKey: '',
options: ConfigCatOptions(
logger: ConfigCatLogger(level: LogLevel.info),
)
);
```
Available log levels:
| Level | Description |
| --------- | --------------------------------------------------------------------------------------- |
| `nothing` | Turn the logging off. |
| `error` | Only error level events are logged. |
| `warning` | Default. Errors and Warnings are logged. |
| `info` | Errors, Warnings and feature flag evaluation is logged. |
| `debug` | All of the above plus debug info is logged. Debug logs can be different for other SDKs. |
Info level logging helps to inspect how a feature flag was evaluated:
```bash
[INFO] 2022-01-20T18:22:02.313703 ConfigCat - [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"","Email":"configcat@example.com","Country":"US","SubscriptionType":"Pro","Role":"Admin","version":"1.0.0"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'False' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'True' => MATCH, applying rule
Returning 'True'.
```
## Sample Apps[](#sample-apps "Direct link to Sample Apps")
Check out our Sample Applications how they use the ConfigCat SDK
* [Console Application](https://github.com/configcat/dart-sdk/tree/main/example/lib)
* [Flutter Application](https://github.com/configcat/dart-sdk/tree/main/example/flutter)
## Guides[](#guides "Direct link to Guides")
See [this](https://configcat.com/blog/2022/10/18/feature-flags-in-dart/) guide on how to use ConfigCat's Dart SDK.
## Look Under the Hood[](#look-under-the-hood "Direct link to Look Under the Hood")
* [ConfigCat Dart (Flutter) SDK's repository on GitHub](https://github.com/configcat/dart-sdk)
* [ConfigCat Dart (Flutter) SDK's pub.dev page](https://pub.dev/packages/configcat_client)
---
# Source: https://configcat.com/docs/advanced/data-governance.md
# Data Governance - CDN
Copy page
ConfigCat's Data Governance feature gives you control over how and where your config JSONs are published and served from. This helps you comply with regional data handling requirements such as GDPR.
## CDN - Data Centers[](#cdn---data-centers "Direct link to CDN - Data Centers")
To ensure high availability and low response times worldwide, ConfigCat provides multiple global data centers, each with multiple CDN nodes for built-in redundancy and failover.
### ConfigCat Data Center locations[](#configcat-data-center-locations "Direct link to ConfigCat Data Center locations")
ConfigCat uses Cloudflare Edge Cache Network to deliver the configuration JSONs to the SDKs. Read more about Cloudflare data centers [here](https://www.cloudflare.com/network/).
## How to govern the data?[](#how-to-govern-the-data "Direct link to How to govern the data?")
Currently available geographical areas:
### Global \[Default][](#global-default "Direct link to Global \[Default]")
Provides geo-location based load balancing on all nodes around the globe to ensure the lowest response times.
### EU Only[](#eu-only "Direct link to EU Only")
Compliant with GDPR. This way your data will never leave the EU.
## Set preferences on the Dashboard[](#set-preferences-on-the-dashboard "Direct link to Set preferences on the Dashboard")
Open [Data Governance page](https://app.configcat.com/organization/data-governance) and follow the steps to set preferences.
> Only team members with Organization Admin role can access Data Governance preferences.
## Set up the ConfigCat SDK in your application code[](#set-up-the-configcat-sdk-in-your-application-code "Direct link to Set up the ConfigCat SDK in your application code")
Make sure the `dataGovernance` option is specified when initializing the ConfigCat SDK in your application code.
> The `dataGovernance` option's value must be in sync with the selected option on the Dashboard.
## Troubleshooting[](#troubleshooting "Direct link to Troubleshooting")
#### What if I forget to specify the `dataGovernance` option?[](#what-if-i-forget-to-specify-the-datagovernance-option "Direct link to what-if-i-forget-to-specify-the-datagovernance-option")
By default, the ConfigCat SDK contacts the ConfigCat Global CDN. However, if you switch to the EU CDN on the Dashboard, your config JSONs will only be published to the EU CDN nodes. Therefore, if you forget to specify the `dataGovernance` option when initializing the ConfigCat SDK, feature flag data download requests will need to be redirected to the EU CDN. To avoid this, it's recommended to specify the correct `dataGovernance` option, otherwise response times can be significantly longer.
#### `Warning: The dataGovernance parameter specified at the client initialization is not in sync with the preferences on the ConfigCat Dashboard....`[](#warning-the-datagovernance-parameter-specified-at-the-client-initialization-is-not-in-sync-with-the-preferences-on-the-configcat-dashboard "Direct link to warning-the-datagovernance-parameter-specified-at-the-client-initialization-is-not-in-sync-with-the-preferences-on-the-configcat-dashboard")
**Don't worry,** your feature flags will still be served. See above example.
---
# Source: https://configcat.com/docs/integrations/datadog.md
# Datadog - Monitor your feature flags events
Copy page
## Overview[](#overview "Direct link to Overview")
Monitor feature flag events in real-time. Feature flag changes will appear as events in Datadog, tagged with relevant product, config, and environment details.

## Installation[](#installation "Direct link to Installation")
1. Have a [Datadog subscription.](https://www.datadoghq.com/)
2. Get a [Datadog API Key.](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys)

3. Open the [integrations tab](https://app.configcat.com/product/integrations) on ConfigCat Dashboard.
4. Click on Datadog's **Connect** button and set your Datadog API key.
5. OPTIONAL - Set the proper site of your Datadog account. [More about Datadog site](https://docs.datadoghq.com/getting_started/site/).
6. You're all set. Go ahead and make some changes on your feature flags, then check your Events in Datadog.
## Un-installation[](#un-installation "Direct link to Un-installation")
1. Open the [integrations tab](https://app.configcat.com/product/integrations) on ConfigCat Dashboard.
2. Click on Datadog's **Connected** button.
3. Select the connection from the **Connected** dropdown.
4. Click the **Disconnect** button in the edit dialog.
5. Click **Yes** in the confirmation dialog.
## Event details[](#event-details "Direct link to Event details")
Every event sent to Datadog by ConfigCat has a *source* property of `configcat` and *tagged* with the `product_name`, `config_name` and `environment_name` where the change has happened.
### Searching for Events[](#searching-for-events "Direct link to Searching for Events")
For example here is how to search for events that happened in the production environment: `sources:configcat production`

## Useful Resources[](#useful-resources "Direct link to Useful Resources")
* [How to send feature flag change notifications to DataDog - Blog Post](https://configcat.com/blog/2021/03/17/connect-configcat-and-datadog/)
* [ConfigCat Integrations API](https://configcat.com/docs/api/reference/integrations/)
---
# Source: https://configcat.com/docs/api/reference/delete-config.md
# Delete Config
Copy page
This endpoint removes a Config identified by the `configId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-environment.md
# Delete Environment
Copy page
This endpoint removes an Environment identified by the `environmentId` parameter. If the `cleanupAuditLogs` flag is set to true, it also deletes the audit log records related to the environment (except for the `Created a new environment` and `Deleted an environment` records).
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/scim/delete-group.md
# Delete Group
Copy page
This endpoint deletes an existing group.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 401
* 404
* 429
No content.
Unauthorized. In case of the SCIM token is invalid.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-integration.md
# Delete Integration
Copy page
This endpoint removes a Integration identified by the `integrationId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-invitation.md
# Delete Invitation
Copy page
This endpoint removes an Invitation identified by the `invitationId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-organization-member.md
# Delete Member from Organization
Copy page
This endpoint removes a Member identified by the `userId` from the given Organization identified by the `organizationId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-permission-group.md
# Delete Permission Group
Copy page
This endpoint removes a Permission Group identified by the `permissionGroupId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-product-member.md
# Delete Member from Product
Copy page
This endpoint removes a Member identified by the `userId` from the given Product identified by the `productId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-product.md
# Delete Product
Copy page
This endpoint removes a Product identified by the `productId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-proxy-profile.md
# Delete Proxy Profile
Copy page
This endpoint removes a Proxy Profile identified by the `proxyProfileId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-reference-reports.md
# Delete Reference reports
Copy page
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 200
* 400
* 404
* 429
OK
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-segment.md
# Delete Segment
Copy page
This endpoint removes a Segment identified by the `segmentId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-setting.md
# Delete Flag
Copy page
This endpoint removes a Feature Flag or Setting from a specified Config, identified by the `configId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-tag.md
# Delete Tag
Copy page
This endpoint deletes a Tag identified by the `tagId` parameter. To remove a Tag from a Feature Flag or Setting use the [Update Flag](https://configcat.com/docs/api/reference/update-setting.md) endpoint.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/scim/delete-user.md
# Delete User
Copy page
This endpoint deletes an existing user.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 401
* 404
* 429
No content.
Unauthorized. In case of the SCIM token is invalid.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/api/reference/delete-webhook.md
# Delete Webhook
Copy page
This endpoint removes a Webhook identified by the `webhookId` parameter.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 204
* 400
* 404
* 429
When the delete was successful.
Bad request.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/sdk-reference/js/deno.md
# Deno SDK
Copy page
[](https://github.com/configcat/js-unified-sdk/stargazers) [](https://github.com/configcat/js-unified-sdk/actions/workflows/js-sdk-ci.yml) [](https://sonarcloud.io/project/overview?id=configcat_js-unified-sdk) [](https://snyk.io/test/github/configcat/js-unified-sdk?targetFile=package.json) [](https://sonarcloud.io/dashboard?id=configcat_js-sdk) [](https://data.jsdelivr.com/v1/package/npm/@configcat/sdk/badge)
[ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Install and import package[](#1-install-and-import-package "Direct link to 1. Install and import package")
First install the [NPM package](https://npmjs.com/package/@configcat/sdk):
```bash
npm i @configcat/sdk
```
Then import it into your application:
```js
import * as configcat from "@configcat/sdk/deno";
```
info
To make this work in older versions of Deno, you may need to enable the [unstable-byonm](https://deno.com/blog/node-to-deno-challenge#what-are-all-these-unstable-node-compatibility-settings) feature or adjust your [import map](https://docs.deno.com/runtime/fundamentals/modules/#differentiating-between-imports-or-importmap-in-deno.json-and---import-map-option).
### 2. Create the *ConfigCat* client with your SDK Key[](#2-create-the-configcat-client-with-your-sdk-key "Direct link to 2-create-the-configcat-client-with-your-sdk-key")
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
```
### 3. Get your setting value[](#3-get-your-setting-value "Direct link to 3. Get your setting value")
The async/await way:
```js
const value = await configCatClient.getValueAsync(
'isMyAwesomeFeatureEnabled',
false,
);
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
```
The Promise way:
```js
configCatClient
.getValueAsync('isMyAwesomeFeatureEnabled', false)
.then((value) => {
if (value) {
do_the_new_thing();
} else {
do_the_old_thing();
}
});
```
The *ConfigCat SDK* also offers a synchronous API for feature flag evaluation. Read more [here](#snapshots-and-synchronous-feature-flag-evaluation).
### 4. Dispose the *ConfigCat* client[](#4-dispose-the-configcat-client "Direct link to 4-dispose-the-configcat-client")
You can safely dispose all clients at once or individually and release all associated resources on application exit.
```js
configcat.disposeAllClients(); // disposes all clients
// -or-
configCatClient.dispose(); // disposes a specific client
```
## Creating the *ConfigCat* Client[](#creating-the-configcat-client "Direct link to creating-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`configcat.getClient('')` returns a client with default options.
The `getClient` function has optional parameters, which can be used to adjust the behavior of the client.
| Parameters | Description | Default |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------- |
| `sdkKey` | **REQUIRED.** SDK Key to access your feature flags and settings. Get it from *ConfigCat Dashboard*. | - |
| `pollingMode` | Optional. The polling mode to use to fetch the config data from the ConfigCat CDN. [More about polling modes](#polling-modes). | `PollingMode.AutoPoll` |
| `options` | Optional. The options object. See the table below. | - |
The available options depends on the chosen polling mode. However, there are some common options which can be set in the case of every polling mode:
| Option Parameter | Description | Default |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `configFetcher` | Custom [`IConfigCatConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigFetcher.ts) instance for downloading a config. | [`DenoHttpConfigFetcher`](https://github.com/configcat/js-unified-sdk/blob/master/src/deno/DenoHttpConfigFetcher.ts) |
| `cache` | Custom [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) implementation for caching the downloaded config. | [`InMemoryConfigCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) |
| `logger` | Custom [`IConfigCatLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) implementation for tracing. | [`ConfigCatConsoleLogger`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatLogger.ts) (with WARN level) |
| `logFilter` | Sets a custom log filter. [More about log filtering](#log-filtering). | `undefined` (none) |
| `baseUrl` | Sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. | |
| `requestTimeoutMs` | The amount of milliseconds the SDK waits for a response from the ConfigCat servers before returning values from the cache. | 30000 |
| `flagOverrides` | Local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). | |
| `dataGovernance` | Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `DataGovernance.Global`, `DataGovernance.EuOnly`. | `DataGovernance.Global` |
| `defaultUser` | Sets the default user. [More about default user](#default-user). | `undefined` (none) |
| `offline` | Determines whether the client should be initialized to offline mode. [More about offline mode](#online--offline-mode). | `false` |
Options also include a property named `setupHook`, which you can use to subscribe to the hooks (events) at the time of initialization. [More about hooks](#hooks).
For example:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
setupHooks: (hooks) => hooks.on('clientReady', function() {
const keys = this.configCatClient.snapshot().getAllKeys();
console.log(`Client is ready! Number of available feature flags: ${keys.length}`);
}),
},
);
```
info
You can acquire singleton client instances for your SDK keys using the `configcat.getClient(sdkKey: "")` factory function. (However, please keep in mind that subsequent calls to `getClient()` with the *same SDK Key* return a *shared* client instance, which was set up by the first call.)
You can close all open clients at once using the `configcat.disposeAllClients()` function or do it individually using the `configCatClient.dispose()` method.
## Anatomy of `getValueAsync()`[](#anatomy-of-getvalueasync "Direct link to anatomy-of-getvalueasync")
Returns a Promise with the value.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((value) => {
console.log(value);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | `typeof defaultValue` |
| -------------- | --------------------- |
| On/Off Toggle | `boolean` |
| Text | `string` |
| Whole Number | `number` |
| Decimal Number | `number` |
In addition to the types mentioned above, you also have the option to provide `null` or `undefined` for the `defaultValue` parameter regardless of the setting kind. However, if you do so, the return type of the `getValue` method will be
* `boolean | string | number | null` when `defaultValue` is `null` or
* `boolean | string | number | undefined` when `defaultValue` is `undefined`.
This is because in these cases the exact return type cannot be determined at compile-time as the TypeScript compiler has no information about the setting type.
It's important to note that providing any other type for the `defaultValue` parameter will result in a `TypeError`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
## Anatomy of `getValueDetailsAsync()`[](#anatomy-of-getvaluedetailsasync "Direct link to anatomy-of-getvaluedetailsasync")
`getValueDetailsAsync()` is similar to `getValueAsync()` but instead of returning the evaluated value only, it provides more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```js
const details = await configCatClient.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
);
```
or
```js
configCatClient
.getValueDetailsAsync(
'keyOfMyFeatureFlag', // Setting Key
false, // Default value
{ identifier: '#UNIQUE-USER-IDENTIFIER#' }, // Optional User Object
)
.then((details) => {
console.log(details);
});
```
caution
It is important to provide an argument for the `defaultValue` parameter that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `key` | `string` | The key of the evaluated feature flag or setting. |
| `value` | `boolean` / `string` / `number` | The evaluated value of the feature flag or setting. |
| `user` | `User` | The User Object used for the evaluation. |
| `isDefaultValue` | `boolean` | True when the default value passed to `getValueDetailsAsync()` is returned due to an error. |
| `errorCode` | `EvaluationErrorCode` | In case of an error, this property contains a code that identifies the reason for the error. |
| `errorMessage` | `string` | In case of an error, this property contains the error message. |
| `errorException` | `any` | In case of an error, this property contains the related exception object (if any). |
| `matchedTargetingRule` | `TargetingRule` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matchedPercentageOption` | `PercentageOption` | The Percentage Option (if any) that was used to select the evaluated value. |
| `fetchTime` | `Date` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
For simple targeting:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
```
```js
const userObject = { identifier: 'john@example.com' };
```
| Parameters | Description |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any `string` value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
For advanced targeting:
```js
const userObject = {
identifier: '#UNIQUE-USER-IDENTIFIER#',
email: 'john@example.com',
country: 'United Kingdom',
custom: {
SubscriptionType: 'Pro',
UserRole: 'Admin',
},
};
```
The `custom` dictionary also allows attribute values other than `string` values:
```js
const userObject = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
userObject.custom = {
Rating: 4.5,
RegisteredAt: new Date('2023-11-22T12:34:56.000Z'),
Roles: ['Role1', 'Role2'],
};
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `string` values,
* all other values are automatically converted to `string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `number` values,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `Date` values, which are automatically converted to a second-based Unix timestamp,
* accept `number` values representing a second-based Unix timestamp,
* accept `string` values containing a properly formatted, valid `number` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept arrays of `string`,
* accept `string` values containing a valid JSON string which can be deserialized to an array of `string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
It's possible to set a default User Object that will be used on feature flag and setting evaluation. It can be useful when your application has a single user only or rarely switches users.
You can set the default User Object either on SDK initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
defaultUser: { identifier: 'john@example.com' },
},
);
```
...or using the `setDefaultUser()` method of the `configCatClient` object:
```js
configCatClient.setDefaultUser({ identifier: 'john@example.com' });
```
Whenever the evaluation methods like `getValueAsync()`, `getValueDetailsAsync()`, etc. are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
// The default user will be used in the evaluation process.
const value = await configCatClient.getValueAsync('keyOfMyFeatureFlag', false);
```
When a `user` parameter is passed to the evaluation methods, it takes precedence over the default user.
```js
const user = { identifier: 'john@example.com' };
configCatClient.setDefaultUser(user);
const otherUser = { identifier: 'brian@example.com' };
// otherUser will be used in the evaluation process.
const value = await configCatClient.getValueAsync(
'keyOfMyFeatureFlag',
false,
otherUser,
);
```
You can also remove the default user by doing the following:
```js
configCatClient.clearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `getValueAsync()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle. [More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `pollIntervalSeconds` option parameter to change the polling interval.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
pollIntervalSeconds: 95,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------------------------------------------------------------------------------------- | ------- |
| `pollIntervalSeconds` | Polling interval in seconds. | 60s |
| `maxInitWaitTimeSeconds` | Maximum waiting time between the client initialization and the first config acquisition in seconds. | 5s |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `getValueAsync()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `getValueAsync()` will return the setting value after the cache is updated.
Use `cacheTimeToLiveSeconds` option parameter to set cache lifetime.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.LazyLoad,
{
cacheTimeToLiveSeconds: 600,
},
);
```
Available options (in addition to the [common ones](#creating-the-configcat-client)):
| Option Parameter | Description | Default |
| ------------------------ | --------------------- | ------- |
| `cacheTimeToLiveSeconds` | Cache TTL in seconds. | 60s |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `forceRefreshAsync()` is your application's responsibility.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
await configCatClient.forceRefreshAsync();
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
> `getValueAsync()` returns `defaultValue` if the cache is empty. Call `forceRefreshAsync()` to update the cache.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
);
const value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value); // console: "my default value"
await configCatClient.forceRefreshAsync();
value = await configCatClient.getValueAsync(
'keyOfMyTextSetting',
'my default value',
);
console.log(value);
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `clientReady: [cacheState: ClientCacheState]`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after the initial sync with the external cache (if any) completes.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTimeSeconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the `cacheState` argument.
* `configFetched: [result: RefreshResult, isInitiatedByUser: boolean]`: This event is emitted each time the client attempts to refresh the cached config by fetching the latest version from the ConfigCat CDN. It is emitted not only when `ForceRefreshAsync` is called but also when the refresh is initiated by the client automatically. Thus, this event allows you to observe potential network issues that occur under the hood.
* `configChanged: [newConfig: IConfig]`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `flagEvaluated: [evaluationDetails: IEvaluationDetails]`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`getValueDetailsAsync()`](#anatomy-of-getvaluedetailsasync).
* `clientError: [message: string, exception?: any]`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on initialization:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.ManualPoll,
{
setupHooks: (hooks) =>
hooks.on('flagEvaluated', function() {
/* handle the event */
}),
},
);
```
...or directly on the `ConfigCatClient` instance:
```js
configCatClient.on('flagEvaluated', function() {
/* handle the event */
});
```
caution
Some events (e.g. `clientReady`, `configChanged` and `clientError`) may be emitted before `getClient` returns. This means you may miss them unless you subscribe on initialization.
However, even if you do, there's another gotcha: it's not safe to use the outer `configCatClient` variable in your event handler because it may not yet be assigned when the handler is called. Instead, you can safely access the client instance via `this.configCatClient` - provided that the event handler is a normal function, not an arrow function.
## Snapshots and synchronous feature flag evaluation[](#snapshots-and-synchronous-feature-flag-evaluation "Direct link to Snapshots and synchronous feature flag evaluation")
On JavaScript platforms, the *ConfigCat* client provides only asynchronous methods for evaluating feature flags and settings because these operations may involve network communication (e.g. downloading config data from the ConfigCat CDN servers), which is necessarily an asynchronous operation in JavaScript.
However, there can be circumstances where synchronous evaluation is preferable, thus, since v8.1.0, the JavaScript SDK provides a way to synchronously evaluate feature flags and settings via *snapshots*.
Using the `snapshot()` method, you can capture the current state of the *ConfigCat* client (including the latest downloaded config data) and use the resulting snapshot object to synchronously evaluate feature flags and settings based on the captured state:
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
);
// Wait for the client to initialize.
await configCatClient.waitForReady();
const snapshot = configCatClient.snapshot();
const user = { identifier: '#UNIQUE-USER-IDENTIFIER#' };
for (const key of snapshot.getAllKeys()) {
const value = snapshot.getValue(key, null, user);
console.log(`${key}: ${value}`);
}
```
Creating a snapshot is a cheap operation. This is possible because snapshots capture the client's internal (in-memory) cache. No attempt is made to refresh the internal cache, even if it's empty or expired.
caution
Please note that creating and using a snapshot
* won't trigger a sync with the external cache when working with [shared caching](https://configcat.com/docs/advanced/caching.md#shared-cache),
* won't fetch the latest config data from the ConfigCat CDN when the internally cached config data is empty or expired.
For the above reasons, it's recommended to use snapshots in conjunction with the Auto Polling mode, where the SDK automatically updates the internal cache in the background. (For other polling modes, you'll need to manually initiate a cache refresh by calling `forceRefreshAsync`.)
Because of this behavior, it's important to make sure that the client has completed initialization and populated its internal cache before creating snapshots. Otherwise the snapshot's evaluation methods won't have the data to do actual evaluation, but will just return the default value you pass to them. Which behavior is usually not what you want in your application.
In Auto Polling mode, you can use the `waitForReady` method to wait for the latest config data to become available locally. This is an asynchronous operation, which completes as soon as the client reaches the ready state, i.e. completes initialization (or the time specified via the `maxInitWaitTimeSeconds` option passes).
(Please note that this doesn't apply to other polling modes. In those cases, the client doesn't contact the ConfigCat CDN during initialization, so the ready state is reached as soon as the first sync with the external cache completes.)
Typically, you call `waitForReady` and wait for its completion only once, in the initialization phase of your application.
caution
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the return value.
```js
const clientCacheState = await configCatClient.waitForReady();
if (clientCacheState === configcat.ClientCacheState.NoFlagData) {
// Handle initialization failure (see below).
console.warn('ConfigCat client failed to obtain the config data during initialization.');
}
```
You have the following options to handle unsuccessful initialization:
* If it's acceptable for your application to start up and use the default values passed to the evaluation methods, you may log some warning (or skip the check altogether as the client will log warnings anyway), and let the application continue.
* Otherwise, you need to either terminate the application or continue waiting. The latter is an option because the client might be able to obtain the config data later, in the case of a transient problem like some temporary network issue. However, the *ConfigCat SDK* doesn't provide out-of-the-box support for this case currently. You can implement this logic by subscribing to the `configChanged` hook and waiting for the first event.
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases where you want to prevent the SDK from making HTTP calls, you can switch it to offline mode:
```js
configCatClient.setOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To switch the SDK back to online mode, do the following:
```js
configCatClient.setOnline();
```
Using the `configCatClient.isOffline` property you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a `{ [key: string]: boolean | string | number }` object or from a custom flag override data source.
### Map[](#map "Direct link to Map")
You can specify simple feature flag & setting overrides using a `{ [key: string]: boolean | string | number }` map.
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: configcat.createFlagOverridesFromMap(
{
enabledFeature: true,
disabledFeature: false,
intSetting: 5,
doubleSetting: 3.14,
stringSetting: 'test',
},
configcat.OverrideBehaviour.LocalOnly,
),
},
);
```
### Custom data source implementation[](#custom-data-source-implementation "Direct link to Custom data source implementation")
You can create a custom flag override data source by implementing `IOverrideDataSource`.
The SDK provides the `createSettingFromValue` function to create `Setting` objects from simple `boolean`, `string` and `number` values. In case you need complex (full-featured) flag overrides, you can use the `deserializeConfig` function to obtain `Setting` objects from a config JSON conforming to the [config JSON v6 format](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
```ts
class MyCustomOverrideDataSource implements IOverrideDataSource {
private settings: Record;
constructor(configJson: string) {
this.settings = deserializeConfig(configJson).f ?? {};
}
getOverrides(): Record {
return this.settings;
}
}
```
or
```js
function MyCustomOverrideDataSource(configJson) {
this.settings = deserializeConfig(configJson).f ?? {};
}
MyCustomOverrideDataSource.prototype.getOverrides = function () {
return this.settings;
};
```
then
```js
// Set the `MyCustomOverrideDataSource` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
flagOverrides: {
dataSource: new MyCustomOverrideDataSource('{ "f": { ... } }'),
behaviour: configcat.OverrideBehaviour.LocalOnly,
}
},
);
```
## Logging[](#logging "Direct link to Logging")
### Setting log levels[](#setting-log-levels "Direct link to Setting log levels")
```js
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: configcat.createConsoleLogger(configcat.LogLevel.Info), // Setting log level to Info
},
);
```
Available log levels:
| Level | Description |
| ----- | ------------------------------------------------------- |
| Off | Nothing gets logged. |
| Error | Only error level events are logged. |
| Warn | Default. Errors and Warnings are logged. |
| Info | Errors, Warnings and feature flag evaluation is logged. |
| Debug | All of the above plus debug info is logged. |
Info level logging helps to inspect the feature flag evaluation process:
```bash
ConfigCat - INFO - [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"#SOME-USER-ID#","Email":"configcat@example.com"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
The SDK provides a simple logger implementation that logs to [the debugging console](https://developer.mozilla.org/en-US/docs/Web/API/console) (`configcat.createConsoleLogger(...)`) but it also allows you to inject any custom implementation of `IConfigCatLogger`.
```ts
class MyCustomLogger implements IConfigCatLogger {
/**
* Writes an event into the log.
* @param level Event severity level.
* @param eventId Event identifier.
* @param message Message.
* @param exception The exception object related to the message (if any).
*/
log(
level: LogLevel,
eventId: LogEventId,
message: LogMessage,
exception?: any,
): void {
// insert your custom log logic
}
}
```
or
```js
function MyCustomLogger() {}
MyCustomLogger.prototype.log = function (level, eventId, message, exception) {
// insert your custom log logic
};
```
then
```js
// Set the `MyCustomLogger` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
logger: new MyCustomLogger(),
},
);
```
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by providing a callback function via the `logFilter` option. The callback will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `IConfigCatLogger.level` property). That is, the callback allows you to filter log events by `level`, `eventId`, `message` or `exception`. The formatted message string can be obtained via `message.toString()`. If the callback function returns `true`, the event will be logged, otherwise it will be skipped.
```js
// Filter out events with id 1001 from the log.
const logFilter = (level, eventId, message, exception) => eventId != 1001;
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{
logFilter: logFilter
}
);
```
caution
Please make sure that your log filter logic doesn't perform heavy computation. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## `getAllKeysAsync()`[](#getallkeysasync "Direct link to getallkeysasync")
You can get the keys for all available feature flags and settings by calling the `getAllKeysAsync()` method.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
const keys = await configCatClient.getAllKeysAsync();
console.log(keys);
```
## `getAllValuesAsync()`[](#getallvaluesasync "Direct link to getallvaluesasync")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValuesAsync();
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValuesAsync(userObject);
settingValues.forEach((i) =>
console.log(i.settingKey + ' -> ' + i.settingValue),
);
```
## `getAllValueDetailsAsync()`[](#getallvaluedetailsasync "Direct link to getallvaluedetailsasync")
Evaluates and returns the values along with evaluation details of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```js
const configCatClient = configcat.getClient('#YOUR-SDK-KEY#');
let settingValues = await configCatClient.getAllValueDetailsAsync();
settingValues.forEach((details) => console.log(details));
// invoke with User Object
const userObject = { identifier: 'john@example.com' };
settingValues = await configCatClient.getAllValueDetailsAsync(userObject);
settingValues.forEach((details) => console.log(details));
```
## Using custom cache implementation[](#using-custom-cache-implementation "Direct link to Using custom cache implementation")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`IConfigCatCache`](https://github.com/configcat/js-unified-sdk/blob/master/src/ConfigCatCache.ts) interface and set the `cache` property in the options passed to `getClient`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
```ts
class MyCustomCache implements IConfigCatCache {
set(key: string, value: string): Promise | void {
// insert your cache write logic here
}
get(
key: string,
): Promise | string | null | undefined {
// insert your cache read logic here
}
}
```
or
```js
function MyCustomCache() {}
MyCustomCache.prototype.set = function (key, value) {
// insert your cache write logic here
};
MyCustomCache.prototype.get = function (key) {
// insert your cache read logic here
};
```
then
```js
// Set the `MyCustomCache` implementation on client creation.
const configCatClient = configcat.getClient(
'#YOUR-SDK-KEY#',
configcat.PollingMode.AutoPoll,
{
cache: new MyCustomCache(),
},
);
```
info
The JavaScript SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Sensitive information handling[](#sensitive-information-handling "Direct link to Sensitive information handling")
The frontend/mobile SDKs are running in your users' browsers/devices. The SDK is downloading a [config JSON](https://configcat.com/docs/requests.md) file from ConfigCat's CDN servers. The URL path for this config JSON file contains your SDK key, so the SDK key and the content of your config JSON file (feature flag keys, feature flag values, Targeting Rules, % rules) can be visible to your users. In ConfigCat, all SDK keys are read-only. They only allow downloading your config JSON files, but nobody can make any changes with them in your ConfigCat account.
If you do not want to expose the SDK key or the content of the config JSON file, we recommend using the SDK in your backend components only. You can always create a backend endpoint using the *ConfigCat SDK* that can evaluate feature flags for a specific user, and call that backend endpoint from your frontend/mobile applications.
Also, we recommend using [confidential targeting comparators](https://configcat.com/docs/targeting/targeting-rule/user-condition.md#confidential-text-comparators) in the Targeting Rules of those feature flags that are used in the frontend/mobile SDKs.
## Platform compatibility[](#platform-compatibility "Direct link to Platform compatibility")
The SDK should be compatible with latest versions of Deno.
The SDK is [tested](https://github.com/configcat/js-unified-sdk/blob/master/.github/workflows/js-sdk-ci.yml) against the following runtimes:
* Deno (v1.31, v1.46, latest stable) on Windows / Ubuntu / macOS
The SDK is compatible with TypeScript v4.0.2 or newer. Earlier versions may work but those are not tested, thus, not supported officially.
These tests are running on each pull request, before each deploy, and on a daily basis.
You can view a sample run [here](https://github.com/configcat/js-unified-sdk/actions/runs/11745259578).
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
* [Sample Deno console application](https://github.com/configcat/js-unified-sdk/tree/master/samples/deno-console)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat SDK for JavaScript on GitHub](https://github.com/configcat/js-unified-sdk)
* [ConfigCat SDK for JavaScript in NPM](https://www.npmjs.com/package/@configcat/sdk)
---
# Source: https://configcat.com/docs/api/reference/deselect-proxy-profile-sdk-keys.md
# Deselect SDK keys
Copy page
This endpoint removes the given list of Config / Environment pairs' SDK Keys from a Proxy Profile identified by the `proxyProfileId`.
## Request[](#request "Direct link to Request")
## Responses[](#responses "Direct link to Responses")
* 200
* 400
* 403
* 404
* 429
When the deselection was successful.
Bad request.
Forbidden. When selection rules are applied to the Proxy Profile.
Not found.
Too many requests. In case of the request rate exceeds the rate limits.
---
# Source: https://configcat.com/docs/glossary/devops-engineer.md
# DevOps Engineer - The Backbone of Efficient Software Deployment
Copy page
## Introduction[](#introduction "Direct link to Introduction")
The role of a DevOps Engineer has become indispensable. Bridging the gap between software creation and its operational performance, a DevOps Engineer is a key player in the orchestration of code life cycles, ensuring that everything from development to deployment and beyond runs seamlessly. Let’s delve into what makes the DevOps Engineer role so vital.
## Who is a DevOps Engineer?[](#who-is-a-devops-engineer "Direct link to Who is a DevOps Engineer?")
A DevOps Engineer is a multi-faceted professional who specializes in the development (Dev) and operations (Ops) aspects of software engineering. Their responsibilities extend across the entire development pipeline, focusing on streamlining processes, enhancing performance, and ensuring the reliability of both software and infrastructure.
## Key Responsibilities of a DevOps Engineer[](#key-responsibilities-of-a-devops-engineer "Direct link to Key Responsibilities of a DevOps Engineer")
* **Development and Maintenance**: Spearheading the development of infrastructure and ensuring its robust maintenance.
* **Deployment**: Orchestrating the deployment process to ensure smooth and timely delivery of software.
* **Monitoring**: Vigilantly monitoring both software and infrastructure to preemptively identify and address issues.
* **Continuous Improvement**: Implementing strategies for continuous development, integration, and deployment.
* **Collaboration**: Acting as a bridge between various teams to foster a cohesive working environment.
## The Importance of DevOps Engineers[](#the-importance-of-devops-engineers "Direct link to The Importance of DevOps Engineers")
* **Efficiency**: By automating processes and improving communication between development and operations teams, DevOps Engineers significantly enhance efficiency.
* **Agility**: They enable organizations to respond swiftly to market changes and customer demands.
* **Reliability**: Through continuous monitoring and maintenance, they ensure that systems are robust and downtime is minimized.
* **Innovation**: By streamlining workflows, they provide more room for innovation and experimentation.
## Challenges Faced by DevOps Engineers and Solutions[](#challenges-faced-by-devops-engineers-and-solutions "Direct link to Challenges Faced by DevOps Engineers and Solutions")
* **Complex Workflows**: Handling intricate workflows can be challenging. Solution: Implementation of automation tools and clear communication channels.
* **Rapid Technology Changes**: Keeping pace with ever-evolving technologies. Solution: Continuous learning and adaptation.
* **Balancing Speed and Security**: Ensuring rapid deployment without compromising on security. Solution: Integrating security measures into the development process.
## Conclusion[](#conclusion "Direct link to Conclusion")
The DevOps Engineer is more than just a role; it’s a mindset that embodies efficiency, collaboration, and continuous improvement. In the current technological era, a proficient DevOps Engineer is not just an asset but a necessity for organizations aiming for resilience, agility, and sustained growth.
---
# Source: https://configcat.com/docs/advanced/team-management/domain-verification.md
# Domain Verification
Copy page
In order to use the [SAML Single Sign-On](https://configcat.com/docs/advanced/team-management/saml/saml-overview.md) and the [Auto-assign Users](https://configcat.com/docs/advanced/team-management/auto-assign-users.md) features, you have to verify the ownership of the domain that your company uses for email addresses.
## Steps to verify your domain[](#steps-to-verify-your-domain "Direct link to Steps to verify your domain")
* Open your organization's authentication settings on the [ConfigCat Dashboard](https://app.configcat.com/organization/authentication).

* Click `ADD & VERIFY DOMAIN`.

* Type your domain name, then click `ADD`

* Follow the instructions on the appearing dialog to verify your domain.

---
# Source: https://configcat.com/docs/sdk-reference/openfeature/dotnet.md
# Source: https://configcat.com/docs/sdk-reference/dotnet.md
# .NET SDK Reference
Copy page
[](https://github.com/configcat/.net-sdk/stargazers) [](https://github.com/configcat/.net-sdk/actions/workflows/dotnet-sdk-ci.yml) [](https://www.nuget.org/packages/ConfigCat.Client/) [](https://sonarcloud.io/project/overview?id=net-sdk) [](https://sonarcloud.io/dashboard?id=net-sdk)
[ConfigCat .NET SDK on GitHub](https://github.com/configcat/.net-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Install *ConfigCat SDK* [NuGet package](https://www.nuget.org/packages/ConfigCat.Client)[](#1-install-configcat-sdk-nuget-package "Direct link to 1-install-configcat-sdk-nuget-package")
* Powershell / NuGet Package Manager Console
* .NET CLI
```powershell
Install-Package ConfigCat.Client
```
```text
dotnet add package ConfigCat.Client
```
info
To get the *ConfigCat SDK* up and running in Unity, please refer to [this guide](https://configcat.com/docs/sdk-reference/unity.md).
### 2. Import package[](#2-import-package "Direct link to 2. Import package")
```csharp
using ConfigCat.Client;
```
### 3. Create the *ConfigCat* client with your *SDK Key*[](#3-create-the-configcat-client-with-your-sdk-key "Direct link to 3-create-the-configcat-client-with-your-sdk-key")
```csharp
var client = ConfigCatClient.Get("#YOUR-SDK-KEY#");
```
### 4. Get your setting value[](#4-get-your-setting-value "Direct link to 4. Get your setting value")
```csharp
var isMyAwesomeFeatureEnabled = await client.GetValueAsync("isMyAwesomeFeatureEnabled", false);
if (isMyAwesomeFeatureEnabled)
{
doTheNewThing();
}
else
{
doTheOldThing();
}
```
The *ConfigCat SDK* also offers a synchronous API for feature flag evaluation. Read more [here](#snapshots-and-non-blocking-synchronous-feature-flag-evaluation).
### 5. Dispose the *ConfigCat* client[](#5-dispose-the-configcat-client "Direct link to 5-dispose-the-configcat-client")
You can safely dispose all clients at once or individually and release all associated resources on application exit.
```csharp
ConfigCatClient.DisposeAll(); // disposes all clients
// -or-
client.Dispose(); // disposes a specific client
```
## Creating the *ConfigCat Client*[](#creating-the-configcat-client "Direct link to creating-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`ConfigCatClient.Get(sdkKey: "")` returns a client with default options.
### Customizing the *ConfigCat Client*[](#customizing-the-configcat-client "Direct link to customizing-the-configcat-client")
To customize the SDK's behavior, you can pass an additional `Action` parameter to the `Get()` static factory method where the `ConfigCatClientOptions` class is used to set up the *ConfigCat Client*.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.PollingMode = PollingModes.ManualPoll;
options.Logger = new ConsoleLogger(LogLevel.Info);
});
```
These are the available options on the `ConfigCatClientOptions` class:
| Properties | Description | Default |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `PollingMode` | Optional, sets the polling mode for the client. [More about polling modes](#polling-modes). | `PollingModes.AutoPoll()` |
| `ConfigFetcher` | Optional, [`IConfigCatConfigFetcher`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/ConfigService/IConfigCatConfigFetcher.cs) instance for downloading a config. | [`HttpClientConfigFetcher`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/ConfigService/HttpClientConfigFetcher.cs) |
| `ConfigCache` | Optional, [`IConfigCatCache`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/Cache/IConfigCatCache.cs) instance for caching the downloaded config. | [`InMemoryConfigCache`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/Cache/InMemoryConfigCache.cs) |
| `Logger` | Optional, [`IConfigCatLogger`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/Logging/IConfigCatLogger.cs) instance for tracing. | [`ConsoleLogger`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/Logging/ConsoleLogger.cs) (with WARNING level) |
| `LogFilter` | Optional, sets a custom log filter. [More about log filtering](#log-filtering). | `null` (none) |
| `BaseUrl` | Optional, sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. | |
| `HttpClientHandler` | Optional, `HttpClientHandler` to provide network credentials and proxy settings. [More about the proxy settings](#using-configcat-behind-a-proxy). | built-in `HttpClientHandler` |
| `HttpTimeout` | Optional, sets the underlying HTTP client's timeout. [More about the HTTP timeout](#http-timeout). | `TimeSpan.FromSeconds(30)` |
| `FlagOverrides` | Optional, sets the local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides). | |
| `DataGovernance` | Optional, describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `Global`, `EuOnly` | `Global` |
| `DefaultUser` | Optional, sets the default user. [More about default user](#default-user). | `null` (none) |
| `Offline` | Optional, determines whether the client should be initialized to offline mode. [More about offline mode](#online--offline-mode). | `false` |
Via the events provided by `ConfigCatClientOptions` you can also subscribe to the hooks (events) at the time of initialization. [More about hooks](#hooks).
For example:
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.ClientReady += (s, e) =>
{
var keys = ((IConfigCatClient)s).Snapshot().GetAllKeys();
Console.WriteLine("Client is ready! Number of available feature flags: " + keys.Count);
};
});
```
info
You can acquire singleton client instances for your SDK keys using the `ConfigCatClient.Get(sdkKey: "")` static factory method. (However, please keep in mind that subsequent calls to `ConfigCatClient.Get()` with the *same SDK Key* return a *shared* client instance, which was set up by the first call.)
You can close all open clients at once using the `ConfigCatClient.DisposeAll()` method or do it individually using the `client.Dispose()` method.
## Anatomy of `GetValueAsync()`[](#anatomy-of-getvalueasync "Direct link to anatomy-of-getvalueasync")
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```csharp
User userObject = new User("#UNIQUE-USER-IDENTIFIER#"); // Optional User Object
var value = await client.GetValueAsync("keyOfMyFeatureFlag", false, userObject);
```
caution
It is important to provide an argument for the `defaultValue` parameter, specifically for the `T` generic type parameter, that matches the type of the feature flag or setting you are evaluating. Please refer to the following table for the corresponding types.
### Setting type mapping[](#setting-type-mapping "Direct link to Setting type mapping")
| Setting Kind | Type parameter `T` |
| -------------- | --------------------------------- |
| On/Off Toggle | `bool` / `bool?` |
| Text | `string` / `string?` |
| Whole Number | `int` / `int?` / `long` / `long?` |
| Decimal Number | `double` / `double?` |
In addition to the types mentioned above, you also have the option to provide `object` or `object?` for the type parameter regardless of the setting kind. However, this approach is not recommended as it may involve [boxing](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing).
It's important to note that providing any other type for the type parameter will result in an `ArgumentException`.
If you specify an allowed type but it mismatches the setting kind, an error message will be logged and `defaultValue` will be returned.
When relying on type inference and not explicitly specifying the type parameter, be mindful of potential type mismatch issues, especially with number types. For example, `client.GetValueAsync("keyOfMyDecimalSetting", 0)` will return `defaultValue` (`0`) instead of the actual value of the decimal setting because the compiler infers the type as `int` instead of `double`, that is, the call is equivalent to `client.GetValueAsync("keyOfMyDecimalSetting", 0)`, which is a type mismatch.
To correctly evaluate a decimal setting, you should use:
```csharp
var value = await client.GetValueAsync("keyOfMyDecimalSetting", 0.0);
// -or-
var value = await client.GetValueAsync("keyOfMyDecimalSetting", 0d);
// -or-
var value = await client.GetValueAsync("keyOfMyDecimalSetting", 0);
```
## Anatomy of `GetValueDetailsAsync()`[](#anatomy-of-getvaluedetailsasync "Direct link to anatomy-of-getvaluedetailsasync")
`GetValueDetailsAsync()` is similar to `GetValueAsync()` but instead of returning the evaluated value only, it provides more detailed information about the evaluation result.
| Parameters | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `defaultValue` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
```csharp
User userObject = new User("#UNIQUE-USER-IDENTIFIER#"); // Optional User Object
var details = await client.GetValueDetailsAsync("keyOfMyFeatureFlag", false, userObject);
```
caution
It is important to provide an argument for the `defaultValue` parameter, specifically for the `T` generic type parameter, that matches the type of the feature flag or setting you are evaluating. Please refer to [this table](#setting-type-mapping) for the corresponding types.
The `details` result contains the following information:
| Field | Type | Description |
| ------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `Key` | `string` | The key of the evaluated feature flag or setting. |
| `Value` | `bool` / `string` / `int` / `double` | The evaluated value of the feature flag or setting. |
| `User` | `User` | The User Object used for the evaluation. |
| `IsDefaultValue` | `bool` | True when the default value passed to `GetValueDetailsAsync()` is returned due to an error. |
| `ErrorCode` | `EvaluationErrorCode` | In case of an error, this property contains a code that identifies the reason for the error. |
| `ErrorMessage` | `string` | In case of an error, this property contains the error message. |
| `ErrorException` | `Exception` | In case of an error, this property contains the related exception object (if any). |
| `MatchedTargetingRule` | `ITargetingRule` | The Targeting Rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `MatchedPercentageOption` | `IPercentageOption` | The Percentage Option (if any) that was used to select the evaluated value. |
| `FetchTime` | `DateTime` | The last download time (UTC) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
```csharp
User userObject = new User("#UNIQUE-USER-IDENTIFIER#");
```
```csharp
User userObject = new User("john@example.com");
```
| Parameters | Description |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `Id` | **REQUIRED.** Unique identifier of a user in your application. Can be any `string` value, even an email address. |
| `Email` | Optional parameter for easier Targeting Rule definitions. |
| `Country` | Optional parameter for easier Targeting Rule definitions. |
| `Custom` | Optional dictionary for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
```csharp
User userObject = new User("#UNIQUE-USER-IDENTIFIER#")
{
Email = "john@example.com",
Country = "United Kingdom",
Custom =
{
["SubscriptionType"] = "Pro",
["UserRole"] = "Admin"
}
};
```
The `Custom` dictionary also allows attribute values other than `string` values:
```csharp
User userObject = new User("#UNIQUE-USER-IDENTIFIER#")
{
Custom =
{
["Rating"] = 4.5,
["RegisteredAt"] = DateTimeOffset.Parse("2023-11-22 12:34:56 +00:00", CultureInfo.InvariantCulture),
["Roles"] = new[] { "Role1", "Role2" }
}
};
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `string` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS ONE OF, etc.)
* accept `string` values,
* all other values are automatically converted to `string` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS ONE OF, <, >=, etc.)
* accept `string` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (=, <, >=, etc.)
* accept `double` values and all other numeric values which can safely be converted to `double`,
* accept `string` values containing a properly formatted, valid `double` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE / AFTER)
* accept `DateTime` or `DateTimeOffset` values, which are automatically converted to a second-based Unix timestamp,
* accept `double` values representing a second-based Unix timestamp and all other numeric values which can safely be converted to `double`,
* accept `string` values containing a properly formatted, valid `double` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY CONTAINS ANY OF / ARRAY NOT CONTAINS ANY OF)
* accept arrays of `string`,
* accept `string` values containing a valid JSON string which can be deserialized to an array of `string`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
It's possible to set a default User Object that will be used on feature flag and setting evaluation. It can be useful when your application has a single user only or rarely switches users.
You can set the default User Object either on SDK initialization:
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
options.DefaultUser = new User(identifier: "john@example.com"));
```
...or using the `SetDefaultUser()` method of the `ConfigCatClient` object:
```csharp
client.SetDefaultUser(new User(identifier: "john@example.com"));
```
Whenever the evaluation methods like `GetValueAsync()`, `GetValueDetailsAsync()`, etc. are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```csharp
var user = new User(identifier: "john@example.com");
client.SetDefaultUser(user);
// The default user will be used in the evaluation process.
var value = await client.GetValueAsync(key: "keyOfMyFeatureFlag", defaultValue: false);
```
When a `user` parameter is passed to the evaluation methods, it takes precedence over the default user.
```csharp
var user = new User(identifier: "john@example.com");
client.SetDefaultUser(user);
var otherUser = new User(identifier: "brian@example.com");
// otherUser will be used in the evaluation process.
var value = await client.GetValueAsync(key: "keyOfMyFeatureFlag", defaultValue: false, user: otherUser);
```
You can also remove the default user by doing the following:
```csharp
client.ClearDefaultUser();
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `GetValueAsync()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle. [More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `pollInterval` option parameter to change the polling interval.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.PollingMode = PollingModes.AutoPoll(pollInterval: TimeSpan.FromSeconds(95));
});
```
Available options:
| Option Parameter | Description | Default |
| ----------------- | ---------------------------------------------------------------------------------------- | ------- |
| `pollInterval` | Polling interval. | 60s |
| `maxInitWaitTime` | Maximum waiting time between the client initialization and the first config acquisition. | 5s |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `GetValueAsync()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `GetValueAsync()` will return the setting value after the cache is updated.
Use `cacheTimeToLive` parameter to manage configuration lifetime.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.PollingMode = PollingModes.LazyLoad(cacheTimeToLive: TimeSpan.FromSeconds(600));
});
```
Available options:
| Option Parameter | Description | Default |
| ----------------- | ----------- | ------- |
| `cacheTimeToLive` | Cache TTL. | 60s |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `ForceRefreshAsync()` is your application's responsibility.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.PollingMode = PollingModes.ManualPoll;
});
await client.ForceRefreshAsync();
```
> `GetValueAsync()` returns `defaultValue` if the cache is empty. Call `ForceRefreshAsync()` to update the cache.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.PollingMode = PollingModes.ManualPoll;
});
Console.WriteLine(await client.GetValueAsync("keyOfMyTextSetting", "my default value")); // console: "my default value"
await client.ForceRefreshAsync();
Console.WriteLine(await client.GetValueAsync("keyOfMyTextSetting", "my default value")); // console: "value from server"
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. Via the following events you can subscribe to particular events raised by the *ConfigCat* client:
* `event EventHandler ClientReady`: This event is raised when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after the initial sync with the external cache (if any) completes.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `maxInitWaitTime` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the `CacheState` property of the event arguments.
* `event EventHandler ConfigFetched`: This event is raised each time the client attempts to refresh the cached config by fetching the latest version from the ConfigCat CDN. It is raised not only when `ForceRefreshAsync` is called but also when the refresh is initiated by the client automatically. Thus, this event allows you to observe potential network issues that occur under the hood.
* `event EventHandler ConfigChanged`: This event is raised first when the client's internal cache gets populated. Afterwards, it is raised again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `event EventHandler FlagEvaluated`: This event is raised each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`GetValueDetailsAsync()`](#anatomy-of-getvaluedetailsasync).
* `event EventHandler Error`: This event is raised when an error occurs within the client.
You can subscribe to these events either on initialization:
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.PollingMode = PollingModes.ManualPoll;
options.FlagEvaluated += (s, e) => { /* handle the event */ };
});
```
...or directly on the `ConfigCatClient` instance:
```csharp
client.FlagEvaluated += (s, e) => { /* handle the event */ };
```
caution
Some events (e.g. `ClientReady`, `ConfigChanged` and `Error`) may be raised before `ConfigCatClient.Get` returns. This means you may miss them unless you subscribe on initialization.
However, even if you do, there's another gotcha: it's not safe to use the outer `client` variable in your event handler because it may not yet be assigned when the handler is called. Instead, you can safely access the client instance via the sender parameter like `var client = (IConfigCatClient)s;`.
## Snapshots and non-blocking synchronous feature flag evaluation[](#snapshots-and-non-blocking-synchronous-feature-flag-evaluation "Direct link to Snapshots and non-blocking synchronous feature flag evaluation")
Currently, the *ConfigCat* client provides both asynchronous and synchronous methods for evaluating feature flags and settings. However, depending on the setup, the synchronous methods may block the executing thread for longer periods of time (e.g. when downloading config data from the ConfigCat CDN servers), which can lead to an unresponsive application. To prevent such issues, the problematic methods have been deprecated and are going to be removed in a future major version.
As an alternative, since v9.2.0, the .NET SDK provides a way to synchronously evaluate feature flags and settings as a non-blocking operation, via *snapshots*.
Using the `Snapshot()` method, you can capture the current state of the *ConfigCat* client (including the latest downloaded config data) and use the resulting snapshot object to synchronously evaluate feature flags and settings based on the captured state:
```csharp
using var client = ConfigCatClient.Get("#YOUR-SDK-KEY#",
options => options.PollingMode = PollingModes.AutoPoll());
// Wait for the client to initialize.
await client.WaitForReadyAsync();
var snapshot = client.Snapshot();
var user = new User("#UNIQUE-USER-IDENTIFIER#");
foreach (var key in snapshot.GetAllKeys())
{
var value = snapshot.GetValue(key, default(object), user);
Console.WriteLine($"{key}: {value}");
}
```
Creating a snapshot is a cheap operation. This is possible because snapshots capture the client's internal (in-memory) cache. No attempt is made to refresh the internal cache, even if it's empty or expired.
caution
Please note that creating and using a snapshot
* won't trigger a sync with the external cache when working with [shared caching](https://configcat.com/docs/advanced/caching.md#shared-cache),
* won't fetch the latest config data from the ConfigCat CDN when the internally cached config data is empty or expired.
For the above reasons, it's recommended to use snapshots in conjunction with the Auto Polling mode, where the SDK automatically updates the internal cache in the background. (For other polling modes, you'll need to manually initiate a cache refresh by calling `ForceRefreshAsync`.)
Because of this behavior, it's important to make sure that the client has completed initialization and populated its internal cache before creating snapshots. Otherwise the snapshot's evaluation methods won't have the data to do actual evaluation, but will just return the default value you pass to them. Which behavior is usually not what you want in your application.
In Auto Polling mode, you can use the `WaitForReadyAsync` method to wait for the latest config data to become available locally. This is an asynchronous operation, which completes as soon as the client reaches the ready state, i.e. completes initialization (or the time specified via the `maxInitWaitTime` option passes).
(Please note that this doesn't apply to other polling modes. In those cases, the client doesn't contact the ConfigCat CDN during initialization, so the ready state is reached as soon as the first sync with the external cache completes.)
Typically, you call `WaitForReadyAsync` and wait for its completion only once, in the initialization phase of your application.
caution
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. You can verify this by checking the return value.
```csharp
var clientCacheState = await client.WaitForReadyAsync();
if (clientCacheState == ClientCacheState.NoFlagData)
{
// Handle initialization failure (see below).
Console.WriteLine("ConfigCat client failed to obtain the config data during initialization.");
}
```
You have the following options to handle unsuccessful initialization:
* If it's acceptable for your application to start up and use the default values passed to the evaluation methods, you may log some warning (or skip the check altogether as the client will log warnings anyway), and let the application continue.
* Otherwise, you need to either terminate the application or continue waiting. The latter is an option because the client might be able to obtain the config data later, in the case of a transient problem like some temporary network issue. However, the *ConfigCat SDK* doesn't provide out-of-the-box support for this case currently. You can implement this logic by subscribing to the `ConfigChanged` hook and waiting for the first event.
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases where you want to prevent the SDK from making HTTP calls, you can switch it to offline mode:
```csharp
client.SetOffline();
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To switch the SDK back to online mode, do the following:
```csharp
client.SetOnline();
```
Using the `client.IsOffline` property you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`OverrideBehaviour.LocalOnly`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`OverrideBehaviour.LocalOverRemote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`OverrideBehaviour.RemoteOverLocal`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can load your feature flag & setting overrides from a file or from a simple `Dictionary` structure.
### JSON File[](#json-file "Direct link to JSON File")
The SDK can load your feature flag & setting overrides from a file. You can also specify whether the file should be reloaded when it gets modified.
#### File[](#file "Direct link to File")
```csharp
IConfigCatClient client = ConfigCatClient.Get("localhost", options =>
{
options.FlagOverrides = FlagOverrides.LocalFile(
"path/to/local_flags.json", // path to the file
true, // reload the file when it gets modified
OverrideBehaviour.LocalOnly
);
});
```
#### JSON File Structure[](#json-file-structure "Direct link to JSON File Structure")
The SDK supports 2 types of JSON structures to describe feature flags & settings.
##### 1. Simple (key-value) structure[](#1-simple-key-value-structure "Direct link to 1. Simple (key-value) structure")
```json
{
"flags": {
"enabledFeature": true,
"disabledFeature": false,
"intSetting": 5,
"doubleSetting": 3.14,
"stringSetting": "test"
}
}
```
##### 2. Complex (full-featured) structure[](#2-complex-full-featured-structure "Direct link to 2. Complex (full-featured) structure")
This is the same format that the SDK downloads from the ConfigCat CDN. It allows the usage of all features that are available on the ConfigCat Dashboard.
You can download your current config JSON from ConfigCat's CDN and use it as a baseline.
A convenient way to get the config JSON for a specific SDK Key is to install the [ConfigCat CLI](https://github.com/configcat/cli) tool and execute the following command:
```bash
configcat config-json get -f v6 -p {YOUR-SDK-KEY} > config.json
```
(Depending on your [Data Governance](https://configcat.com/docs/advanced/data-governance.md) settings, you may need to add the `--eu` switch.)
Alternatively, you can download the config JSON manually, based on your [Data Governance](https://configcat.com/docs/advanced/data-governance.md) settings:
* GLOBAL: `https://cdn-global.configcat.com/configuration-files/{YOUR-SDK-KEY}/config_v6.json`
* EU: `https://cdn-eu.configcat.com/configuration-files/{YOUR-SDK-KEY}/config_v6.json`
```json
{
"p": {
// hash salt, required only when confidential text comparator(s) are used
"s": "80xCU/SlDz1lCiWFaxIBjyJeJecWjq46T4eu6GtozkM="
},
"s": [ // array of segments
{
"n": "Beta Users", // segment name
"r": [ // array of User Conditions (there is a logical AND relation between the elements)
{
"a": "Email", // comparison attribute
"c": 0, // comparator (see below)
"l": [ // comparison value (see below)
"john@example.com", "jane@example.com"
]
}
]
}
],
"f": { // key-value map of feature flags & settings
"isFeatureEnabled": { // key of a particular flag / setting
"t": 0, // setting type, possible values:
// 0 -> on/off setting (feature flag)
// 1 -> text setting
// 2 -> whole number setting
// 3 -> decimal number setting
"r": [ // array of Targeting Rules (there is a logical OR relation between the elements)
{
"c": [ // array of conditions (there is a logical AND relation between the elements)
{
"u": { // User Condition
"a": "Email", // comparison attribute
"c": 2, // comparator, possible values and required comparison value types:
// 0 -> IS ONE OF (cleartext) + string array comparison value ("l")
// 1 -> IS NOT ONE OF (cleartext) + string array comparison value ("l")
// 2 -> CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 3 -> NOT CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 4 -> IS ONE OF (semver) + semver string array comparison value ("l")
// 5 -> IS NOT ONE OF (semver) + semver string array comparison value ("l")
// 6 -> < (semver) + semver string comparison value ("s")
// 7 -> <= (semver + semver string comparison value ("s")
// 8 -> > (semver) + semver string comparison value ("s")
// 9 -> >= (semver + semver string comparison value ("s")
// 10 -> = (number) + number comparison value ("d")
// 11 -> <> (number + number comparison value ("d")
// 12 -> < (number) + number comparison value ("d")
// 13 -> <= (number + number comparison value ("d")
// 14 -> > (number) + number comparison value ("d")
// 15 -> >= (number) + number comparison value ("d")
// 16 -> IS ONE OF (hashed) + string array comparison value ("l")
// 17 -> IS NOT ONE OF (hashed) + string array comparison value ("l")
// 18 -> BEFORE (UTC datetime) + second-based Unix timestamp number comparison value ("d")
// 19 -> AFTER (UTC datetime) + second-based Unix timestamp number comparison value ("d")
// 20 -> EQUALS (hashed) + string comparison value ("s")
// 21 -> NOT EQUALS (hashed) + string comparison value ("s")
// 22 -> STARTS WITH ANY OF (hashed) + string array comparison value ("l")
// 23 -> NOT STARTS WITH ANY OF (hashed) + string array comparison value ("l")
// 24 -> ENDS WITH ANY OF (hashed) + string array comparison value ("l")
// 25 -> NOT ENDS WITH ANY OF (hashed) + string array comparison value ("l")
// 26 -> ARRAY CONTAINS ANY OF (hashed) + string array comparison value ("l")
// 27 -> ARRAY NOT CONTAINS ANY OF (hashed) + string array comparison value ("l")
// 28 -> EQUALS (cleartext) + string comparison value ("s")
// 29 -> NOT EQUALS (cleartext) + string comparison value ("s")
// 30 -> STARTS WITH ANY OF (cleartext) + string array comparison value ("l")
// 31 -> NOT STARTS WITH ANY OF (cleartext) + string array comparison value ("l")
// 32 -> ENDS WITH ANY OF (cleartext) + string array comparison value ("l")
// 33 -> NOT ENDS WITH ANY OF (cleartext + string array comparison value ("l")
// 34 -> ARRAY CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 35 -> ARRAY NOT CONTAINS ANY OF (cleartext) + string array comparison value ("l")
"l": [ // comparison value - depending on the comparator, another type of value may need
// to be specified (see above):
// "s": string
// "d": number
"@example.com"
]
}
},
{
"p": { // Flag Condition (Prerequisite)
"f": "mainIntFlag", // key of prerequisite flag
"c": 0, // comparator, possible values: 0 -> EQUALS, 1 -> NOT EQUALS
"v": { // comparison value (value's type must match the prerequisite flag's type)
"i": 42
}
}
},
{
"s": { // Segment Condition
"s": 0, // segment index, a valid index into the top-level segment array ("s")
"c": 1 // comparator, possible values: 0 -> IS IN SEGMENT, 1 -> IS NOT IN SEGMENT
}
}
],
"s": { // alternatively, an array of Percentage Options ("p", see below) can also be specified
"v": { // the value served when the rule is selected during evaluation
"b": true
},
"i": "bcfb84a7"
}
}
],
"p": [ // array of Percentage Options
{
"p": 10, // % value
"v": { // the value served when the Percentage Option is selected during evaluation
"b": true
},
"i": "bcfb84a7"
},
{
"p": 90,
"v": {
"b": false
},
"i": "bddac6ae"
}
],
"v": { // fallback value, served when none of the Targeting Rules match,
// no Percentage Options are defined or evaluation of these is not possible
"b": false // depending on the setting type, another type of value may need to be specified:
// text setting -> "s": string
// whole number setting -> "i": number
// decimal number setting -> "d": number
},
"i": "430bded3" // variation id (for analytical purposes)
}
}
}
```
For a more comprehensive specification of the config JSON v6 format, you may refer to [this JSON schema document](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
### Dictionary[](#dictionary "Direct link to Dictionary")
You can set up the SDK to load your feature flag & setting overrides from a `Dictionary`.
```csharp
var dictionary = new Dictionary
{
{"enabledFeature", true},
{"disabledFeature", false},
{"intSetting", 5},
{"doubleSetting", 3.14},
{"stringSetting", "test"},
};
IConfigCatClient client = ConfigCatClient.Get("localhost", options =>
{
options.FlagOverrides = FlagOverrides.LocalDictionary(dictionary, OverrideBehaviour.LocalOnly);
});
```
## Logging[](#logging "Direct link to Logging")
### Setting log level[](#setting-log-level "Direct link to Setting log level")
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#");
client.LogLevel = LogLevel.Info;
```
Available log levels:
| Level | Description |
| ------- | ------------------------------------------------------- |
| Off | Nothing is logged. |
| Error | Only error level events are logged. |
| Warning | Default. Errors and Warnings are logged. |
| Info | Errors, Warnings and feature flag evaluation is logged. |
| Debug | All of the above plus debug info is logged. |
Info level logging helps to inspect the feature flag evaluation process:
```bash
ConfigCat.INFO [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"","Email":"configcat@example.com","Country":"US","SubscriptionType":"Pro","Role":"Admin","version":"1.0.0"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'False' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'True' => MATCH, applying rule
Returning 'True'.
```
### Custom logger implementation[](#custom-logger-implementation "Direct link to Custom logger implementation")
By default, the SDK logs to [the console's standard output](https://learn.microsoft.com/en-us/dotnet/api/system.console.out) but it also allows you to inject any custom logger implementation via the `ConfigCatClientOptions.Logger` property.
Sample code on how to create a basic file logger implementation for ConfigCat client: [See Sample Code](https://github.com/configcat/.net-sdk/blob/master/samples/FileLoggerSample.cs)
Another sample which shows how to implement an adapter to [the built-in logging framework](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging) of .NET Core/.NET 5+: [See Sample Code](https://github.com/configcat/.net-sdk/blob/master/samples/ASP.NETCore/WebApplication/Adapters/ConfigCatToMSLoggerAdapter.cs)
### Log Filtering[](#log-filtering "Direct link to Log Filtering")
You can define a custom log filter by providing a callback function via the `ConfigCatClientOptions.LogFilter` property. The callback will be called by the *ConfigCat SDK* each time a log event occurs (and the event passes the minimum log level specified by the `IConfigCatLogger.LogLevel` property). That is, the callback allows you to filter log events by `level`, `eventId`, `message` or `exception`. The formatted message string can be obtained via `message.InvariantFormattedMessage`. If the callback function returns `true`, the event will be logged, otherwise it will be skipped.
```cs
// Filter out events with id 1001 from the log.
LogFilterCallback logFilter = (LogLevel level, LogEventId eventId, ref FormattableLogMessage message, Exception? exception) => eventId != 1001;
var client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options => options.LogFilter = logFilter);
```
caution
Please make sure that your log filter logic doesn't perform heavy computation and doesn't block the executing thread. A complex or incorrectly implemented log filter can degrade the performance of the SDK.
## `GetAllKeysAsync()`[](#getallkeysasync "Direct link to getallkeysasync")
You can get the keys for all available feature flags and settings by calling the `GetAllKeysAsync()` method of the `ConfigCatClient`.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#");
IEnumerable keys = await client.GetAllKeysAsync();
```
## `GetAllValuesAsync()`[](#getallvaluesasync "Direct link to getallvaluesasync")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#");
IDictionary settingValues = await client.GetAllValuesAsync();
// invoke with User Object
User userObject = new User("#UNIQUE-USER-IDENTIFIER#");
IDictionary settingValuesTargeting = await client.GetAllValuesAsync(userObject);
```
## `GetAllValueDetailsAsync()`[](#getallvaluedetailsasync "Direct link to getallvaluedetailsasync")
Evaluates and returns the values along with evaluation details of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#");
IReadOnlyList settingValues = await client.GetAllValueDetailsAsync();
// invoke with User Object
User userObject = new User("435170f4-8a8b-4b67-a723-505ac7cdea92");
IReadOnlyList settingValuesTargeting = await client.GetAllValueDetailsAsync(userObject);
```
## Using custom cache implementation[](#using-custom-cache-implementation "Direct link to Using custom cache implementation")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`IConfigCatCache`](https://github.com/configcat/.net-sdk/blob/master/src/ConfigCatClient/Cache/IConfigCatCache.cs) interface and set the `ConfigCache` parameter in the setup callback of `ConfigCatClient.Get`. This allows you to seamlessly integrate ConfigCat with your existing caching infrastructure.
```csharp
public class MyCustomCache : IConfigCatCache
{
public string? Get(string key)
{
/* insert your synchronous cache read logic here */
}
public Task GetAsync(string key, CancellationToken cancellationToken = default)
{
/* insert your asynchronous cache read logic here */
}
public void Set(string key, string value)
{
/* insert your synchronous cache write logic here */
}
public Task SetAsync(string key, string value, CancellationToken cancellationToken = default)
{
/* insert your asynchronous cache write logic here */
}
}
```
then
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.ConfigCache = new MyCustomCache()
});
```
info
The .NET SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
## Using ConfigCat behind a proxy[](#using-configcat-behind-a-proxy "Direct link to Using ConfigCat behind a proxy")
Provide your own network credentials (username/password) and proxy server settings (proxy server/port) by setting the `HttpClientHandler` property in the setup callback of `ConfigCatClient.Get`.
```csharp
var myProxySettings = new WebProxy(proxyHost, proxyPort)
{
UseDefaultCredentials = false,
Credentials = new NetworkCredential(proxyUserName, proxyPassword)
};
var myHttpClientHandler = new HttpClientHandler { Proxy = myProxySettings };
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.HttpClientHandler = myHttpClientHandler;
});
```
## HTTP Timeout[](#http-timeout "Direct link to HTTP Timeout")
You can set the maximum wait time for a ConfigCat HTTP response.
```csharp
IConfigCatClient client = ConfigCatClient.Get("#YOUR-SDK-KEY#", options =>
{
options.HttpTimeout = TimeSpan.FromSeconds(10);
});
```
The default timeout is 30 seconds.
## Platform compatibility[](#platform-compatibility "Direct link to Platform compatibility")
The *ConfigCat SDK* supports all the widespread .NET JIT runtimes, everything that implements [.NET Standard 2.0](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0)+ and supports TLS 1.2 should work. Starting with v9.3.0, it can also be used in applications that employ [trimmed self-contained](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained) or various [ahead-of-time (AOT) compilation](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) deployment models.
Based on our tests, the SDK is compatible with the following runtimes/deployment models:
* .NET Framework 4.5+ (including Ngen)
* .NET Core 3.1, .NET 5+ (including Crossgen2/ReadyToRun and Native AOT)
* Mono 5.10+
* .NET for Android (formerly known as Xamarin.Android)
* .NET for iOS (formerly known as Xamarin.iOS)
* Unity 2021.3+ (Mono JIT)
* Unity 2021.3+ (IL2CPP)\*
* Universal Windows Platform 10.0.16299.0+ (.NET Native)\*\*
* WebAssembly (Mono AOT/Emscripten, also known as wasm-tools)
\*Unity WebGL also works but needs a bit of extra effort: you will need to enable WebGL compatibility by calling the `ConfigCatClient.PlatformCompatibilityOptions.EnableUnityWebGLCompatibility` method. For more details, see [Sample Scripts](https://github.com/configcat/.net-sdk/tree/master/samples/UnityWebGL).
\*\*To make the SDK work in Release builds on UWP, you will need to add `` to your application's [.rd.xml](https://learn.microsoft.com/en-us/windows/uwp/dotnet-native/runtime-directives-rd-xml-configuration-file-reference) file. See also [this discussion](https://github.com/dotnet/runtime/issues/29912#issuecomment-638471351).
info
We strive to provide an extensive support for the various .NET runtimes and versions. If you still encounter an issue with the SDK on some platform, please open a [GitHub issue](https://github.com/configcat/.net-sdk/issues/new/choose) or [contact support](https://configcat.com/support).
## Troubleshooting[](#troubleshooting "Direct link to Troubleshooting")
When the *ConfigCat SDK* does not work as expected in your application, please check for the following potential problems:
* **Symptom:** Instead of the actual value, the default one is constantly returned by `GetValueAsync()` and the log contains the following message (provided that the client is set up to log error level events as described [here](#logging)): "Secure connection could not be established. Please make sure that your application is enabled to use TLS 1.2+."
**Problem:** ConfigCat CDN servers require TLS 1.2 or newer security protocol for communication. As for allowed security protocols, please keep in mind that newer .NET runtimes rely on operating system settings, older versions, however, may need additional setup to make secure communication with the CDN servers work.
| Runtime Version | Default Protocols |
| -------------------------------------------- | ---------------------- |
| .NET Framework 4.5 and earlier | SSL 3.0, TLS 1.0 |
| .NET Framework 4.6 | TLS 1.0, 1.1, 1.2, 1.3 |
| .NET Framework 4.7+, .NET Core 1.0+, .NET 5+ | System (OS) Defaults |
As shown in the table above, if your application runs on .NET Framework 4.5, by default it will fail to establish a connection to the CDN servers. Read [this](https://stackoverflow.com/a/58195987/8656352) for more details.
**Solution**: The best solution to the problem is to upgrade your application to target a newer runtime but in case that is not possible, you can use the following workaround:
```csharp
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
```
(Place this code at the startup of your application, **before** any instances of `ConfigCatClient` is created.)
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
Check out our Sample Applications how they use the *ConfigCat SDK*:
* [Sample Console App](https://github.com/configcat/.net-sdk/tree/master/samples/ConsoleApp)
* [Sample Multi-page Web App (ASP.NET Core MVC)](https://github.com/configcat/.net-sdk/tree/master/samples/ASP.NETCore)
* [Sample Single-page Web App (ASP.NET Core Blazor WebAssembly)](https://github.com/configcat/.net-sdk/tree/master/samples/BlazorWasm)
* [Sample Mobile/Windows Store App (.NET MAUI)](https://github.com/configcat/.net-sdk/tree/master/samples/MAUI)
## Guides[](#guides "Direct link to Guides")
See the following guides on how to use ConfigCat's .NET SDK:
* [.NET 6](https://configcat.com/blog/2022/11/25/feature-flags-in-net6/)
* [ASP.NET Core](https://configcat.com/blog/2021/10/10/aspnetcore-options-pattern/)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat .NET SDK on GitHub](https://github.com/configcat/.net-sdk)
* [ConfigCat .NET SDK on nuget.org](https://www.nuget.org/packages/ConfigCat.Client)
---
# Source: https://configcat.com/docs/sdk-reference/elixir.md
# Elixir SDK Reference
Copy page
[](https://github.com/configcat/elixir-sdk/stargazers) [](https://github.com/configcat/elixir-sdk/actions/workflows/elixir-ci.yml) [](https://codecov.io/github/configcat/elixir-sdk?branch=main) [](https://hex.pm/packages/configcat) [](https://hexdocs.pm/configcat/) [](https://hex.pm/packages/configcat) [](https://hex.pm/packages/configcat) [](https://github.com/configcat/elixir-sdk/commits/main)
[ConfigCat Elixir SDK on GitHub](https://github.com/configcat/elixir-sdk)
## Getting started[](#getting-started "Direct link to Getting started")
### 1. Add `configcat` to your list of dependencies in `mix.exs`[](#1-add-configcat-to-your-list-of-dependencies-in-mixexs "Direct link to 1-add-configcat-to-your-list-of-dependencies-in-mixexs")
```elixir
def deps do
[
{:configcat, "~> 4.0.0"}
]
end
```
### 2. Add `ConfigCat` to your application Supervisor tree[](#2-add-configcat-to-your-application-supervisor-tree "Direct link to 2-add-configcat-to-your-application-supervisor-tree")
```elixir
def start(_type, _args) do
children = [
{ConfigCat, [sdk_key: "#YOUR-SDK-KEY#"]},
MyApp
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
```
### 3. Get your setting value[](#3-get-your-setting-value "Direct link to 3. Get your setting value")
```elixir
isMyAwesomeFeatureEnabled = ConfigCat.get_value("isMyAwesomeFeatureEnabled", false)
if isMyAwesomeFeatureEnabled do
do_the_new_thing()
else
do_the_old_thing()
end
```
## Setting up the *ConfigCat Client*[](#setting-up-the-configcat-client "Direct link to setting-up-the-configcat-client")
*ConfigCat Client* is responsible for:
* managing the communication between your application and ConfigCat servers.
* caching your setting values and feature flags.
* serving values quickly in a failsafe way.
`{ConfigCat, options}` returns a client with default options.
| Properties | Description |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sdk_key` | **REQUIRED.** SDK Key to access your feature flags and settings. Get it from the *ConfigCat Dashboard*. |
| `base_url` | Sets the CDN base url (forward proxy, dedicated subscription) from where the SDK will download the config JSON. |
| `data_governance` | Describes the location of your feature flag and setting data within the ConfigCat CDN. This parameter needs to be in sync with your Data Governance preferences. Defaults to `:global`. [More about Data Governance](https://configcat.com/docs/advanced/data-governance.md). Available options: `:global`, `:eu_only`. |
| `cache_policy` | `CachePolicy.auto/1`, `CachePolicy.lazy/1` and `CachePolicy.manual/0`. Defaults to: `CachePolicy.auto/0` See [See below](#polling-modes) for details. |
| `cache` | Caching module you want `configcat` to use. Defaults to: `ConfigCat.InMemoryCache`. [More about cache](#custom-cache-behaviour-with-cache-option-parameter). |
| `http_proxy` | Specify this option if you need to use a proxy server to access your ConfigCat settings. You can provide a simple URL, like `https://my_proxy.example.com` or include authentication information, like `https://user:password@my_proxy.example.com/`. |
| `connect_timeout_milliseconds` | Timeout for establishing a TCP or SSL connection, in milliseconds. Default is 8000. |
| `read_timeout_milliseconds` | Timeout for receiving an HTTP response from the socket, in milliseconds. Default is 5000. |
| `flag_overrides` | Local feature flag & setting overrides. [More about feature flag overrides](#flag-overrides) |
| `default_user` | Sets the default user. [More about default user](#default-user). |
| `offline` | Defaults to `false`. Indicates whether the SDK should be initialized in offline mode. [More about offline mode](#online--offline-mode). |
| `hooks` | Used to subscribe events that the SDK sends in specific scenarios. [More about hooks](#hooks). |
| `name` | A unique identifier for this instance of `ConfigCat`. Defaults to `ConfigCat`. Must be provided if you need to run more than one instance of `ConfigCat` in the same application. If you provide a `name`, you must then pass that name to all of the API functions using the `client` option. [More about multiple instances](#multiple-configcat-instances). |
## Anatomy of `get_value()`[](#anatomy-of-get_value "Direct link to anatomy-of-get_value")
| Parameters | Description |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `default_value` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *ConfigCat.User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
| `client` | If you are running multiple instances of `ConfigCat`, provide the `client: :unique_name` option, specifying the name of the instance which you want to access. |
```elixir
value = ConfigCat.get_value(
"keyOfMySetting", # Setting Key
false, # Default value
ConfigCat.User.new("#UNIQUE-USER-IDENTIFIER#") # Optional User Object
)
```
## Anatomy of `get_value_details()`[](#anatomy-of-getvaluedetails "Direct link to anatomy-of-getvaluedetails")
`get_value_details()` is similar to `get_value()` but instead of returning the evaluated value only, it gives more detailed information about the evaluation result.
| Parameters | Description |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key` | **REQUIRED.** The key of a specific setting or feature flag. Set on *ConfigCat Dashboard* for each setting. |
| `default_value` | **REQUIRED.** This value will be returned in case of an error. |
| `user` | Optional, *User Object*. Essential when using Targeting. [Read more about Targeting.](https://configcat.com/docs/targeting/targeting-overview.md) |
| `client` | If you are running multiple instances of `ConfigCat`, provide the `client: :unique_name` option, specifying the name of the instance which you want to access. |
```elixir
details = ConfigCat.get_value_details(
"keyOfMySetting", # Setting Key
false, # Default value
ConfigCat.User.new("#UNIQUE-USER-IDENTIFIER#") # Optional User Object
)
```
The `details` result contains the following information:
| Field | Description |
| --------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `value` | The evaluated value of the feature flag or setting. |
| `key` | The key of the evaluated feature flag or setting. |
| `default_value?` | True when the default value passed to `get_value_details()` is returned due to an error. |
| `error` | In case of an error, this field contains the error message. |
| `user` | The User Object that was used for evaluation. |
| `matched_targeting_rule` | The targeting rule (if any) that matched during the evaluation and was used to return the evaluated value. |
| `matched_percentage_option` | The percentage option (if any) that was used to select the evaluated value. |
| `fetch_time` | The last download time (UTC DateTime) of the current config. |
## User Object[](#user-object "Direct link to User Object")
The [User Object](https://configcat.com/docs/targeting/user-object.md) is essential if you'd like to use ConfigCat's [Targeting](https://configcat.com/docs/targeting/targeting-overview.md) feature.
```elixir
user_object = ConfigCat.User.new("#UNIQUE-USER-IDENTIFIER#")
user_object = ConfigCat.User.new("john@example.com")
```
| Parameters | Description |
| ------------ | -------------------------------------------------------------------------------------------------------------------------- |
| `identifier` | **REQUIRED.** Unique identifier of a user in your application. Can be any `String` value, even an email address. |
| `email` | Optional parameter for easier Targeting Rule definitions. |
| `country` | Optional parameter for easier Targeting Rule definitions. |
| `custom` | Optional `Map` for custom attributes of a user for advanced Targeting Rule definitions. E.g. User role, Subscription type. |
```elixir
user_object = ConfigCat.User.new("#UNIQUE-USER-IDENTIFIER#", email: "john@example", country: "United Kingdom",
custom: %{SubscriptionType: "Pro", UserRole: "Admin"})
```
The `custom` dictionary also allows attribute values other than `String` values:
```elixir
user_object = ConfigCat.User.new(
"#UNIQUE-USER-IDENTIFIER#",
custom: %{
"Rating" => 4.5,
"RegisteredAt" => ~U[2023-09-19T11:01:35.999Z],
"Roles" => [ "Role1", "Role2" ]
}
)
```
### User Object Attribute Types[](#user-object-attribute-types "Direct link to User Object Attribute Types")
All comparators support `String` values as User Object attribute (in some cases they need to be provided in a specific format though, see below), but some of them also support other types of values. It depends on the comparator how the values will be handled. The following rules apply:
**Text-based comparators** (EQUALS, IS\_ONE\_OF, etc.)
* accept `String` values,
* all other values are automatically converted to `String` (a warning will be logged but evaluation will continue as normal).
**SemVer-based comparators** (IS\_ONE\_OF\_SEMVER, LESS\_THAN\_SEMVER, GREATER\_THAN\_SEMVER, etc.)
* accept `String` values containing a properly formatted, valid semver value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Number-based comparators** (EQUALS\_NUMBER, LESS\_THAN\_NUMBER, GREATER\_THAN\_OR\_EQUAL\_NUMBER, etc.)
* accept `Float` values and all other numeric values which can safely be converted to `Float`,
* accept `String` values containing a properly formatted, valid `Float` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**Date time-based comparators** (BEFORE\_DATETIME / AFTER\_DATETIME)
* accept `DateTime` and `NaiveDateTime` values, which are automatically converted to a second-based Unix timestamp (`NaiveDateTime` values are considered to be in UTC),
* accept `Float` values representing a second-based Unix timestamp and all other numeric values which can safely be converted to `Float`,
* accept `String` values containing a properly formatted, valid `Float` value,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
**String array-based comparators** (ARRAY\_CONTAINS\_ANY\_OF / ARRAY\_NOT\_CONTAINS\_ANY\_OF)
* accept arrays of `String`,
* accept `String` values containing a valid JSON string which can be deserialized to an array of `String`,
* all other values are considered invalid (a warning will be logged and the currently evaluated Targeting Rule will be skipped).
### Default user[](#default-user "Direct link to Default user")
There's an option to set a default User Object that will be used at feature flag and setting evaluation. It can be useful when your application has a single user only, or rarely switches users.
You can set the default User Object either on SDK initialization:
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
default_user: ConfigCat.User.new("john@example.com")
]}
```
or with the `set_default_user` method of the ConfigCat client.
```elixir
ConfigCat.set_default_user(ConfigCat.User.new("john@example.com"))
```
Whenever the `get_value`, `get_value_details`, `get_variation_id`, `get_all_variation_ids`, or `get_all_values` methods are called without an explicit `user` parameter, the SDK will automatically use the default user as a User Object.
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
default_user: ConfigCat.User.new("john@example.com")
]}
```
```elixir
# The default user will be used in the evaluation process.
value = ConfigCat.get_value("keyOfMySetting", false)
```
When the `user` parameter is specified on the requesting method, it takes precedence over the default user.
```elixir
other_user = ConfigCat.User.new("brian@example.com")
# otherUser will be used in the evaluation process.
value = ConfigCat.get_value("keyOfMySetting", false, other_user)
```
For deleting the default user, you can do the following:
```elixir
ConfigCat.clear_default_user()
```
## Polling Modes[](#polling-modes "Direct link to Polling Modes")
The *ConfigCat SDK* supports 3 different polling strategies to fetch feature flags and settings from the ConfigCat CDN. Once the latest data is downloaded, it is stored in the cache, then calls to `get_value()` use the cached data to evaluate feature flags and settings. With the following polling modes, you can customize the SDK to best fit to your application's lifecycle.
[More about polling modes.](https://configcat.com/docs/advanced/caching.md)
### Auto polling (default)[](#auto-polling-default "Direct link to Auto polling (default)")
The *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN automatically every 60 seconds and stores it in the cache.
Use the `poll_interval_seconds` option parameter to change the polling interval.
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
cache_policy: ConfigCat.CachePolicy.auto(poll_interval_seconds: 60)
]},
```
Available options:
| Option Parameter | Description | Default |
| ---------------------------- | ---------------------------------------------------------------------------------------------------- | ------- |
| `poll_interval_seconds` | Polling interval. | 60 |
| `max_init_wait_time_seconds` | Maximum waiting time between the client initialization and the first config acquisition in secconds. | 5 |
### Lazy loading[](#lazy-loading "Direct link to Lazy loading")
When calling `get_value()`, the *ConfigCat SDK* downloads the latest config data from the ConfigCat CDN only if it is not already present in the cache, or if the cache has expired. In this case `get_value()` will return the setting value after the cache is updated.
Use `cache_refresh_interval_seconds` option parameter to set cache lifetime.
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
cache_policy: ConfigCat.CachePolicy.lazy(cache_refresh_interval_seconds: 300)
]}
```
Available options:
| Option Parameter | Description | Default |
| -------------------------------- | ----------- | ------- |
| `cache_refresh_interval_seconds` | Cache TTL. | 60 |
### Manual polling[](#manual-polling "Direct link to Manual polling")
Manual polling gives you full control over when the config data is downloaded from the ConfigCat CDN. The *ConfigCat SDK* will not download it automatically. Calling `force_refresh()` is your application's responsibility.
```elixir
ConfigCat.force_refresh()
```
> `get_value()` returns `default_value` if the cache is empty. Call `force_refresh()` to update the cache.
```elixir
value = ConfigCat.get_value("key", "my default value") # Returns "my default value"
ConfigCat.force_refresh()
value = ConfigCat.get_value("key", "my default value") # Returns "value from server"
```
### Custom cache behaviour with `cache:` option parameter[](#custom-cache-behaviour-with-cache-option-parameter "Direct link to custom-cache-behaviour-with-cache-option-parameter")
The *ConfigCat SDK* stores the downloaded config data in a local cache to minimize network traffic and enhance client performance. If you prefer to use your own cache solution, such as an external or distributed cache in your system, you can implement the [`ConfigCache`](https://github.com/configcat/elixir-sdk/blob/main/lib/config_cat/config_cache.ex) behaviour and provide the `cache` option when initializing the SDK. This allows you to integrate ConfigCat with your existing caching infrastructure seamlessly.
To be able to customize the caching layer, you need to implement the `ConfigCat.ConfigCache` behaviour:
```elixir
defmodule MyApp.CustomConfigCache do
alias ConfigCat.ConfigCache
@behaviour ConfigCache
@impl ConfigCache
def get(cache_key) do
# here you have to return with the cached value
end
@impl ConfigCache
def set(cache_key, value) do
# here you have to store the new value in the cache
end
end
```
Then use your custom cache implementation:
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
cache: MyApp.CustomConfigCache
]}
```
info
The Elixir SDK supports *shared caching*. You can read more about this feature and the required minimum SDK versions [here](https://configcat.com/docs/advanced/caching.md#shared-cache).
### Multiple `ConfigCat` instances[](#multiple-configcat-instances "Direct link to multiple-configcat-instances")
If you need to run more than one instance of `ConfigCat`, there are two ways you can do it.
#### Module-Based[](#module-based "Direct link to Module-Based")
You can create a module that uses ConfigCat and then call the ConfigCat API functions on that module. This is the recommended option, as it makes the calling code a bit clearer and simpler.
You can pass any of the options listed above as arguments to `use ConfigCat` or specify them in your supervisor. Arguments specified by the supervisor take precedence over those provided to `use ConfigCat`.
```elixir
# lib/my_app/first_flags.ex
defmodule MyApp.FirstFlags do
use ConfigCat, sdk_key: "sdk_key_1"
end
# lib/my_app/second_flags.ex
defmodule MyApp.SecondFlags do
use ConfigCat, sdk_key: "sdk_key_2"
end
# lib/my_app/application.ex
def start(_type, _args) do
children = [
# ... other children ...
FirstFlags,
SecondFlags,
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
# Calling code:
FirstFlags.get_value("someKey", "default value")
SecondFlags.get_value("otherKey", "other default")
```
#### Explicit Client[](#explicit-client "Direct link to Explicit Client")
If you prefer not to use the module-based solution, you can instead add multiple `ConfigCat` children to your application's supervision tree. You will need to give `ConfigCat` a unique `name` option for each, as well as using `Supervisor.child_spec/2` to provide a unique `id` for each instance. When calling the ConfigCat API functions, you'll pass a `client:` keyword argument with the unique `name` you gave to that instance.
```elixir
# lib/my_app/application.ex
def start(_type, _args) do
children = [
# ... other children ...
Supervisor.child_spec({ConfigCat, [sdk_key: "sdk_key_1", name: :first]}, id: :config_cat_1),
Supervisor.child_spec({ConfigCat, [sdk_key: "sdk_key_2", name: :second]}, id: :config_cat_2),
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
# Calling code:
ConfigCat.get_value("someKey", "default value", client: :first)
ConfigCat.get_value("otherKey", "other default", client: :second)
```
## Hooks[](#hooks "Direct link to Hooks")
The SDK provides several hooks (events), by means of which you can get notified of its actions. You can subscribe to the following events emitted by the *ConfigCat* client:
* `on_client_ready`: This event is emitted when the client reaches the ready state, i.e. completes initialization.
* If Lazy Loading or Manual Polling is used, it's considered ready right after instantiation.
* If Auto Polling is used, the ready state is reached as soon as
* the initial sync with the external cache yields up-to-date config data,
* otherwise, if the client is online (i.e. HTTP requests are allowed), the first config fetch operation completes (regardless of success or failure),
* or the time specified via Auto Polling's `max_init_wait_time_seconds` option has passed.
Reaching the ready state usually means the client is ready to evaluate feature flags and settings. However, please note that this is not guaranteed. In case of initialization failure or timeout, the internal cache may be empty or expired even after the ready state is reported. Alternatively, in Auto Polling mode, you can wait for the first `onConfigChanged` event to be notified when the internal cache is actually populated with config data.
* `on_config_changed(config: map())`: This event is emitted first when the client's internal cache gets populated. Afterwards, it is emitted again each time the internally cached config is updated to a newer version, either as a result of synchronization with the external cache, or as a result of fetching a newer version from the ConfigCat CDN.
* `on_flag_evaluated(evaluation_details: EvaluationDetails.t())`: This event is emitted each time the client evaluates a feature flag or setting. The event provides the same evaluation details that you would get from [`get_value_details`](#anatomy-of-getvaluedetails).
* `on_error(error: String.t())`: This event is emitted when an error occurs within the client.
You can subscribe to these events either on SDK initialization:
```elixir
def on_flag_evaluated(evaluation_details) do
# handle the event
end
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
hooks: [on_flag_evaluated: {__MODULE__, :on_flag_evaluated, []}]
]}
```
or with the `Hooks` property of the ConfigCat client:
```elixir
ConfigCat.Hooks.add_on_flag_evaluated({__MODULE__, :on_flag_evaluated, []})
```
A hook callback is either an anonymous function or a module/function name/extra\_arguments tuple. Each callback is passed specific arguments. These specific arguments are prepended to the extra arguments provided in the tuple (if any). For example, you might want to define a callback that sends a message to another process which the config changes. You can pass the pid of that process as an extra argument:
```elixir
def MyModule do
def subscribe_to_config_changes(subscriber_pid) do
ConfigCat.hooks()
|> ConfigCat.Hooks.add_on_config_changed({__MODULE__, :on_config_changed, [subscriber_pid]})
end
def on_config_changed(config, pid) do
send pid, {:config_changed, config}
end
end
```
## Online / Offline mode[](#online--offline-mode "Direct link to Online / Offline mode")
In cases when you'd want to prevent the SDK from making HTTP calls, you can put it in offline mode:
```elixir
ConfigCat.set_offline()
```
In offline mode, the SDK won't initiate HTTP requests and will work only from its cache.
To put the SDK back in online mode, you can do the following:
```elixir
ConfigCat.set_online()
```
> With `ConfigCat.offline?` you can check whether the SDK is in offline mode.
## Flag Overrides[](#flag-overrides "Direct link to Flag Overrides")
With flag overrides you can overwrite the feature flags & settings downloaded from the ConfigCat CDN with local values. Moreover, you can specify how the overrides should apply over the downloaded values. The following 3 behaviours are supported:
* **Local only** (`:local_only`): When evaluating values, the SDK will not use feature flags & settings from the ConfigCat CDN, but it will use all feature flags & settings that are loaded from local-override sources.
* **Local over remote** (`:local_over_remote`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the local-override version will take precedence.
* **Remote over local** (`:remote_over_local`): When evaluating values, the SDK will use all feature flags & settings that are downloaded from the ConfigCat CDN, plus all feature flags & settings that are loaded from local-override sources. If a feature flag or a setting is defined both in the downloaded and the local-override source then the downloaded version will take precedence.
You can set up the SDK to load your feature flag & setting overrides from a file or a map.
### JSON File[](#json-file "Direct link to JSON File")
The SDK can load your feature flag & setting overrides from a file.
#### File[](#file "Direct link to File")
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
flag_overrides: ConfigCat.LocalFileDataSource.new(
"path/to/the/local_flags.json", # path to the file
:local_only # local/offline mode
)
]}
```
#### JSON File Structure[](#json-file-structure "Direct link to JSON File Structure")
The SDK supports 2 types of JSON structures to describe feature flags & settings.
##### 1. Simple (key-value) structure[](#1-simple-key-value-structure "Direct link to 1. Simple (key-value) structure")
```json
{
"flags": {
"enabledFeature": true,
"disabledFeature": false,
"intSetting": 5,
"doubleSetting": 3.14,
"stringSetting": "test"
}
}
```
##### 2. Complex (full-featured) structure[](#2-complex-full-featured-structure "Direct link to 2. Complex (full-featured) structure")
This is the same format that the SDK downloads from the ConfigCat CDN. It allows the usage of all features that are available on the ConfigCat Dashboard.
You can download your current config JSON from ConfigCat's CDN and use it as a baseline.
A convenient way to get the config JSON for a specific SDK Key is to install the [ConfigCat CLI](https://github.com/configcat/cli) tool and execute the following command:
```bash
configcat config-json get -f v6 -p {YOUR-SDK-KEY} > config.json
```
(Depending on your [Data Governance](https://configcat.com/docs/advanced/data-governance.md) settings, you may need to add the `--eu` switch.)
Alternatively, you can download the config JSON manually, based on your [Data Governance](https://configcat.com/docs/advanced/data-governance.md) settings:
* GLOBAL: `https://cdn-global.configcat.com/configuration-files/{YOUR-SDK-KEY}/config_v6.json`
* EU: `https://cdn-eu.configcat.com/configuration-files/{YOUR-SDK-KEY}/config_v6.json`
```json
{
"p": {
// hash salt, required only when confidential text comparator(s) are used
"s": "80xCU/SlDz1lCiWFaxIBjyJeJecWjq46T4eu6GtozkM="
},
"s": [ // array of segments
{
"n": "Beta Users", // segment name
"r": [ // array of User Conditions (there is a logical AND relation between the elements)
{
"a": "Email", // comparison attribute
"c": 0, // comparator (see below)
"l": [ // comparison value (see below)
"john@example.com", "jane@example.com"
]
}
]
}
],
"f": { // key-value map of feature flags & settings
"isFeatureEnabled": { // key of a particular flag / setting
"t": 0, // setting type, possible values:
// 0 -> on/off setting (feature flag)
// 1 -> text setting
// 2 -> whole number setting
// 3 -> decimal number setting
"r": [ // array of Targeting Rules (there is a logical OR relation between the elements)
{
"c": [ // array of conditions (there is a logical AND relation between the elements)
{
"u": { // User Condition
"a": "Email", // comparison attribute
"c": 2, // comparator, possible values and required comparison value types:
// 0 -> IS ONE OF (cleartext) + string array comparison value ("l")
// 1 -> IS NOT ONE OF (cleartext) + string array comparison value ("l")
// 2 -> CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 3 -> NOT CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 4 -> IS ONE OF (semver) + semver string array comparison value ("l")
// 5 -> IS NOT ONE OF (semver) + semver string array comparison value ("l")
// 6 -> < (semver) + semver string comparison value ("s")
// 7 -> <= (semver + semver string comparison value ("s")
// 8 -> > (semver) + semver string comparison value ("s")
// 9 -> >= (semver + semver string comparison value ("s")
// 10 -> = (number) + number comparison value ("d")
// 11 -> <> (number + number comparison value ("d")
// 12 -> < (number) + number comparison value ("d")
// 13 -> <= (number + number comparison value ("d")
// 14 -> > (number) + number comparison value ("d")
// 15 -> >= (number) + number comparison value ("d")
// 16 -> IS ONE OF (hashed) + string array comparison value ("l")
// 17 -> IS NOT ONE OF (hashed) + string array comparison value ("l")
// 18 -> BEFORE (UTC datetime) + second-based Unix timestamp number comparison value ("d")
// 19 -> AFTER (UTC datetime) + second-based Unix timestamp number comparison value ("d")
// 20 -> EQUALS (hashed) + string comparison value ("s")
// 21 -> NOT EQUALS (hashed) + string comparison value ("s")
// 22 -> STARTS WITH ANY OF (hashed) + string array comparison value ("l")
// 23 -> NOT STARTS WITH ANY OF (hashed) + string array comparison value ("l")
// 24 -> ENDS WITH ANY OF (hashed) + string array comparison value ("l")
// 25 -> NOT ENDS WITH ANY OF (hashed) + string array comparison value ("l")
// 26 -> ARRAY CONTAINS ANY OF (hashed) + string array comparison value ("l")
// 27 -> ARRAY NOT CONTAINS ANY OF (hashed) + string array comparison value ("l")
// 28 -> EQUALS (cleartext) + string comparison value ("s")
// 29 -> NOT EQUALS (cleartext) + string comparison value ("s")
// 30 -> STARTS WITH ANY OF (cleartext) + string array comparison value ("l")
// 31 -> NOT STARTS WITH ANY OF (cleartext) + string array comparison value ("l")
// 32 -> ENDS WITH ANY OF (cleartext) + string array comparison value ("l")
// 33 -> NOT ENDS WITH ANY OF (cleartext + string array comparison value ("l")
// 34 -> ARRAY CONTAINS ANY OF (cleartext) + string array comparison value ("l")
// 35 -> ARRAY NOT CONTAINS ANY OF (cleartext) + string array comparison value ("l")
"l": [ // comparison value - depending on the comparator, another type of value may need
// to be specified (see above):
// "s": string
// "d": number
"@example.com"
]
}
},
{
"p": { // Flag Condition (Prerequisite)
"f": "mainIntFlag", // key of prerequisite flag
"c": 0, // comparator, possible values: 0 -> EQUALS, 1 -> NOT EQUALS
"v": { // comparison value (value's type must match the prerequisite flag's type)
"i": 42
}
}
},
{
"s": { // Segment Condition
"s": 0, // segment index, a valid index into the top-level segment array ("s")
"c": 1 // comparator, possible values: 0 -> IS IN SEGMENT, 1 -> IS NOT IN SEGMENT
}
}
],
"s": { // alternatively, an array of Percentage Options ("p", see below) can also be specified
"v": { // the value served when the rule is selected during evaluation
"b": true
},
"i": "bcfb84a7"
}
}
],
"p": [ // array of Percentage Options
{
"p": 10, // % value
"v": { // the value served when the Percentage Option is selected during evaluation
"b": true
},
"i": "bcfb84a7"
},
{
"p": 90,
"v": {
"b": false
},
"i": "bddac6ae"
}
],
"v": { // fallback value, served when none of the Targeting Rules match,
// no Percentage Options are defined or evaluation of these is not possible
"b": false // depending on the setting type, another type of value may need to be specified:
// text setting -> "s": string
// whole number setting -> "i": number
// decimal number setting -> "d": number
},
"i": "430bded3" // variation id (for analytical purposes)
}
}
}
```
For a more comprehensive specification of the config JSON v6 format, you may refer to [this JSON schema document](https://github.com/configcat/config-json/blob/main/V6/config.schema.json).
### Map[](#map "Direct link to Map")
You can set up the SDK to load your feature flag & setting overrides from a map.
```elixir
map = %{
"enabledFeature" => true,
"disabledFeature" => false,
"intSetting" => 5,
"doubleSetting" => 3.14,
"stringSetting" => "test"
}
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
flag_overrides: ConfigCat.LocalMapDataSource.new(map, :local_only)
]}
```
## Logging[](#logging "Direct link to Logging")
In the *ConfigCat SDK*, we use the default Elixir's [Logger](https://hexdocs.pm/logger/Logger.html) so you can customise as you like.
Debug level logging helps to inspect how a feature flag was evaluated:
```bash
[debug] [5000] Evaluating 'isPOCFeatureEnabled' for User '{"Identifier":"","Email":"configcat@example.com","Country":"US","SubscriptionType":"Pro","Role":"Admin","version":"1.0.0"}'
Evaluating targeting rules and applying the first match if any:
- IF User.Email CONTAINS ANY OF ['@something.com'] THEN 'false' => no match
- IF User.Email CONTAINS ANY OF ['@example.com'] THEN 'true' => MATCH, applying rule
Returning 'true'.
```
The following example shows how to set the *Log Level* on the internal *ConfigCat* logger. Set the log level of the module with [put\_module\_level/2](https://hexdocs.pm/logger/1.15.6/Logger.html#put_module_level/2) function. Put the following code into your application.ex file and run it on start:
```elixir
defp set_config_cat_log_level do
:configcat
|> Application.spec(:modules)
|> Logger.put_module_level(:debug)
end
```
On Elixir 1.13 or later you can use [put\_application\_level/2](https://hexdocs.pm/logger/1.15.6/Logger.html#put_application_level/2) function which is equivalent to the code above.
## `get_all_keys()`[](#get_all_keys "Direct link to get_all_keys")
You can get the keys for all available feature flags and settings by calling the `get_all_keys()` method.
```elixir
keys = ConfigCat.get_all_keys()
```
## `get_all_values()`[](#get_all_values "Direct link to get_all_values")
Evaluates and returns the values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```elixir
values = ConfigCat.get_all_values(
ConfigCat.User.new("#UNIQUE-USER-IDENTIFIER#") # Optional User Object
)
```
## `get_all_value_details()`[](#get_all_value_details "Direct link to get_all_value_details")
Evaluates and returns the detailed values of all feature flags and settings. Passing a [User Object](#user-object) is optional.
```elixir
all_value_details = ConfigCat.get_all_value_details(
ConfigCat.User.new("#UNIQUE-USER-IDENTIFIER#") # Optional User Object
)
```
## Using ConfigCat behind a proxy[](#using-configcat-behind-a-proxy "Direct link to Using ConfigCat behind a proxy")
Provide your own network credentials (username/password), and proxy server settings (proxy server/port) by passing the proxy details to the creator method.
```elixir
{ConfigCat, [
sdk_key: "#YOUR-SDK-KEY#",
http_proxy: "https://user@pass:yourproxy.com"
]}
```
## Sample Applications[](#sample-applications "Direct link to Sample Applications")
* [Sample App](https://github.com/configcat/elixir-sdk/tree/main/samples)
## Look under the hood[](#look-under-the-hood "Direct link to Look under the hood")
* [ConfigCat's Elixir SDK on GitHub](https://github.com/configcat/elixir-sdk)
* [ConfigCat's HexDocs](https://hexdocs.pm/configcat)
* [ConfigCat's Elixir SDK on Hex.pm](https://hex.pm/packages/configcat)
---
# Source: https://configcat.com/docs/advanced/proxy/endpoints.md
# Endpoints
Copy page
The Proxy accepts HTTP requests on the following endpoints.
## CDN Proxy[](#cdn-proxy "Direct link to CDN Proxy")
The CDN proxy endpoint's purpose is to forward the underlying *config JSON* to other ConfigCat SDKs used by your application.
GETOPTIONS/configuration-files/{path}
This endpoint is mainly used by ConfigCat SDKs to retrieve all required data for feature flag evaluation.
**Route parameters**:
* `path`: It's set by the ConfigCat SDK configured to use the ConfigCat Proxy. It contains either an SDK key or an [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The `config.json` file is downloaded successfully.
* 204: In response to an `OPTIONS` request.
* 304: The `config.json` file isn't modified based on the `Etag` sent in the `If-None-Match` header.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
### SDK Usage[](#sdk-usage "Direct link to SDK Usage")
In order to let a ConfigCat SDK use the Proxy, you have to set the SDK's `baseUrl` parameter to point to the Proxy's host.
example.js
```js
import * as configcat from "@configcat/sdk";
const configCatClient = configcat.getClient(
"#YOUR-SDK-KEY#",
configcat.PollingMode.AutoPoll,
{ baseUrl: "http://localhost:8050" } // Proxy URL
);
```
Additionally, as the Proxy maps [unique identifiers to each configured SDK key](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) it works with, you can use that identifier prefixed with `configcat-proxy/` as the SDK key at the ConfigCat SDK's initialization.
So, let's assume you set up the Proxy with an SDK key mapped to the `my_sdk` SDK identifier:
example.js
```js
import * as configcat from "@configcat/sdk";
const configCatClient = configcat.getClient(
"configcat-proxy/my_sdk", // SDK identifier prefixed with 'configcat-proxy/'
configcat.PollingMode.AutoPoll,
{ baseUrl: "http://localhost:8050" } // Proxy URL
);
```
### Supported SDK Versions[](#supported-sdk-versions "Direct link to Supported SDK Versions")
The following SDK versions are supported by the `>=v0.3.X` Proxy's CDN endpoint:
| SDK | Version |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| .NET | >= [v9.0.0](https://github.com/configcat/.net-sdk/releases/tag/v9.0.0) |
| Android (Java) | >= [v10.0.0](https://github.com/configcat/android-sdk/releases/tag/v10.0.0) |
| C++ | >= [v4.0.0](https://github.com/configcat/cpp-sdk/releases/tag/v4.0.0) |
| Dart (Flutter) | >= [v4.0.0](https://github.com/configcat/dart-sdk/releases/tag/4.0.0) |
| Elixir | >= [v4.0.0](https://github.com/configcat/elixir-sdk/releases/tag/v4.0.0) |
| Go | >= [v9.0.0](https://github.com/configcat/go-sdk/releases/tag/v9.0.0) |
| Java | >= [v9.0.0](https://github.com/configcat/java-sdk/releases/tag/v9.0.0) |
| JavaScript (Browser, Bun, Chromium Extension, Cloudflare Worker, Deno, Node) | >= [v1.0.0](https://github.com/configcat/js-unified-sdk/releases) |
| JS - Legacy | >= [v9.0.0](https://github.com/configcat/js-sdk/releases/tag/v9.0.0) |
| JS SSR - Legacy | >= [v8.0.0](https://github.com/configcat/js-ssr-sdk/releases/tag/v8.0.0) |
| Kotlin | >= [v3.0.0](https://github.com/configcat/kotlin-sdk/releases/tag/3.0.0) |
| Node - Legacy | >= [v11.0.0](https://github.com/configcat/node-sdk/releases/tag/v11.0.0) |
| PHP 8.1+ | >= [v9.0.0](https://github.com/configcat/php-sdk/releases/tag/v9.0.0) |
| PHP 7.1+ | >= [v3.0.0](https://github.com/configcat/php7-sdk/releases/tag/v3.0.0) |
| Python | >= [v9.0.3](https://github.com/configcat/python-sdk/releases/tag/v9.0.3) |
| React | >= [v4.0.0](https://github.com/configcat/react-sdk/releases/tag/v4.0.0) |
| Ruby | >= [v8.0.0](https://github.com/configcat/ruby-sdk/releases/tag/v8.0.0) |
| Rust | >= [v0.1.0](https://github.com/configcat/rust-sdk/releases/tag/v0.1.0) |
| Swift (iOS) | >= [v11.0.0](https://github.com/configcat/swift-sdk/releases/tag/11.0.0) |
### Available Options[](#available-options "Direct link to Available Options")
The following CDN Proxy related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML
- Environment variable```yaml
http:
cdn_proxy:
enabled:
``````shell
CONFIGCAT_HTTP_CDN_PROXY_ENABLED=
``` | `true` | Turns the hosting of the CDN proxy endpoint on/off. This endpoint can be used by other ConfigCat SDKs in your applications. |
| - YAML
- Environment variable```yaml
http:
cdn_proxy:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML
- Environment variable```yaml
http:
cdn_proxy:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`.
When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML
- Environment variable```yaml
http:
cdn_proxy:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin.
When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value.
The `if_no_match` option is mandatory if this option is used.
When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML
- Environment variable```yaml
http:
cdn_proxy:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_CDN_PROXY_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML
- Environment variable```yaml
http:
cdn_proxy:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_CDN_PROXY_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each CDN proxy endpoint response. |
## API[](#api "Direct link to API")
These API endpoints are for server side feature flag evaluation.
### Endpoints using SDK key[](#endpoints-using-sdk-key "Direct link to Endpoints using SDK key")
The following endpoints are using SDK keys to determine which config / environment is the target of the desired action. The SDK key must be provided in the `X-ConfigCat-SdkKey` HTTP header.
info
These endpoints are only available from Proxy version [`v3.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v3.0.0).
POSTOPTIONS/api/eval
This endpoint evaluates a single feature flag identified by a `key` with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines the feature flag's config / environment.
**Request body**:
```json
{
"key": "",
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header or the `key` from the request body is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/eval"; // Proxy API URL
const data = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"X-ConfigCat-SdkKey": "#YOUR-SDK-KEY#",
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData); // {"value":,"variationId":""}
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/eval-all
This endpoint evaluates all feature flags with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/eval-all"; // Proxy API URL
const data = {
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"X-ConfigCat-SdkKey": "#YOUR-SDK-KEY#",
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData);
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/refresh
This endpoint commands the underlying SDK to download the latest available *config JSON*.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that identifies an SDK within the Proxy.
**Responses**:
* 200: The refresh was successful.
* 204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
GETOPTIONS/api/keys
This endpoint returns all feature flag keys belonging to the given SDK key.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that identifies an SDK within the Proxy.
**Responses**:
* 200: The keys are returned successfully.
* Response body:
```json
{
"keys": [
"feature-flag-key-1",
"feature-flag-key-2"
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
### Endpoints using SDK identifier[](#endpoints-using-sdk-identifier "Direct link to Endpoints using SDK identifier")
The following endpoints are using an [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) to determine which config / environment is the target of the desired action. The SDK identifier must be provided as a route parameter of the HTTP request.
POSTOPTIONS/api/{sdkId}/eval
This endpoint evaluates a single feature flag identified by a `key` with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines the feature flag's config / environment.
**Request body**:
```json
{
"key": "",
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` or the `key` from the request body is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/#SDK-IDENTIFIER#/eval"; // Proxy API URL with SDK identifier
const data = {
key: "isMyAwesomeFeatureEnabled", // Feature flag key
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData); // {"value":,"variationId":""}
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/{sdkId}/eval-all
This endpoint evaluates all feature flags with the given [User Object](https://configcat.com/docs/targeting/user-object.md).
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"user": {
"Identifier": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
// any other attribute
}
}
```
The type of the `user` object's fields can only be `string`, `number`, or `string[]`.
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const url = "http://localhost:8050/api/#SDK-IDENTIFIER#/eval-all"; // Proxy API URL with SDK identifier
const data = {
user: { // User Object for evaluation
Identifier: "#UNIQUE-USER-IDENTIFIER#"
}
};
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
};
try {
const response = await fetch(url, requestOptions);
const responseData = await response.json();
console.log(responseData);
} catch (error) {
console.error("Error:", error)
}
```
POSTOPTIONS/api/{sdkId}/refresh
This endpoint commands the underlying SDK to download the latest available *config JSON*.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The refresh was successful.
* 204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
GETOPTIONS/api/{sdkId}/keys
This endpoint returns all feature flag keys belonging to the given [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key).
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The keys are returned successfully.
* Response body:
```json
{
"keys": [
"feature-flag-key-1",
"feature-flag-key-2"
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
### Available Options[](#available-options-1 "Direct link to Available Options")
The following API related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML
- Environment variable```yaml
http:
api:
enabled:
``````shell
CONFIGCAT_HTTP_API_ENABLED=
``` | `true` | Turns the hosting of the API endpoints on/off. These endpoints can be used for server side feature flag evaluation. |
| - YAML
- Environment variable```yaml
http:
api:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_API_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML
- Environment variable```yaml
http:
api:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_API_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`.
When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML
- Environment variable```yaml
http:
api:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_API_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin.
When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value.
The `if_no_match` option is mandatory if this option is used.
When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML
- Environment variable```yaml
http:
api:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_API_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML
- Environment variable```yaml
http:
api:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_API_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each API endpoint response. |
| - YAML
- Environment variable```yaml
http:
api:
auth_headers:
X-API-KEY: ""
``````shell
CONFIGCAT_HTTP_API_AUTH_HEADERS='{"X-API-KEY":""}'
``` | - | Additional headers that must be on each request sent to the API endpoints. If the request doesn't include the specified header, or the values are not matching, the Proxy will respond with a `401` HTTP status code. |
## OpenFeature Remote Evaluation Protocol (OFREP)[](#openfeature-remote-evaluation-protocol-ofrep "Direct link to OpenFeature Remote Evaluation Protocol (OFREP)")
info
OFREP compatibility is only available from Proxy version [`v2.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v2.0.0).
The Proxy conforms to the [OpenFeature Remote Evaluation Protocol](https://github.com/open-feature/protocol), which means it can be used with OFREP compatible OpenFeature providers.
### Endpoints using SDK key[](#endpoints-using-sdk-key-1 "Direct link to Endpoints using SDK key")
The following endpoints are using SDK keys to determine which config / environment is the target of the desired action. The SDK key must be provided in the `X-ConfigCat-SdkKey` HTTP header.
info
These endpoints are only available from Proxy version [`v3.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v3.0.0).
POSTOPTIONS/ofrep/v1/evaluate/flags/{key}
This endpoint is used by OFREP compatible OpenFeature providers to evaluate a feature flag.
**Route parameters**:
* `key`: The key of the feature flag to evaluate.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines the feature flag's config / environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK or the feature flag for `key` is not found.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkKey", "#YOUR-SDK-KEY#"],
],
}),
);
```
POSTOPTIONS/ofrep/v1/evaluate/flags
This endpoint is used by OFREP compatible OpenFeature providers to evaluate all feature flags.
**Headers**:
* `X-ConfigCat-SdkKey`: The SDK key that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"flags": [
{
"key": "",
"value": ,
"variant": "",
"reason": ""
},
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkKey` header is missing.
* 404: The `X-ConfigCat-SdkKey` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkKey", "#YOUR-SDK-KEY#"],
],
}),
);
```
### Endpoints using SDK identifier[](#endpoints-using-sdk-identifier-1 "Direct link to Endpoints using SDK identifier")
The following endpoints are using an [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) to determine which config / environment is the target of the desired action. The SDK identifier must be provided in the `X-ConfigCat-SdkId` HTTP header.
POSTOPTIONS/ofrep/v1/evaluate/flags/{key}
This endpoint is used by OFREP compatible OpenFeature providers to evaluate a feature flag.
**Route parameters**:
* `key`: The key of the feature flag to evaluate.
**Headers**:
* `X-ConfigCat-SdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines the feature flag's config / environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The feature flag evaluation finished successfully.
* Response body:
```json
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkId` header is missing.
* 404: The `X-ConfigCat-SdkId` header is pointing to a non-existent SDK or the feature flag for `key` is not found.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: "http://localhost:8050", // Proxy URL
headers: [
["X-ConfigCat-SdkId", "#SDK-IDENTIFIER#"],
],
}),
);
```
POSTOPTIONS/ofrep/v1/evaluate/flags
This endpoint is used by OFREP compatible OpenFeature providers to evaluate all feature flags.
**Headers**:
* `X-ConfigCat-SdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that determines which config's feature flags should be evaluated in which environment.
**Request body**:
```json
{
"context": {
"targetingKey": "",
"Rating": 4.5,
"Roles": ["Role1","Role2"],
}
}
```
**Responses**:
* 200: The evaluation of all feature flags finished successfully.
* Response body:
```json
{
"flags": [
{
"key": "",
"value": ,
"variant": "",
"reason": ""
},
{
"key": "",
"value": ,
"variant": "",
"reason": ""
}
]
}
```
204: In response to an `OPTIONS` request.
* 400: The `X-ConfigCat-SdkId` header is missing.
* 404: The `X-ConfigCat-SdkId` header is pointing to a non-existent SDK.
**Example**:
example.js
```js
import { OpenFeature } from "@openfeature/web-sdk";
import { OFREPWebProvider } from '@openfeature/ofrep-web-provider';
OpenFeature.setProvider(
new OFREPWebProvider({
baseUrl: 'http://localhost:8050', // Proxy URL
headers: [
["X-ConfigCat-SdkId", "#SDK-IDENTIFIER#"],
],
}),
);
```
### Available Options[](#available-options-2 "Direct link to Available Options")
The following OFREP related options are available:
| Option | Default | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML
- Environment variable```yaml
http:
ofrep:
enabled:
``````shell
CONFIGCAT_HTTP_OFREP_ENABLED=
``` | `true` | Turns the hosting of the OFREP endpoints on/off. These endpoints can be used by OFREP compatible OpenFeature providers for server side feature flag evaluation. |
| - YAML
- Environment variable```yaml
http:
ofrep:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML
- Environment variable```yaml
http:
ofrep:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`.
When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML
- Environment variable```yaml
http:
ofrep:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin.
When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value.
The `if_no_match` option is mandatory if this option is used.
When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML
- Environment variable```yaml
http:
ofrep:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_OFREP_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML
- Environment variable```yaml
http:
ofrep:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_OFREP_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each OFREP endpoint response. |
| - YAML
- Environment variable```yaml
http:
ofrep:
auth_headers:
X-API-KEY: ""
``````shell
CONFIGCAT_HTTP_OFREP_AUTH_HEADERS='{"X-API-KEY":""}'
``` | - | Additional headers that must be on each request sent to the OFREP endpoints. If the request doesn't include the specified header, or the values are not matching, the Proxy will respond with a `401` HTTP status code. |
## SSE[](#sse "Direct link to SSE")
The SSE endpoint allows you to subscribe for feature flag value changes through [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) connections.
### Endpoints using SDK key[](#endpoints-using-sdk-key-2 "Direct link to Endpoints using SDK key")
The following endpoints are using SDK keys to determine which config / environment is the target of the desired action. The SDK key must be provided in the `sdkKey` field of the base64 encoded `data` route parameter.
info
These endpoints are only available from Proxy version [`v3.0.0`](https://github.com/configcat/configcat-proxy/releases/tag/v3.0.0).
GETOPTIONS/sse/eval/k/{data}
This endpoint subscribes to a single flag's changes. Whenever the watched flag's value changes, the Proxy sends the new value to each connected client.
**Route parameters**:
* `data`: The `base64` encoded input data for feature flag evaluation that must contain the SDK key, the feature flag's key, and a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `data`, or the `sdkKey` or `key` field of `data` is missing.
* 404: The `sdkKey` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
sdkKey: "#YOUR-SDK-KEY#",
key: "isMyAwesomeFeatureEnabled",
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/eval/k/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"value":,"variationId":""}
};
```
GETOPTIONS/sse/eval-all/k/{data}
This endpoint subscribes to all feature flags' changes behind the given SDK key. When any of the watched flags' value change, the Proxy sends its new value to each connected client.
**Route parameters**:
* `data`: The `base64` encoded input data for feature flag evaluation that contains the SDK key and a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkKey` field of `data` is missing.
* 404: The `sdkKey` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
sdkKey: "#YOUR-SDK-KEY#",
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/eval-all/k/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"feature-flag-key":{"value":,"variationId":""}}
};
```
### Endpoints using SDK identifier[](#endpoints-using-sdk-identifier-2 "Direct link to Endpoints using SDK identifier")
The following endpoints are using an SDK identifier to determine which config / environment is the target of the desired action. The SDK identifier must be provided in the `sdkId` route parameter.
GETOPTIONS/sse/{sdkId}/eval/{data}
This endpoint subscribes to a single flag's changes. Whenever the watched flag's value changes, the Proxy sends the new value to each connected client.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
* `data`: The `base64` encoded input data for feature flag evaluation that must contain the feature flag's key and a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"value": ,
"variationId": ""
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId`, `data`, or the `key` attribute of `data` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
key: "isMyAwesomeFeatureEnabled",
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/#SDK-IDENTIFIER#/eval/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"value":,"variationId":""}
};
```
GETOPTIONS/sse/{sdkId}/eval-all/{data}
This endpoint subscribes to all feature flags' changes behind the given [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key). When any of the watched flags' value change, the Proxy sends its new value to each connected client.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
* `data`: **Optional**. The `base64` encoded input data for feature flag evaluation that contains a [User Object](https://configcat.com/docs/targeting/user-object.md).
**Responses**:
* 200: The SSE connection established successfully.
* Response body:
```json
{
"feature-flag-key-1": {
"value": ,
"variationId": ""
},
"feature-flag-key-2": {
"value": ,
"variationId": ""
}
}
```
204: In response to an `OPTIONS` request.
* 400: The `sdkId` is missing.
* 404: The `sdkId` is pointing to a non-existent SDK.
**Example**:
example.js
```js
const rawData = {
user: { // field types can only be `string`, `number`, or `string[]`.
Identifier: "#UNIQUE-USER-IDENTIFIER#",
Rating: 4.5,
Roles: ["Role1","Role2"],
// any other attribute
}
};
const data = btoa(JSON.stringify(rawData));
const evtSource = new EventSource("http://localhost:8050/sse/#SDK-IDENTIFIER#/eval-all/" + data);
evtSource.onmessage = (event) => {
console.log(event.data); // {"feature-flag-key":{"value":,"variationId":""}}
};
```
### Available Options[](#available-options-3 "Direct link to Available Options")
The following SSE related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML
- Environment variable```yaml
http:
sse:
enabled:
``````shell
CONFIGCAT_HTTP_SSE_ENABLED=
``` | `true` | Turns the hosting of the SSE endpoint on/off, This endpoint can be used to stream feature flag value changes. |
| - YAML
- Environment variable```yaml
http:
sse:
cors:
enabled:
``````shell
CONFIGCAT_HTTP_SSE_CORS_ENABLED=
``` | `true` | Turns the sending of CORS headers on/off. It can be used to restrict access to specific domains. By default, the Proxy allows each origin by setting the `Access-Control-Allow-Origin` response header to the request's origin. You can override this functionality by restricting the allowed origins with the `allowed_origins` or `allowed_origins_regex` options. |
| - YAML
- Environment variable```yaml
http:
sse:
cors:
allowed_origins:
- https://domain1.com
- https://domain2.com
``````shell
CONFIGCAT_HTTP_SSE_CORS_ALLOWED_ORIGINS='["https://domain1.com","https://domain2.com"]'
``` | - | List of allowed CORS origins. When it's set, the Proxy will include only that origin in the `Access-Control-Allow-Origin` response header which matches the request's `Origin`.
When there's no matching request origin and the `allowed_origins_regex` option is not set, the Proxy will set the `Access-Control-Allow-Origin` response header to the first item in the allowed origins list. |
| - YAML
- Environment variable```yaml
http:
sse:
cors:
allowed_origins_regex:
patterns:
- https:\/\/.*domain1\.com
- https:\/\/.*domain2\.com
``````shell
CONFIGCAT_HTTP_SSE_CORS_ALLOWED_ORIGINS_REGEX_PATTERNS='["https:\\/\\/.*domain1\\.com","https:\\/\\/.*domain2\\.com"]'
``` | - | List of regex patterns used to match allowed CORS origins. When it's set, the Proxy will match the request's `Origin` with the given regex patterns. When there's a match, the `Access-Control-Allow-Origin` response header will be set to the matched origin.
When there's no matching request origin, the Proxy will set the `Access-Control-Allow-Origin` response header to the `if_no_match` field's value.
The `if_no_match` option is mandatory if this option is used.
When using the environment variable, the regex escape character must be doubled (`\\`) because it's parsed as a JSON list and `\` is also a JSON escape character. |
| - YAML
- Environment variable```yaml
http:
sse:
cors:
allowed_origins_regex:
if_no_match: https://domain1.com
``````shell
CONFIGCAT_HTTP_SSE_CORS_ALLOWED_ORIGINS_REGEX_IF_NO_MATCH="https://domain1.com"
``` | - | Required when the previous `patterns` option is set. It's value is used in the `Access-Control-Allow-Origin` header when an incoming request's `Origin` doesn't match with any previously configured regex patterns. |
| - YAML
- Environment variable```yaml
http:
sse:
headers:
Custom-Header-Name: ""
``````shell
CONFIGCAT_HTTP_SSE_HEADERS='{"Custom-Header-Name":""}'
``` | - | Additional headers that must be sent back on each [SSE endpoint](#sse) response. |
| - YAML
- Environment variable```yaml
http:
sse:
log:
level: ""
``````shell
CONFIGCAT_HTTP_SSE_LOG_LEVEL=""
``` | `warn` | The verbosity of the SSE related logs.
Possible values: `error`, `warn`, `info` or `debug`. |
## Webhook[](#webhook "Direct link to Webhook")
Through the webhook endpoint, you can notify the Proxy about the availability of new feature flag evaluation data. Also, with the appropriate [SDK options](https://configcat.com/docs/advanced/proxy/proxy-overview.md#additional-options-for-underlying-sdks), the Proxy can [validate the signature](https://configcat.com/docs/advanced/notifications-webhooks.md#verifying-webhook-requests) of each incoming webhook request.
info
If you use the [automatic configuration with Proxy profiles](https://configcat.com/docs/advanced/proxy/proxy-overview.md#1-automatic-configuration-with-proxy-profiles), you don't have to set up individual webhooks manually. You can follow the documentation of webhook notifications for Proxy profiles [here](https://configcat.com/docs/advanced/proxy/proxy-overview.md#webhook-notification).
GETPOST/hook/{sdkId}
Notifies the Proxy that the SDK with the given [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) must refresh its *config JSON* to the latest version.
**Route parameters**:
* `sdkId`: The [SDK identifier](https://configcat.com/docs/advanced/proxy/proxy-overview.md#sdk-identifier--sdk-key) that uniquely identifies an SDK within the Proxy.
**Responses**:
* 200: The Proxy accepted the notification.
* 400: The `sdkId` is missing or the [webhook signature validation](https://configcat.com/docs/advanced/notifications-webhooks.md#verifying-webhook-requests) failed.
* 404: The `sdkId` is pointing to a non-existent SDK.
### ConfigCat Dashboard[](#configcat-dashboard "Direct link to ConfigCat Dashboard")
You can set up webhooks to invoke the Proxy on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard.

### Available Options[](#available-options-4 "Direct link to Available Options")
The following webhook related options are available:
| Option | Default | Description |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| - YAML
- Environment variable```yaml
http:
webhook:
enabled:
``````shell
CONFIGCAT_HTTP_WEBHOOK_ENABLED=
``` | `true` | Turns the hosting of the Webhook endpoint on/off. This endpoint can be used to notify the Proxy about the availability of new feature flag evaluation data. |
| - YAML
- Environment variable```yaml
http:
webhook:
auth:
user: ""
``````shell
CONFIGCAT_HTTP_WEBHOOK_AUTH_USER=""
``` | - | Basic authentication user. The basic authentication webhook header can be set on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard. |
| - YAML
- Environment variable```yaml
http:
webhook:
auth:
password: ""
``````shell
CONFIGCAT_HTTP_WEBHOOK_AUTH_PASSWORD=""
``` | - | Basic authentication password. The basic authentication webhook header can be set on the [Webhooks page](https://app.configcat.com/product/webhooks) of the ConfigCat Dashboard. |
| - YAML
- Environment variable```yaml
http:
webhook:
auth_headers:
X-API-KEY: ""
``````shell
CONFIGCAT_HTTP_WEBHOOK_AUTH_HEADERS='{"X-API-KEY":"