> Documentation index: [Saleor](/llms.txt) · [This section](/developer/llms.txt)
> Source: https://docs.saleor.io/developer/extending/webhooks/creating

# Creating Webhook

To subscribe to a webhook, we need to first create an App with proper permissions.

<a id="app-creation"></a>

## App creation

Webhooks are available in Saleor to both Local and External Apps. Local App is an entity tightly integrated into Saleor whereas External App is an externally hosted application that can communicate with Saleor API and integrate into Saleor Dashboard.

Saleor Local Apps are custom Webhooks & Token pairs that can be used to connect apps and access Saleor API. Defining webhooks through Saleor Local Apps allows Saleor API to send real-time notifications or data to another application or service. It enables communication between different systems by delivering event-based information from one system to another. Use Saleor's webhook functionality to receive notifications and trigger custom actions or integrations in response to specific events.

<a id="using-graphql"></a>

### Using GraphQL

Executing the a [`appCreate`](/api-reference/apps/mutations/app-create.md) GraphQL mutation.

```graphql
mutation {
  appCreate(
    input:{
      name: "App name",
      permissions: [MANAGE_ORDERS]
    }
  ){
    authToken
    app{
      id
    }
    errors{
      field
      code
      message
    }
  }
}
```

<a id="using-the-dashboard"></a>

### Using the Dashboard

Navigate to the **Extentions** section, clicking **Add Extention** -> **Provide details manually**.

<a id="webhook-creation"></a>

## Webhook creation

<a id="using-dashboard"></a>

### Using Dashboard

To create a webhook visit **Extentions** page. This page lists all apps and plugins in your Saleor instance. Apps assign Permissions to the Webhooks & Tokens. Choose an App from the list or create a new one. On the App page click `Create Webhook` button which opens the Create Webhook form.

Submitting the `Create Webhook` form triggers the [`webhookCreate`](/api-reference/webhooks/mutations/webhook-create.md) mutation. For fields explanation please check [Using GraphQL](#using-graphql) section.

<a id="using-graphql-1"></a>

### Using GraphQL

Let's assume that we want to extend the order processing app. The App should receive notifications whenever new orders are created in Saleor. To do so, we'll create a new webhook using the [`webhookCreate`](/api-reference/webhooks/mutations/webhook-create.md) mutation. The mutation takes the following input:

-   `name`: the name of the webhook. This is a display label — it is not stable and should not be used to reference the webhook. See [Webhook identifier](#webhook-identifier).
-   `identifier`: an optional, app-defined stable identifier, added in Saleor 3.23.23. See [Webhook identifier](#webhook-identifier).
-   `targetUrl`: the URL of a service that will receive webhooks requests.
-   `asyncEvents`: a list of the asynchronous events to subscribe to.
-   `syncEvents`: a list of the synchronous events to subscribe to.
-   `app`: the ID of the App to which the webhook belongs. Can be ommited, if the request has the `Authentication` header with the App access token.
-   `isActive`: whether to activate the webhook.
-   `secretKey` DEPRECATED, optional, the secret key used to create a hash signature with each payload.
-   `query`: subscription query used to define a webhook payload, check [Subscription Webhook Payloads](/developer/extending/webhooks/subscription-webhook-payloads.md) page for details.
-   `customHeaders`: custom headers, which will be added to HTTP request. There is a limitation of 5 headers per webhook and 998 characters per header. Only "X-_" and "Authorization_" keys are allowed.

```graphql
mutation {
  webhookCreate(
    input: {
      name: "New orders notification"
      targetUrl: "https://order-processing-service.example.com"
      asyncEvents: [ORDER_CREATED]
      app: "QXBwOjk="
      isActive: true
      query: "
        subscription {
          event {
            ... on OrderCreated {
              order {
                id
                created
              }
            }
          }
        }
      "
      customHeaders: "{\"X-Key\": \"Value\"}"
    }
  ) {
    webhook {
      id
    }
    webhookErrors {
      field
      code
    }
  }
}
```

If there are no errors in the response, the webhook is successfully created. From now on, whenever a new order is placed, the payload with the order data specified by subscription query will be sent to your `targetUrl`.

<a id="managing-app-webhooks"></a>

## Managing app webhooks

After installation, the App can create a webhook subscription. To manage its own webhooks, no additional permissions are needed. If requests contain the app token in the `Authentication` header, the `app` argument will be automatically populated with the corresponding App.

<a id="webhook-identifier"></a>

### Webhook identifier

**Added in Saleor 3.23.23.**

A webhook's `name` is a display label: it can be changed by a staff user in the Dashboard, and two webhooks of the same app may share it. An app that looks its webhooks up by `name` will therefore eventually fail to find them.

Instead, declare an `identifier` — a stable, app-defined string that the app controls:

-   It must be **unique per app** (an app cannot reuse the same `identifier` for two of its webhooks), but the same value may be used by different apps.
-   Maximum length is 256 characters. Blank and whitespace-only values are treated as not set.
-   It is exposed on the [`Webhook`](/api-reference/webhooks/objects/webhook.md) type via the `identifier` field.

Set it in `webhookCreate`, in `webhookUpdate` (pass a blank value to clear it), or declare it upfront in the [app manifest](/developer/extending/apps/architecture/manifest.md) so the webhook is created with it at install time:

```json
{
  "webhooks": [
    {
      "name": "Order created",
      "identifier": "order-created",
      "asyncEvents": ["ORDER_CREATED"],
      "query": "subscription { event { ... on OrderCreated { order { id }}}}",
      "targetUrl": "https://example.com/api/webhooks/order-created"
    }
  ]
}
```

Duplicate identifiers within one manifest fail the installation with the `DUPLICATED_WEBHOOK_IDENTIFIER` [app error code](/api-reference/apps/enums/app-error-code.md).

Once set, the app can pass `identifier` instead of `id` to [`webhookUpdate`](/api-reference/webhooks/mutations/webhook-update.md) and [`webhookDelete`](/api-reference/webhooks/mutations/webhook-delete.md) (available from Saleor 3.23.27). This removes the need to resolve a webhook ID first — see [How to update app webhooks](/developer/extending/apps/updating-app-webhooks.md).

note

Identifiers are unique per app only, so the `identifier` argument is available **exclusively to an app referencing its own webhook**. Staff users must use `id`; a non-app request passing `identifier` is rejected with the `INVALID` webhook error code.

There is no `webhook(identifier: ...)` query. To read a webhook by its identifier, query the app's own webhooks:

```graphql
query {
  app {
    webhooks {
      id
      identifier
      targetUrl
    }
  }
}
```

<a id="custom-payloads"></a>

### Custom payloads

You can define webhook payloads in Saleor with GraphQL subscriptions. Subscription queries allow you to subscribe to different events and determine what fields should be returned in the payload. For details check [Subscription Webhook Payloads](/developer/extending/webhooks/subscription-webhook-payloads.md) page.

tip

If you change the webhook subscription, you may need to update the webhook in the Saleor API. You can read more about it in the [How to update app webhooks](/developer/extending/apps/updating-app-webhooks.md) guide.

<a id="updating-a-webhook"></a>

### Updating a webhook

To update a webhook (e.g. to deactivate it or change the permissions), use the `webhookUpdate` mutation. The mutation takes similar input fields as the `webhookCreate` mutation. The example below shows how to deactivate a webhook:

```graphql
mutation {
  webhookUpdate(id: "V2ViaG9vazox", input: { isActive: false }) {
    webhook {
      isActive
    }
    webhookErrors {
      field
      code
    }
  }
}
```

From Saleor 3.23.27, an app can point at its own webhook with `identifier` instead of `id`. The two arguments are mutually exclusive:

```graphql
mutation {
  webhookUpdate(identifier: "order-created", input: { isActive: false }) {
    webhook {
      isActive
    }
    webhookErrors {
      field
      code
    }
  }
}
```

<a id="removing-a-webhook"></a>

### Removing a webhook

To fully remove a webhook, use the `webhookDelete` mutation:

```graphql
mutation {
  webhookDelete(id: "V2ViaG9vazox") {
    webhookErrors {
      field
      code
    }
  }
}
```

As with `webhookUpdate`, from Saleor 3.23.27 an app may reference its own webhook by `identifier` instead of `id`:

```graphql
mutation {
  webhookDelete(identifier: "order-created") {
    webhookErrors {
      field
      code
    }
  }
}
```
