> ## 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.

# Manage subscriptions

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

Subscription management helps you update existing subscriptions when your business requirements change. You can modify subscription details, change plan assignments, and cancel subscriptions when necessary. This ability ensures appropriate billing and customer satisfaction with flexible options for immediate and delayed cancellations.

## Update subscription details

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 PUT call to the `/v1/commerce/billing/subscriptions/{external_subscription_id}` endpoint with the modified request parameters such as name, plan overrides, start date, and end date.

**Path parameter**: `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.

<Warning>
  When updating subscription charges in `plan_overrides.charges[]`, use the `id` field to identify which charge to override. The `id` should match a charge from the plan's usage\_based\_charges array. In the response, PayPal returns both `id` (charge identifier) and `metric_id` (the metric the charge applies to).
</Warning>

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

<CodeGroup>
  ```shell lines expandable title="Sample request" theme={null}
  curl -X PUT -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/Subscription_External_1' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "name": "Updated Subscription Name",
        "status": "ACTIVE",
        "plan_overrides": {
            "amount": {
                "value": 25.00
            },
            "name": "Updated Plan Name",
            "trial_period": 7,
            "tax_codes": [
                "standard_vat"
            ],
            "charges": [
                {
                    "id": "99fa7a6b-d005-43a5-8bab-0df7a2a721fb",
                    "properties": {
                        "amount": "0.50"
                    },
                    "min_amount": {
                        "value": 5.00
                    },
                    "tax_codes": [
                        "standard_vat"
                    ]
                }
            ]
        },
        "start_date": "2025-07-30T01:54:40Z",
        "end_date": "2025-09-09T04:26:24Z"
    }'
  ```

  ```json lines expandable title="Sample response" theme={null}
  {
      "name": "Updated Subscription Name",
      "external_customer_id": "5eb02857-a71e-4ea2-bcf9-1753840218",
      "external_id": "Subscription_External_1",
      "plan_code": "Plan-Code-1753840215",
      "billing_time": "ANNIVERSARY",
      "status": "ACTIVE",
      "plan_overrides": {
          "amount": {
              "value": 25.00,
              "currency_code": "USD"
          },
          "name": "Updated Plan Name",
          "trial_period": 7,
          "taxes": [
              {
                  "id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
                  "name": "TVA",
                  "code": "standard_vat",
                  "description": "French standard VAT",
                  "rate": "20.00",
                  "created_at": "2023-07-06T14:35:58Z"
              }
          ],
          "charges": [
              {
                  "id": "99fa7a6b-d005-43a5-8bab-0df7a2a721fb",
                  "metric_id": "2e097d19-1350-4baf-8add-5d19ecef8113",
                  "properties": {
                      "amount": "0.50"
                  },
                  "min_amount": {
                      "value": 5.00,
                      "currency_code": "USD"
                  },
                  "taxes": [
                      {
                          "id": "1a901a90-1a90-1a90-1a90-1a901a901a90",
                          "name": "TVA",
                          "code": "standard_vat",
                          "description": "French standard VAT",
                          "rate": "20.00",
                          "created_at": "2023-07-06T14:35:58Z"
                      }
                  ]
              }
          ]
      },
      "start_date": "2025-07-30T01:54:40Z",
      "end_date": "2025-09-09T04:26:24Z",
      "created_at": "2025-07-30T01:54:40Z",
      "updated_at": "2025-08-05T23:59:59Z",
      "current_period_start": "2025-07-30T01:54:40Z",
      "current_period_end": "2025-08-05T23:59:59Z",
      "id": "b71befc2-4799-402c-9d13-ca1f72759c64"
  }
  ```
</CodeGroup>

A successful call returns a `200 OK` response with the updated subscription details.

## Cancel a subscription

Subscription cancellation provides flexible options for ending billing relationships. You can cancel:

* **Active subscriptions**: Subscriptions currently in effect. Can be cancelled immediately or scheduled for the end of the current billing period.
* **Pending subscriptions**: Subscriptions scheduled to start in the future or new plans from downgrades waiting to take effect at the end of the billing period. Can only be cancelled immediately.

### Cancel immediately

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/subscriptions/{external_subscription_id}/cancel` endpoint with `cancel_option` set to `IMMEDIATE`.

**Path parameter**: `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.

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

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X POST -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/SUB_1752779018503/cancel' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "cancel_option": "IMMEDIATE"
    }'
  ```

  ```json lines expandable title="Sample response" theme={null}
  {
      "external_customer_id": "5eb02857-a71e-4ea2-bcf9-1753840218",
      "external_id": "SUB_1752779018503",
      "plan_code": "Plan-Code-1753840215",
      "billing_time": "ANNIVERSARY",
      "status": "CANCELED",
      "plan_overrides": {
          "amount": {
              "value": 20.00,
              "currency_code": "USD"
          },
          "name": "Plan-Name-1753840215",
          "trial_period": 14,
          "charges": [
              {
                  "id": "99fa7a6b-d005-43a5-8bab-0df7a2a721fb",
                  "metric_id": "2e097d19-1350-4baf-8add-5d19ecef8113",
                  "properties": {
                      "amount": "1"
                  }
              }
          ]
      },
      "start_date": "2025-07-30T01:54:40Z",
      "end_date": "2025-09-09T04:26:24Z",
      "created_at": "2025-07-30T01:54:40Z",
      "canceled_at": "2025-08-05T23:59:59Z",
      "current_period_start": "2025-07-30T01:54:40Z",
      "current_period_end": "2025-08-05T23:59:59Z",
      "id": "b71befc2-4799-402c-9d13-ca1f72759c64"
  }
  ```
</CodeGroup>

A successful call returns a `200 OK` response with the subscription details showing status changed to `CANCELED`.

### Cancel at period end

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/subscriptions/{external_subscription_id}/cancel` endpoint with `cancel_option` set to `END_OF_PERIOD`.

**Path parameter**: `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.

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

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X POST -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/SUB_1752779018503/cancel' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "cancel_option": "END_OF_PERIOD"
    }'
  ```

  ```json lines title="Sample response" theme={null}
  {
      "external_customer_id": "5eb02857-a71e-4ea2-bcf9-1753840218",
      "external_id": "SUB_1752779018503",
      "plan_code": "Plan-Code-1753840215",
      "billing_time": "ANNIVERSARY",
      "status": "ACTIVE",
      "cancel_at_period_end": true,
      "cancellation_date": "2025-08-05T23:59:59Z",
      "start_date": "2025-07-30T01:54:40Z",
      "end_date": "2025-09-09T04:26:24Z",
      "created_at": "2025-07-30T01:54:40Z",
      "updated_at": "2025-08-05T23:59:59Z",
      "current_period_start": "2025-07-30T01:54:40Z",
      "current_period_end": "2025-08-05T23:59:59Z",
      "id": "b71befc2-4799-402c-9d13-ca1f72759c64"
  }
  ```
</CodeGroup>

A successful call returns a `200 OK` response with the subscription details. The status remains `ACTIVE` until the cancellation date. The response includes `cancel_at_period_end` set to `true` and `cancellation_date` showing when the subscription ends.

## Manage subscription entitlements

Subscription entitlements allow you to customize feature access and capabilities for individual subscriptions, overriding the default plan entitlements. This provides flexibility to offer tailored features, limits, and permissions to specific customers based on their needs or negotiated agreements.

### Update subscription entitlements

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 PATCH call to the `/v1/commerce/billing/subscriptions/{external_subscription_id}/entitlements` endpoint with the entitlements to update.

**Path parameter**: `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.

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

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X PATCH -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/SUB_1752779018503/entitlements' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>' \
    -d '{
        "entitlements": [
            {
                "feature_code": "seats",
                "feature_privilege_values": {
                    "max": 200,
                    "max_admins": 20,
                    "root": true,
                    "guest_access": true
                }
            },
            {
                "feature_code": "api_access",
                "feature_privilege_values": {
                    "rate_limit": 50000,
                    "endpoints": "premium"
                }
            }
        ]
    }'
  ```

  ```json lines expandable title="Sample response" theme={null}
  {
      "entitlements": [
          {
              "feature_code": "seats",
              "name": "Number of seats",
              "description": "Number of users of the account",
              "feature_privileges": [
                  {
                      "code": "max",
                      "name": "Maximum",
                      "value_type": "INTEGER",
                      "plan_value": 100,
                      "override_value": 200
                  },
                  {
                      "code": "max_admins",
                      "name": "Max Admins",
                      "value_type": "INTEGER",
                      "plan_value": 10,
                      "override_value": 20
                  },
                  {
                      "code": "root",
                      "name": "Allow root user",
                      "value_type": "BOOLEAN",
                      "plan_value": true,
                      "override_value": true
                  },
                  {
                      "code": "guest_access",
                      "name": "Guest Access",
                      "value_type": "BOOLEAN",
                      "plan_value": false,
                      "override_value": true
                  }
              ]
          },
          {
              "feature_code": "api_access",
              "name": "API Access",
              "description": "Access to API endpoints",
              "feature_privileges": [
                  {
                      "code": "rate_limit",
                      "name": "Rate Limit",
                      "value_type": "INTEGER",
                      "plan_value": 10000,
                      "override_value": 50000
                  },
                  {
                      "code": "endpoints",
                      "name": "Endpoints",
                      "value_type": "STRING",
                      "plan_value": "all",
                      "override_value": "premium"
                  }
              ]
          }
      ]
  }
  ```
</CodeGroup>

A successful call returns a `200 OK` response with the updated subscription entitlements. New privileges or features are added, existing values are overwritten if duplicates are found, and items not included remain unchanged.

<Tip>
  The response includes both `plan_value` and `override_value` parameters. The `plan_value` shows the default value from the plan, while `override_value` shows the customized value for this subscription.
</Tip>

### List subscription entitlements

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 GET call to the `/v1/commerce/billing/subscriptions/{external_subscription_id}/entitlements` endpoint to retrieve all entitlements for a specific subscription.

**Path parameter**: `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X GET -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/SUB_1752779018503/entitlements' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>'
  ```

  ```json lines expandable title="Sample response" theme={null}
  {
      "entitlements": [
          {
              "feature_code": "seats",
              "name": "Number of seats",
              "description": "Number of users of the account",
              "feature_privileges": [
                  {
                      "code": "max",
                      "name": "Maximum",
                      "value_type": "INTEGER",
                      "plan_value": 100,
                      "override_value": 200
                  },
                  {
                      "code": "max_admins",
                      "name": "Max Admins",
                      "value_type": "INTEGER",
                      "plan_value": 10,
                      "override_value": 20
                  },
                  {
                      "code": "root",
                      "name": "Allow root user",
                      "value_type": "BOOLEAN",
                      "plan_value": true,
                      "override_value": true
                  },
                  {
                      "code": "guest_access",
                      "name": "Guest Access",
                      "value_type": "BOOLEAN",
                      "plan_value": false,
                      "override_value": true
                  }
              ]
          },
          {
              "feature_code": "api_access",
              "name": "API Access",
              "description": "Access to API endpoints",
              "feature_privileges": [
                  {
                      "code": "rate_limit",
                      "name": "Rate Limit",
                      "value_type": "INTEGER",
                      "plan_value": 10000,
                      "override_value": 50000
                  },
                  {
                      "code": "endpoints",
                      "name": "Endpoints",
                      "value_type": "STRING",
                      "plan_value": "all",
                      "override_value": "premium"
                  }
              ]
          }
      ]
  }
  ```
</CodeGroup>

A successful call returns a `200 OK` response with the subscription entitlements, showing both plan defaults and any subscription-specific overrides.

### Remove privilege overrides

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 DELETE call to the `/v1/commerce/billing/subscriptions/{external_subscription_id}/entitlements/{feature_code}/privileges/{privilege_code}` endpoint to remove a privilege override for a subscription and revert to the plan default.

**Path parameters**:

* `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.
* `feature_code` is the `code` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-features" target="_blank" rel="noopener noreferrer">created the feature</a>.
* `privilege_code` is the `code` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-features#feature-with-privileges" target="_blank" rel="noopener noreferrer">created the privilege</a>.

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X DELETE -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/SUB_1752779018503/entitlements/seats/privileges/guest_access' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>'
  ```
</CodeGroup>

A successful call returns a `204 No Content` response.

### Remove subscription entitlement overrides

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 DELETE call to the `/v1/commerce/billing/subscriptions/{external_subscription_id}/entitlements/{feature_code}` endpoint to remove all overrides for a specific subscription and revert to plan defaults.

**Path parameters**:

* `external_subscription_id` is the `external_id` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-subscriptions" target="_blank" rel="noopener noreferrer">created the subscription</a>.
* `feature_code` is the `code` you provided when you <a href="/limited-release/usage-based-billing/set-up-billing-process/create-features" target="_blank" rel="noopener noreferrer">created the feature</a>.

<CodeGroup>
  ```shell lines title="Sample request" theme={null}
  curl -X DELETE -L 'https://api-m.sandbox.paypal.com/v1/commerce/billing/subscriptions/SUB_1752779018503/entitlements/api_access' \
    -H 'Authorization: Bearer <ACCESS-TOKEN>'
  ```
</CodeGroup>

A successful call returns a `204 No Content` response.
