> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# App Extensions: Guide

This guide describes how to get started developing App Extensions. It contains the following:

* An App Extensions-flavored variation on setting up a draft app
* Example requests and responses for the App Extensions mutations and query
* Implementation and code examples

## Prerequisites

Before getting started working with App Extensions, make sure you have the following:

* A BigCommerce store; we recommend using a [sandbox store](/developer/docs/overview/sandboxes) or other non-production store.
* A [Developer Portal](https://build.bigcommerce.com/apps) account registered to the same email account that owns the sandbox store.
* General familiarity with developing BigCommerce apps. To familiarize yourself, see the [Apps Guide](/developer/docs/integrations/getting-started) or [Apps Quick Start](/developer/docs/integrations/apps/quick-start).

## OAuth scopes

> **Note**
>
> Use an [app-level API account](/developer/docs/overview/api-fundamentals/api-accounts#app-level-api-accounts) to
> make App Extensions API calls. Neither
> [store-level](/developer/docs/overview/api-fundamentals/api-accounts#store-level-api-accounts)
> nor
> [account-level](/developer/docs/overview/api-fundamentals/api-accounts#store-level-api-accounts)
> API accounts can manage App Extensions.

The following section describes the process for creating an app profile and app-level API account. Configure the following OAuth scopes as directed in [Setup](#create-an-app-profile):

| Name           | Permission | Parameter                     | Description                                                                                                                             |
| :------------- | :--------- | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |
| App Extensions | manage     | `store_app_extensions_manage` | Manage App Extensions; requires an app-level API account                                                                                |
| Other          |            |                               | As needed for the app to function; for a list, see [OAuth scopes](/developer/docs/overview/api-fundamentals/api-accounts#oauth-scopes). |

## Create an app profile

> **Note**
>
> Unlike store-level API accounts, you can edit an app-level API account's list
> of authorized scopes during development.

Generate an [app-level API account](/developer/docs/overview/api-fundamentals/api-accounts#app-level-api-accounts) by [creating an app profile](/developer/docs/integrations/apps/guide/managing-apps-in-dev-portal#create-an-app-profile) in a [Developer Portal account](https://build.bigcommerce.com/apps) registered to the same email account that owns the development store.

Add the [required OAuth scopes](#oauth-scopes) from the preceding section on the **Scopes** tab of the app editor, then click **Update & Close**.

For more information on creating app profiles, see [Managing Apps in the Developer Portal](/developer/docs/integrations/apps/guide/managing-apps-in-dev-portal).

The following image shows the `App Extensions : manage` scope on the **Scopes** tab of the Developer Portal's app editor:

![App Extensions scope](/_fern-img/1f62c2b5acdfe40729680277e8daebf4d66e63bd1da228dee36a8f4f8b615fcf.webp)

To create a draft app, configure its environment variables and callback URLs, and install it on your store, see the [Apps Quick Start](/developer/docs/integrations/apps/quick-start).

## Example requests

This section contains examples of App Extensions-related GraphQL Admin API queries and mutations. It presents mutations and their variables separately. You can use a tool like [Postman](https://postman.com) or [Altair](https://altairgraphql.dev/) to make requests; if you prefer to get started quickly in Postman, see the [App Extensions Postman collection](/developer/docs/integrations/apps/app-extensions/postman-collection).

Use the following HTTP configuration to send requests:

**`GraphQL Admin API HTTP configuration`**

```http title="GraphQL Admin API HTTP configuration" showLineNumbers={false}
POST https://api.bigcommerce.com/stores/{{store_hash}}/graphql
X-Auth-Token: {{access_token}}
Accept: application/json
Content-Type: application/json
```

The following examples direct you to stringify the GraphQL query portion of your requests, but how this works in practice varies depending on the client you use.

### Create an App Extension

The [createAppExtension](/developer/api-reference/graphql/admin/mutations/app-extension/create-app-extension) mutation registers an App Extension that opens a side panel on the store control panel's customers page to let users read and write notes about interactions with specific customers.

#### Mutation

**`Example mutation: createAppExtension`**

```graphql title="Example mutation: createAppExtension"
mutation AppExtension($input: CreateAppExtensionInput!) {
  appExtension {
    createAppExtension(input: $input) {
      appExtension {
        id
        context
        model
        url
        label {
          defaultValue
          locales {
            value
            localeCode
          }
        }
      }
    }
  }
}
```

#### Variables

**`Example variables: createAppExtension`**

```json title="Example variables: createAppExtension"
{
  "input": {
    "context": "PANEL",
    "model": "CUSTOMERS",
    "url": "/customers/${id}/interactions",
    "label": {
      "defaultValue": "Interactions",
      "locales": [
        {
          "value": "Interaction Notes",
          "localeCode": "en-US"
        },
        {
          "value": "Notas de interacción",
          "localeCode": "es-MX"
        }
      ]
    }
  }
}
```

#### Request and Response

**`Example request: createAppExtension`**

```http title="Example request: createAppExtension"
POST https://api.bigcommerce.com/stores/{{store_hash}}/graphql
X-Auth-Token: {{access_token}}
Accept: application/json
Content-Type: application/json

{
  "query": "`mutation`", //stringify the value from the Mutation tab
  "variables": variables //use the value from the variables tab
}

```

**`Example response: createAppExtension`**

```json title="Example response: createAppExtension"
{
  "data": {
    "appExtension": {
      "createAppExtension": {
        "appExtension": {
          "id": "bc/store/appExtension/2",
          "context": "PANEL",
          "model": "CUSTOMERS",
          "url": "/customers/${id}/interactions",
          "label": {
            "defaultValue": "Interactions",
            "locales": [
              {
                "value": "Interaction Notes",
                "localeCode": "en-US"
              },
              {
                "value": "Notas de interacción",
                "localeCode": "es-MX"
              }
            ]
          }
        }
      }
    }
  }
}
```

### Get a store's App Extensions

The [Store appExtensions](/developer/api-reference/graphql/admin/queries/store) query returns a list of the store's App Extensions registered to the API account that makes the request, along with any details requested using the query schema. Note that all GraphQL requests use the `POST` method.

Because each App Extension is owned by the app that created it, this query only returns App Extensions registered by your app's API account (`client_id`). You can't retrieve or modify another app's App Extensions. For more on how App Extensions relate to the app that created them, see [App ownership and scope](/developer/docs/integrations/apps/app-extensions/overview#app-ownership-and-scope).

#### Query

**`Example query: Get store appExtensions`**

```graphql title="Example query: Get store appExtensions"
query {
  store {
    appExtensions {
      edges {
        node {
          id
          url
          model
        }
      }
    }
  }
}
```

#### Request and Response

**`Example request: Store appExtensions`**

```http title="Example request: Store appExtensions"
POST https://api.bigcommerce.com/stores/{{store_hash}}/graphql
X-Auth-Token: {{access_token}}
Accept: application/json
Content-Type: application/json

{
  "query": "`query`" //stringify the value from the Query tab
}

```

**`Example response: Store appExtensions`**

```json title="Example response: Store appExtensions"
{
  "data": {
    "store": {
      "appExtensions": {
        "edges": [
          {
            "node": {
              "id": "bc/store/appExtension/1",
              "url": "/product-app-extension/${id}",
              "model": "PRODUCTS"
            }
          },
          {
            "node": {
              "id": "bc/store/appExtension/2",
              "url": "/customers/${id}/interactions",
              "model": "CUSTOMERS"
            }
          }
        ]
      }
    }
  }
}
```

### Update an App Extension

The [updateAppExtension](/developer/api-reference/graphql/admin/mutations/app-extension/update-app-extension) mutation can update the `label` object and the `url` of an existing App Extension. All other properties are non-mutable.

Changes to the `label` object overwrite existing values, rather than upserting. Be sure to send the full label object you intend the App Extension to have.

Note that the `UpdateAppExtensionInput` has two properties, `id` and `data`. Add the desired new values for the `url` or `label` properties to the `data` attribute.

#### Mutation

**`Example mutation: updateAppExtension`**

```graphql title="Example mutation: updateAppExtension"
mutation AppExtension($input: UpdateAppExtensionInput!) {
  appExtension {
    updateAppExtension(input: $input) {
      appExtension {
        id
        url
        label {
          defaultValue
        }
      }
    }
  }
}
```

#### Variables

**`Example variables: updateAppExtension`**

```json title="Example variables: updateAppExtension"
{
  "input": {
    "id": "bc/store/appExtension/2",
    "data": {
      "url": "/interactions/customers/${id}"
    }
  }
}
```

#### Request and Response

**`Example request: updateAppExtension`**

```http title="Example request: updateAppExtension"
POST https://api.bigcommerce.com/stores/{{store_hash}}/graphql
X-Auth-Token: {{access_token}}
Accept: application/json
Content-Type: application/json

{
  "query": "`mutation`", //stringify the value from the Mutation tab
  "variables": variables //use the value from the variables tab
}

```

**`Example response: updateAppExtension`**

```json title="Example response: updateAppExtension"
{
  "data": {
    "appExtension": {
      "updateAppExtension": {
        "appExtension": {
          "id": "bc/store/appExtension/2",
          "url": "/interactions/customers/${id}",
          "label": {
            "defaultValue": "Interactions"
          }
        }
      }
    }
  }
}
```

### Delete an App Extension

The [deleteAppExtension](/developer/api-reference/graphql/admin/mutations/app-extension/delete-app-extension) mutation deletes an App Extension. It cannot be recovered. Note that you can request an additional property that isn't accessible to the other queries and mutations, `deletedAppExtensionId`. You can't request any other properties in the delete mutation.

> **Info**
>
> Use `deleteAppExtension` to remove an App Extension while your app remains installed on the store. You don't need to call it as part of your uninstall flow: because App Extensions are owned by the app that created them, BigCommerce automatically deletes all of your app's App Extensions from a store when the store owner uninstalls your app. See [Automatic deletion on app uninstall](/developer/docs/integrations/apps/app-extensions/overview#automatic-deletion-on-app-uninstall).

#### Mutation

**`Example mutation: deleteAppExtension`**

```graphql title="Example mutation: deleteAppExtension"
mutation AppExtension($input: DeleteAppExtensionInput!) {
  appExtension {
    deleteAppExtension(input: $input) {
        deletedAppExtensionId
    }
  }
}
```

#### Variables

**`Example variables: deleteAppExtension`**

```json title="Example variables: deleteAppExtension"
{
  "input": {
    "id": "bc/store/appExtension/2"
  }
}
```

#### Request and Response

**`Example request: deleteAppExtension`**

```http title="Example request: deleteAppExtension"
POST https://api.bigcommerce.com/stores/{{store_hash}}/graphql
X-Auth-Token: {{access_token}}
Accept: application/json
Content-Type: application/json

{
  "query": "`mutation`", //stringify the value from the Mutation tab
  "variables": variables //use the value from the variables tab
}

```

**`Example response: deleteAppExtension`**

```json title="Example response: deleteAppExtension"
{
  "data": {
    "appExtension": {
      "deleteAppExtension": {
        "deletedAppExtensionId": "bc/store/appExtension/2"
      }
    }
  }
}
```

## Example code

### Starter app

The BigCommerce [Next.js starter app (GitHub)](https://github.com/bigcommerce-edu/starter-sc-app-next) contains a [reference implementation](https://github.com/bigcommerce-edu/starter-sc-app-next/blob/main/src/lib/gift-certs-manager/register-app-extension.ts) for registering an App Extension.

### Code sample

The following Node.js code sample uses the [node-fetch http request package](https://www.npmjs.com/package/node-fetch) to create a color picker App Extension that opens in a side panel on the **View Products** page of the merchant's store control panel.

#### Configuration

**`create-color-picker-extension.js`**

```js title="create-color-picker-extension.js" showLineNumbers={false}
import setAppExtension from "./set-app-extension";

// Hardcoded example of store-specific credentials
const subjectStore = {
  store_hash: "qwerty",
  // the store's access_token from your DB
  access_token: "xxxxxalphanumxxxxx"
};

// stringified GraphQL Mutation
const registerAppExtensionMutation = `
mutation AppExtension($input: CreateAppExtensionInput!) {
  appExtension {
    createAppExtension(input: $input) {
      appExtension {
        id
        context
        model
        url
        label {
          defaultValue
          locales {
            value
            localeCode
          }
        }
      }
    }
  }
}
`;

// This GraphQL variable describes the particular App Extension your app is registering; modify for your use case
const colorPickerExtension = {
  input: {
    context: "PANEL",
    model: "PRODUCTS",
    url: "/product/${id}/pigment",
    label: {
      defaultValue: "Select Color",
      locales: [
        {
          value: "Pick Color",
          localeCode: "en-US"
        },
        {
          value: "Choisissez la couleur",
          localeCode: "fr-FR"
        },
      ],
    },
  },
};

return setAppExtension(
  subjectStore,
  registerAppExtensionMutation,
  colorPickerExtension
);
```

#### Request Logic

**`set-app-extension.js`**

```js title="set-app-extension.js"
// set-app-extension.js
import fetch from 'node-fetch';

const newAppExtension = async(store, query, variables) => {

  let {store_hash, access_token} = store;

  try {

    let response = await fetch({
      method: 'POST',
      url: `https://api.bigcommerce.com/stores/${store_hash}/graphql`,
      headers: {
        'X-Auth-Token': access_token,
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: {
        query,
        variables
      }
    });

    let data = await response.json();
    console.log(data);

  } catch(error) {
    console.log(error);
  };
}

export default async(store, query, variables) => await newAppExtension(store, query, variables);
```

## Resources

### Related articles

* [Developer Portal](https://build.bigcommerce.com)
* [Single-Click App OAuth Flow](/developer/docs/integrations/apps/guide/auth)

### External resources

* [node-fetch http request package (npmjs.com)](https://www.npmjs.com/package/node-fetch)