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

# Feature Flag Entitlement

> अपने application में purchase के आधार पर features को नियंत्रित करें। Feature flag entitlements payment पर तुरंत एक boolean capability प्रदान करते हैं और cancellation पर इसे अपने-आप revoke कर देते हैं।

<Info>
  एक feature flag entitlement Dodo Payments को billing-aware feature-flag store में बदल देता है। किसी product से `advanced_reports` जैसा flag attach करें, और प्रत्येक paying customer को एक grant मिलता है जिसे आपका application API के माध्यम से check कर सकता है या webhooks के साथ sync में रख सकता है। किसी external platform, OAuth या delivery step की आवश्यकता नहीं है — grant स्वयं capability है।
</Info>

## क्या deliver होता है

Dodo Payments से कुछ भी बाहर नहीं जाता — grant ही deliverable **है**:

* Purchase पर grant बनाया जाता है और सीधे `delivered` में चला जाता है। कोई `pending` phase, customer action या delivery के fail होने की संभावना नहीं होती।
* Grant में typed `feature` payload होता है: `{ "feature_type": "boolean", "feature_id": "advanced_reports" }`। आपका application `feature_id` पढ़कर तय करता है कि क्या unlock करना है।
* Cancellation, refund या manual revoke grant को `revoked` में ले जाता है, और आपका application flag को गायब होते देखता है।

सामान्य उपयोगों में plan-based feature gating (Pro से analytics unlock करना), add-on capabilities ("API access" upgrade) और one-time purchases के रूप में बेचे जाने वाले early-access programs शामिल हैं।

<Note>
  `feature_id` merchant द्वारा चुना गया identifier है और entitlements में unique नहीं होता। दो entitlements एक ही `feature_id` प्रदान कर सकते हैं — उदाहरण के लिए, monthly और yearly Pro plan दोनों `advanced_reports` प्रदान कर सकते हैं।
</Note>

## Feature flag बनाएं

<Steps>
  <Step title="Open Entitlements">
    अपने Dodo Payments dashboard में **Entitlements** पर जाएं और नया entitlement शुरू करने के लिए **+** पर click करें, फिर **Feature Flags** चुनें।
  </Step>

  <Step title="Name the flag">
    अपने dashboard के लिए flag को **Display Name**, application द्वारा check किया जाने वाला **Feature ID** (dashboard name से एक ID सुझाता है) और एक **Description** दें, ताकि आपकी team को पता रहे कि यह किसे नियंत्रित करता है।

    <Frame caption="Creating a feature flag. The Feature ID is what your application checks; Meta Data attaches limits alongside the flag.">
      <img src="https://mintcdn.com/dodopayments/oS2MTbJuY6MeBjjs/images/entitlements/feature-flags/create.png?fit=max&auto=format&n=oS2MTbJuY6MeBjjs&q=85&s=08d8fc2cfee102ff08fd150c76b5fcf9" alt="New Feature Flag form with display name, feature ID, description, and metadata key-value entries" style={{ maxHeight: '500px', width: 'auto' }} width="1196" height="776" data-path="images/entitlements/feature-flags/create.png" />
    </Frame>
  </Step>

  <Step title="Optionally add metadata">
    Flag के साथ key-value configuration — limits, tier names, quotas — attach करने के लिए **Meta Data** toggle करें। यह configuration flag के साथ आपके application तक deliver की जाती है। [Attach limits with metadata](#attach-limits-with-metadata) देखें।
  </Step>

  <Step title="Confirm">
    **Confirm** पर click करें। Flag आपकी entitlements list में दिखाई देगा और products से attach करने के लिए तैयार होगा।

    <Frame caption="The created feature flag. The right pane tracks every customer grant issued from it.">
      <img src="https://mintcdn.com/dodopayments/oS2MTbJuY6MeBjjs/images/entitlements/feature-flags/list.png?fit=max&auto=format&n=oS2MTbJuY6MeBjjs&q=85&s=02eedcbbf7ece9f67d375c984c5515b9" alt="Entitlements dashboard showing the Advanced Reports feature flag with its grant activity pane" style={{ maxHeight: '500px', width: 'auto' }} width="1316" height="898" data-path="images/entitlements/feature-flags/list.png" />
    </Frame>
  </Step>
</Steps>

## Product से attach करें

किसी product को खोलें (या नया बनाएं), **Entitlements** card खोजें और मौजूदा entitlements attach करने के लिए **+** पर click करें। अपना feature flag चुनें और **Done** पर click करें।

<Frame caption="Attaching the feature flag to a product. One product can deliver multiple entitlements.">
  <img src="https://mintcdn.com/dodopayments/oS2MTbJuY6MeBjjs/images/entitlements/feature-flags/attach-picker.png?fit=max&auto=format&n=oS2MTbJuY6MeBjjs&q=85&s=da2137873e285cc6ce0ce234fe899ed3" alt="Entitlements attach panel with the Advanced Reports feature flag selected" style={{ maxHeight: '500px', width: 'auto' }} width="1316" height="898" data-path="images/entitlements/feature-flags/attach-picker.png" />
</Frame>

Attached flag product form पर दिखाई देता है और checkout preview इसे **Includes** के अंतर्गत सूचीबद्ध करता है।

<Frame caption="The product now includes the feature flag. Every successful purchase or active subscription grants it.">
  <img src="https://mintcdn.com/dodopayments/oS2MTbJuY6MeBjjs/images/entitlements/feature-flags/attach-to-product.png?fit=max&auto=format&n=oS2MTbJuY6MeBjjs&q=85&s=3556181389997edddde9c396d0ce408d" alt="Product form with the Advanced Reports feature flag attached in the Entitlements card" style={{ maxHeight: '500px', width: 'auto' }} width="1316" height="898" data-path="images/entitlements/feature-flags/attach-to-product.png" />
</Frame>

## आवश्यक configuration

| Field          | Required | Description                                                                                                    |
| -------------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `feature_id`   | Yes      | वह identifier जिसे आपका application check करता है, जैसे `advanced_reports`। Entitlements में unique नहीं होता। |
| `feature_type` | Yes      | प्रदान की गई capability का type। आज केवल `boolean` supported है।                                               |

### API के माध्यम से बनाएं

<CodeGroup>
  ```typescript TypeScript theme={null} theme={null}
  import DodoPayments from 'dodopayments';

  const client = new DodoPayments({
    bearerToken: process.env['DODO_PAYMENTS_API_KEY'],
    environment: 'test_mode',
  });

  const entitlement = await client.entitlements.create({
    name: 'Advanced Reports',
    integration_type: 'feature_flag',
    integration_config: {
      feature_type: 'boolean',
      feature_id: 'advanced_reports',
    },
    metadata: {
      tier: 'pro',
      monthly_report_limit: 100,
    },
  });
  ```

  ```python Python theme={null} theme={null}
  client.entitlements.create(
      name="Advanced Reports",
      integration_type="feature_flag",
      integration_config={
          "feature_type": "boolean",
          "feature_id": "advanced_reports",
      },
      metadata={
          "tier": "pro",
          "monthly_report_limit": 100,
      },
  )
  ```

  ```go Go theme={null} theme={null}
  client.Entitlements.New(ctx, dodopayments.EntitlementNewParams{
    Name:            dodopayments.F("Advanced Reports"),
    IntegrationType: dodopayments.F(dodopayments.EntitlementIntegrationTypeFeatureFlag),
    IntegrationConfig: dodopayments.F[dodopayments.IntegrationConfigUnionParam](
      dodopayments.IntegrationConfigFeatureFlagConfigParam{
        FeatureType: dodopayments.F(dodopayments.FeatureTypeBoolean),
        FeatureID:   dodopayments.F("advanced_reports"),
      },
    ),
  })
  ```
</CodeGroup>

***

## Metadata के साथ limits attach करें

Boolean flag इस प्रश्न का उत्तर देता है: "क्या इस customer के पास feature है?" Metadata बताता है: "किस configuration के साथ?" Entitlement metadata string, integer, number और boolean values स्वीकार करता है, और प्रत्येक grant बनने के समय entitlement के metadata का एक **frozen snapshot** लेता है।

यही snapshot behavior metadata को plan limits के लिए सुरक्षित बनाता है:

* बाद में entitlement का metadata edit करने पर केवल **future** grants प्रभावित होते हैं। Customers अपने खरीदे गए limits के अनुसार बने रहते हैं।
* Snapshot प्रत्येक grant पर उसके `metadata` field के रूप में लौटाया जाता है, इसलिए एक API call से flag और उसकी configuration दोनों मिलती हैं।

उदाहरण के लिए, `advanced_reports` flag के साथ `{ "tier": "pro", "monthly_report_limit": 100 }` होने पर आपका application dashboard unlock करने के साथ 100-report quota भी enforce कर सकता है, बिना किसी दूसरे lookup के। यदि बाद में limit को 250 कर दिया जाए, तो मौजूदा customers 100 पर ही रहेंगे, जब तक उन्हें नया grant न मिले (उदाहरण के लिए, plan change के बाद)।

<Tip>
  Limits और configuration के लिए metadata का उपयोग करें; identity के लिए केवल `feature_id` का उपयोग करें। ID में limits encode करना (`advanced_reports_100`) प्रत्येक limit change के लिए नया flag बनाने को मजबूर करता है और आपके application के checks को तोड़ देता है।
</Tip>

***

## Customer के features check करें

Customer के delivered feature-flag grants की list बनाएं और enabled features का set तैयार करें। Endpoint सभी entitlements में प्रत्येक grant के लिए एक row लौटाता है, जिसे `integration_type` और `status` से filter किया जा सकता है।

<CodeGroup>
  ```typescript TypeScript theme={null} theme={null}
  const features = new Map<string, Record<string, unknown>>();

  for await (const grant of client.customers.listEntitlementGrants('cus_abc123', {
    integration_type: 'feature_flag',
    status: 'Delivered',
  })) {
    if (grant.feature) {
      features.set(grant.feature.feature_id, grant.metadata ?? {});
    }
  }

  if (features.has('advanced_reports')) {
    const limit = features.get('advanced_reports')?.monthly_report_limit;
    // unlock the dashboard, enforce the limit
  }
  ```

  ```python Python theme={null} theme={null}
  page = client.customers.list_entitlement_grants(
      customer_id="cus_abc123",
      integration_type="feature_flag",
      status="Delivered",
  )

  features = {
      grant.feature.feature_id: grant.metadata
      for grant in page.items
      if grant.feature
  }

  if "advanced_reports" in features:
      limit = features["advanced_reports"].get("monthly_report_limit")
  ```

  ```go Go theme={null} theme={null}
  page, _ := client.Customers.ListEntitlementGrants(
    ctx, "cus_abc123",
    dodopayments.CustomerListEntitlementGrantsParams{
      IntegrationType: dodopayments.F("feature_flag"),
      Status:          dodopayments.F("Delivered"),
    },
  )

  features := map[string]bool{}
  for _, grant := range page.Items {
    if grant.Feature.FeatureID != "" {
      features[grant.Feature.FeatureID] = true
    }
  }
  ```
</CodeGroup>

<Note>
  `feature` payload केवल `feature_flag` grants पर populated होता है; हर दूसरे integration type के लिए यह `null` होता है। पूर्ण response shape के लिए [List Customer Grants](/api-reference/entitlements/list-customer-grants) API reference देखें।
</Note>

हर request पर API check करने से आपके hot path में latency बढ़ती है। प्रत्येक customer के लिए feature set को short TTL (hours नहीं, minutes) के साथ cache करें और grant की state बदलने पर अपने webhook handler से cache invalidate करें — यह संयोजन checks को fast और revocations को लगभग instant रखता है।

***

## Lifecycle

Feature flag grants standard [grant lifecycle](/features/entitlements/introduction#how-grants-work) का पालन करते हैं, एक simplification के साथ: कोई delivery step नहीं होता, इसलिए grants कभी `pending` में नहीं रुकते और `failed` में नहीं जाते।

| Trigger                                                 | Effect                                                                                                           |
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| One-time payment succeeds / subscription becomes active | Grant `status: delivered` के साथ बनाया जाता है और `delivered_at` set होता है।                                    |
| Subscription put on hold, cancelled, or expired         | Matching `revocation_reason` के साथ grant revoke किया जाता है।                                                   |
| Refund on a one-time payment                            | `revocation_reason: refund` के साथ grant revoke किया जाता है।                                                    |
| Subscription recovers (for example, dunning succeeds)   | Revoked grant को `delivered` में restore किया जाता है — वही grant `id`, और revocation fields clear किए जाते हैं। |
| Manual API revoke                                       | `revocation_reason: manual` के साथ grant revoke किया जाता है। Renewal पर auto-restore नहीं होता।                 |

Grants प्रत्येक entitlement और customer के लिए idempotent होते हैं: जब तक customer के पास किसी flag का non-revoked grant है, repeat purchases और renewals duplicates नहीं बनाते।

***

## Webhooks

Polling के बजाय flags को अपने database में mirror करने के लिए [`entitlement_grant.*` events](/developer-resources/webhooks/intents/entitlement-grant) को subscribe करें:

* `entitlement_grant.created` — यह पहले से `delivered` में `feature` payload के साथ आता है। Feature enable करें।
* `entitlement_grant.delivered` — पहले revoked grant के restore होने पर fire होता है। Feature फिर से enable करें।
* `entitlement_grant.revoked` — access वापस ले लिया गया है। Feature disable करें और अपनी messaging तय करने के लिए `revocation_reason` check करें।

```typescript TypeScript theme={null} theme={null}
app.post('/webhooks/dodo', async (req, res) => {
  const event = req.body;

  if (event.type.startsWith('entitlement_grant.') && event.data.feature) {
    const { customer_id, feature } = event.data;
    const enabled = event.type !== 'entitlement_grant.revoked';

    await db.customerFeatures.upsert({
      customerId: customer_id,
      featureId: feature.feature_id,
      enabled,
      config: event.data.metadata ?? {},
    });
  }

  res.sendStatus(200);
});
```

Feature flags के लिए कोई `entitlement_grant.failed` नहीं है — delivery पूरी तरह Dodo Payments के भीतर होती है और fail नहीं हो सकती।

***

## उदाहरण: Pro plan से advanced reports unlock करना

1. **Flag बनाएं।** `feature_id: advanced_reports` को metadata `{ "tier": "pro", "monthly_report_limit": 100 }` के साथ बनाएं।
2. इसे अपने Pro Plan subscription product से **attach करें**।
3. **Customer subscribe करता है।** Dodo Payments एक `delivered` grant बनाता है और `entitlement_grant.created` fire करता है; आपका webhook handler customer के लिए 100 की limit के साथ `advanced_reports` enable करता है।
4. **आपका app feature को gate करता है।** Dashboard load होने पर cached feature set check करें (या `listEntitlementGrants` call करें) और reports tab केवल तब render करें जब `advanced_reports` मौजूद हो।
5. **Customer cancel करता है।** Dodo Payments grant revoke करता है और `entitlement_grant.revoked` fire करता है; आपका handler feature disable कर देता है। यदि customer बाद में dunning के माध्यम से recover करता है, तो `entitlement_grant.delivered` इसे restore कर देता है — किसी code change की आवश्यकता नहीं।

***

## Best practices

* **Stable, snake\_case feature ids का उपयोग करें।** आपका application code इन strings को check करता है; किसी एक का नाम बदलना दोनों sides पर breaking change है।
* **प्रत्येक capability के लिए एक flag रखें।** एकल `pro_bundle` के बजाय `advanced_reports` + `api_access` को दो entitlements के रूप में रखना बेहतर है — revocation और plan mixes साफ रहते हैं।
* **State को webhooks से drive करें और API से verify करें।** Webhooks आपके database को current रखते हैं; list endpoint reconciliation jobs और cache misses के लिए source of truth है।
* **`revoked` को immediate मानें।** Revoked flag का अर्थ है कि customer अब feature के लिए pay नहीं कर रहा है। अगले session पर नहीं, अगली request पर gate करें।
* **Limits को code में नहीं, metadata में रखें।** Quota बदलने के लिए केवल entitlement edit करना होगा — नए customers इसे अपने-आप प्राप्त करेंगे, जबकि मौजूदा grants अपना purchased snapshot बनाए रखेंगे।
