---
title: Subscribing to webhooks
description: Your app must respond to mandatory webhook topics.
api_version: v0
source_url:
  html: 'https://shopify.dev/docs/api/shopify-app-react-router/v0/guide-webhooks'
  md: 'https://shopify.dev/docs/api/shopify-app-react-router/v0/guide-webhooks.md'
---

# Subscribing to webhooks

Your app must respond to [mandatory webhook topics](https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks). In addition, your app can register [optional webhook topics](https://shopify.dev/docs/api/admin-rest/current/resources/webhook#event-topics).

There are app-specific and shop-specific webhooks. We recommend app-specific webhooks for most apps, but there are reasons to register shop-specific webhooks. For more information, please read [App-specific vs shop-specific webhooks](https://shopify.dev/docs/apps/build/webhooks/subscribe#app-specific-vs-shop-specific-subscriptions).

***

## App-specific webhooks (recommended)

The easiest way to configure webhooks is to use app-specific webhooks in `shopify.app.toml`. You can find more info in the [webhooks documentation](https://shopify.dev/docs/apps/webhooks/getting-started-declarative).

To set up a simple HTTPS webhook subscription, you can follow these steps:

1. Add the topic to subscribe to in `shopify.app.toml`. In this example we subscribe to the `APP_UNINSTALLED` topic.
2. Review the required scopes for the webhook topics, and update your [app scopes](https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes) as necessary.
3. Run `shopify app deploy` from the CLI to save your webhooks configuration.

## Configure app-specific webhooks

## shopify.app.toml

```tsx
[webhooks]
api_version = "2024-04"


  [[webhooks.subscriptions]]
  topics = [ "app/uninstalled" ]
  uri = "/webhooks"
  compliance_topics = [ "customers/data_request", "customers/redact", "shop/redact" ]
```

***

## Shop-specific webhooks

Shop-specific webhooks are useful when you need to subscribe to different webhook topics for different shops, or when a topic is not supported by app-specific webhooks.Configure `shopifyApp` and to setup shop-specific webhook subscriptions with the following steps:

1. The webhooks you want to subscribe to. In this example we subscribe to the `APP_UNINSTALLED` topic.
2. The code to register the `APP_UNINSTALLED` topic after a merchant installs you app. Here `shopifyApp` provides an `afterAuth` hook.
3. Review the required scopes for the webhook topics, and update your [app scopes](https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes) as necessary.

**Note:**

You can't register mandatory topics using this package, you must [configure those in the Partner Dashboard](https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks) instead.

## Configure shop-specific webhooks

## /app/shopify.server.ts

```tsx
import {shopifyApp, DeliveryMethod} from '@shopify/shopify-app-react-router/server';


const shopify = shopifyApp({
  apiKey: 'abcde1234567890',
  // ...etc
  webhooks: {
    APP_UNINSTALLED: {
      deliveryMethod: DeliveryMethod.Http,
      callbackUrl: '/webhooks',
    },
  },
  hooks: {
    afterAuth: async ({session}) => {
      // Register webhooks for the shop
      // In this example, every shop will have these webhooks
      // You could wrap this in some custom shop specific conditional logic if needed
      shopify.registerWebhooks({session});
    },
  },
});


export const authenticate = shopify.authenticate;
```

***

## Set up your endpoints

Create a route in your app to handle incoming webhook requests for each `callbackUrl` you set in your configuration.Legitimate webhook requests are always `POST` requests signed by Shopify, so you must authenticate them before taking any action. To do this you must set up an `action` that uses the `authenticate.webhook` function to authenticate the request.

Please keep in mind that webhook endpoints should respond as quickly as possible. If you need to run a long-running job, then consider using background tasks.

**Caution:**

Webhook endpoints **must** respond with an `HTTP 200` code, or Shopify will retry.

## Receive webhook requests

## /app/routes/webhooks.tsx

```tsx
import {ActionFunctionArgs} from 'react-router';


import db from '../db.server';


import {authenticate} from '~/shopify.server';


export const action = async ({request}: ActionFunctionArgs) => {
  const {topic, shop, session} = await authenticate.webhook(request);


  switch (topic) {
    case 'APP_UNINSTALLED':
      // Webhook requests can trigger after an app is uninstalled
      // If the app is already uninstalled, the session may be undefined.
      if (session) {
        await db.session.deleteMany({where: {shop}});
      }
      break;
    case 'CUSTOMERS_DATA_REQUEST':
    case 'CUSTOMERS_REDACT':
    case 'SHOP_REDACT':
    default:
      throw new Response('Unhandled webhook topic', {status: 404});
  }


  throw new Response();
};
```

***

## Resources

[authenticate.webhook](https://shopify.dev/docs/api/shopify-app-react-router/v0/authenticate/webhook)

***
