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

# Create features

<div className="m-badge-page-wrapper">
  <Badge stroke color="orange" size="sm">Limited Release</Badge>
</div>

A feature defines what customers can access and do in your application. Each feature connects the following:

* <a href="/limited-release/usage-based-billing/set-up-billing-process/create-pricing-plans" target="_blank" rel="noopener noreferrer">Pricing plans</a> through entitlements that assign privilege values for each plan level.
* <a href="/limited-release/usage-based-billing/manage-entities/manage-subscriptions#manage-subscription-entitlements" target="_blank" rel="noopener noreferrer">Subscriptions</a> through entitlement overrides that customize access for individual customers.

**How features, privileges, and entitlements work together**

* Your feature defines what customers can access. For example, you create an API access feature.
* Privileges set specific limits and permissions within each feature. For example, you add a `rate_limit` privilege to the API access feature to control the number of requests.
* When you add a feature to a plan, you set specific values for each privilege. These values are called entitlements. For example, you set the `rate_limit` privilege to 1,000 requests per day in your Basic plan and 100,000 requests per day in your Premium plan.
* Subscription entitlements override plan entitlements for individual customers. For example, you set a specific customer's `rate_limit` to 50,000 requests per day even though they are on the Basic plan.

## 1. Understand feature configuration

Before you create a feature, you can plan these configuration details for your application. Then, you can make a POST call to the <a href="/reference/api/rest/features/create-a-feature" target="_blank" rel="noopener noreferrer">Create feature</a> endpoint to send the information to PayPal.

**Feature identification**

* **Name**: Choose a human-readable identifier that describes the feature.
* **Code**: Create a unique identifier you use in API calls. Ensure this code is unique across all features in your account.
* **Description**: Provide details about what the feature enables or restricts.

**Privilege identification** <span id="privilege-planning" />

* **Name**: Choose a human-readable identifier that describes the privilege.
* **Code**: Create a unique identifier for the privilege within the feature.

## 2. Create features

You can create a basic feature, or include [privileges](#feature-with-privileges) to define specific access controls.

Use a <a href="/developer/how-to/api/get-started#2-get-an-access-token" target="_blank" rel="noopener noreferrer">valid access token</a> and make a POST call to the `/v1/commerce/billing/features` endpoint. Include the following parameters:

| <span style={{textAlign: 'left', display: 'block'}}>Parameter</span>                                                                                                                        | <span style={{textAlign: 'left', display: 'block'}}>Action</span>                                                                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `code`<br /><span style={{color: 'red', fontSize: 'smaller'}}>Required</span>, <span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span>                                          | Set a unique code to identify this feature.                                                                                      |
| `name`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span>                                                                                                             | Provide a human-readable name for the feature.                                                                                   |
| `description`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span>                                                                                                      | Provide a description of what functionality the feature provides or restricts.                                                   |
| `privileges[]`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>array</span>                                                                                                      | Add privilege configurations to define specific access controls within the feature.                                              |
| `privileges[].code`<br /><span style={{color: 'red', fontSize: 'smaller'}}>Required when privileges\[] provided</span>, <span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span> | Set a unique code to identify this privilege within the feature.                                                                 |
| `privileges[].name`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span>                                                                                                | Provide a human-readable name for the privilege.                                                                                 |
| `privileges[].value_type`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span>                                                                                          | Set to `INTEGER` for numeric limits, `BOOLEAN` for on/off toggles, `SELECT` for predefined options, or `STRING` for text values. |
| `privileges[].config`<br /><span style={{color: 'red', fontSize: 'smaller'}}>Required for SELECT type</span>, <span style={{color: '#95a5a6', fontSize: 'smaller'}}>object</span>           | Provide a `select_options` array with the available choices for SELECT type privileges.                                          |

For information on all parameters, see <a href="/reference/api/rest/features/create-a-feature" target="_blank" rel="noopener noreferrer">API reference</a>.

### Feature without privileges

You can create a basic feature without any privileges.

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X POST -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/features' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "name": "API access",
        "code": "api_access",
        "description": "Access to REST API endpoints"
    }'
  ```

  ```json lines title="Sample response" theme={null}
  {
      "code": "api_access",
      "name": "API access",
      "description": "Access to REST API endpoints",
      "created_at": "2025-01-28T10:00:00Z"
  }
  ```
</CodeGroup>

### Feature with privileges

You can create a feature with associated privileges to enable fine-grained control.

**Basic privileges**

You can use basic privilege types when you want to define simple access controls for features.

<CodeGroup>
  ```shell lines expandable title="Sample request" theme={null}
  curl -X POST -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/features' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "code": "seats",
        "name": "Number of seats",
        "description": "Number of users allowed in the account",
        "privileges": [
            {
                "code": "max",
                "name": "Maximum seats",
                "value_type": "INTEGER"
            },
            {
                "code": "max_admins",
                "name": "Maximum admin users",
                "value_type": "INTEGER"
            },
            {
                "code": "root",
                "name": "Allow root user",
                "value_type": "BOOLEAN"
            }
        ]
    }'
  ```

  ```json lines title="Sample response" theme={null}
  {
      "code": "seats",
      "name": "Number of seats",
      "description": "Number of users allowed in the account",
      "privileges": [
          {
              "code": "max",
              "name": "Maximum seats",
              "value_type": "INTEGER"
          },
          {
              "code": "max_admins",
              "name": "Maximum admin users",
              "value_type": "INTEGER"
          },
          {
              "code": "root",
              "name": "Allow root user",
              "value_type": "BOOLEAN"
          }
      ],
      "created_at": "2025-01-28T10:00:00Z"
  }
  ```
</CodeGroup>

**Fixed-option privileges**

Set `value_type` to `SELECT` when you want customers to choose from a predefined list of options. When you use `SELECT`, ensure you also provide a `config.select_options` array with the available choices.

<CodeGroup>
  ```shell lines expandable title="Sample request" theme={null}
  curl -X POST -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/features' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "code": "sso",
        "name": "Single Sign-On",
        "description": "SSO authentication configuration",
        "privileges": [
            {
                "code": "provider",
                "name": "SSO Provider",
                "value_type": "SELECT",
                "config": {
                    "select_options": [
                        "google",
                        "okta",
                        "azure",
                        "saml"
                    ]
                }
            },
            {
                "code": "enabled",
                "name": "SSO Enabled",
                "value_type": "BOOLEAN"
            }
        ]
    }'
  ```

  ```json lines expandable title="Sample response" theme={null}
  {
      "code": "sso",
      "name": "Single Sign-On",
      "description": "SSO authentication configuration",
      "privileges": [
          {
              "code": "provider",
              "name": "SSO Provider",
              "value_type": "SELECT",
              "config": {
                  "select_options": [
                      "google",
                      "okta",
                      "azure",
                      "saml"
                  ]
              }
          },
          {
              "code": "enabled",
              "name": "SSO Enabled",
              "value_type": "BOOLEAN"
          }
      ],
      "created_at": "2025-01-28T10:00:00Z"
  }
  ```
</CodeGroup>

A successful call returns a `201 Created` response. The response includes the following parameters:

| <span style={{textAlign: 'left', display: 'block'}}>Parameter</span>                         | <span style={{textAlign: 'left', display: 'block'}}>Description</span> | <span style={{textAlign: 'left', display: 'block'}}>Further action</span>                                                                                                                            |
| -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `code`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span>              | Unique code for the created feature.                                   | Use this `code` when <a href="/limited-release/usage-based-billing/manage-entities/manage-features" target="_blank" rel="noopener noreferrer">managing the feature</a>.                              |
| `privileges[].code`<br /><span style={{color: '#95a5a6', fontSize: 'smaller'}}>string</span> | Unique code for each privilege within the feature.                     | Use this `privileges[].code` when <a href="/limited-release/usage-based-billing/manage-entities/manage-features#delete-privilege" target="_blank" rel="noopener noreferrer">deleting privileges</a>. |

For information on all parameters, see <a href="/reference/api/rest/features/create-a-feature" target="_blank" rel="noopener noreferrer">API reference</a>.

## 3. Manage features

You can update feature configurations when adding new privileges, modifying existing privilege settings, or changing feature descriptions. To review a feature's current configuration, make a GET call to the <a href="/reference/api/rest/features/retrieve-a-feature" target="_blank" rel="noopener noreferrer">/v1/commerce/billing/features/{code}</a> endpoint.

| Feature attribute       | Updatable | Possible management options                                                                                                                                                                                 | Impact on existing customers           |
| ----------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **Feature name**        | Yes       | <a href="/limited-release/usage-based-billing/manage-entities/manage-features#update-feature-details" target="_blank" rel="noopener noreferrer">Update feature details</a> - modify display name            | No impact - display only               |
| **Feature description** | Yes       | <a href="/limited-release/usage-based-billing/manage-entities/manage-features#update-feature-details" target="_blank" rel="noopener noreferrer">Update feature details</a> - modify feature description     | No impact - display only               |
| **Feature privileges**  | Yes       | <a href="/limited-release/usage-based-billing/manage-entities/manage-features#update-feature-details" target="_blank" rel="noopener noreferrer">Update feature details</a> - modify privilege configuration | Affects existing customer entitlements |
| **Feature code**        | No        | Feature cannot be modified - unique identifier remains permanent                                                                                                                                            | N/A - cannot be modified               |
