Skip to main content

Subscribing to webhooks

Your app must respond to mandatory webhook topics. In addition, your app can register optional webhook topics.


Anchor to configConfiguring webhooks

To set up webhooks first we need to configure shopifyApp with 2 pieces:

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

You can't register mandatory topics using this package, you must configure those in the Partner Dashboard instead.

/app/shopify.server.ts

import {shopifyApp, DeliveryMethod} from '@shopify/shopify-app-remix/server';

const shopify = shopifyApp({
apiKey: 'abcde1234567890',
// ...etc
webhooks: {
APP_UNINSTALLED: {
deliveryMethod: DeliveryMethod.Http,
callbackUrl: '/webhooks',
},
},
hooks: {
afterAuth: async ({session}) => {
shopify.registerWebhooks({session});
},
},
});

export const authenticate = shopify.authenticate;

Anchor to endpointsSet up your endpoints

Legitimate webhook requests are always POSTs signed by Shopify, so you must authenticate them before taking any action.

For each callbackUrl in your configuration, 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.

/app/routes/webhooks.tsx

import {ActionFunction} from '@remix-run/node';

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

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

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

switch (topic) {
case 'APP_UNINSTALLED':
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();
};