On April 15 Shopify held their traditional Town Hall event and we’ve got a lot of new features to know.

@shopify/shopify-api
That is something big. It is a library to build Shopify apps at a the speed of light. It is agnostic and you can use it with any JacaScript library you want.
It was built on Node.js with TypeScript and it can do:
- Create online or offline access tokens for the Admin API via OAuth
- Make requests to the REST API
- Make requests to the GraphQL API
- Register/process webhooks
You can choose 2 options to start your app from – plain Node.js or Express. In dev mode it uses the same ngrok approach as we got used to.
In terms of authorization it provides an easy out-of-a-box OAuth interface.
app.get('/login', async (req, res) => {
let authRoute = await Shopify.Auth.beginAuth(req, res, SHOP, '/auth/callback', true);
return res.redirect(authRoute);
})
The most amazing thing is that now we can make GraphQL Admin API calls via built in GraphqlClient.
// Load the current session to get the `accessToken`
const session = await Shopify.Utils.loadCurrentSession(req, res);
// GraphQLClient takes in the shop url and the accessToken for that shop.
const client = new Shopify.Clients.Graphql(session.shop, session.accessToken);
// Use client.query and pass your query as `data`
const products = await client.query({
data: `{
products (first: 10) {
edges {
node {
id
title
descriptionHtml
}
}
}
}`,
});
The final thing is the ability to create webhooks Inside the code. You can register the webhook and get event based data from orders and other types of store events.
// Register webhooks after OAuth completes
app.get('/auth/callback', async (req, res) => {
try {
await Shopify.Auth.validateAuthCallback(req, res, req.query as unknown as AuthQuery); // req.query must be cast to unkown and then AuthQuery in order to be accepted
const handleWebhookRequest = async (topic: string, shop: string, webhookRequestBody: Buffer) => {
// this handler is triggered when a webhook is sent by the Shopify platform to your application
}
const currentSession = await Shopify.Utils.loadCurrentSession(request, response);
// See https://shopify.dev/docs/admin-api/graphql/reference/events/webhooksubscriptiontopic for a list of available topics
const resp = await Shopify.Webhooks.Registry.register({
path: '/webhooks',
topic: 'PRODUCTS_CREATE',
accessToken: currentSession.accessToken,
shop: currentSession.shop,
webhookHandler: handleWebhookRequest
});
} catch (error) {
console.error(error); // in practice these should be handled more gracefully
}
return res.redirect('/'); // wherever you want your user to end up after OAuth completes
});
You can check this library here.
Webhook metrics
Every Shopify app developer knows the bottleneck with webhook failures. When Shopify receives non 200 responses it allows several attempts more and if it gets the same non 200 statuses, it removes your webhook at all. Pretty rude, isn’t it?
Fortunately, now we can see those removed and failed webhooks as well as the average response time of your app and we can do something with them.

Now you can see the data from the last 7 days per each of your apps, split to every webhook call

Also you can check the best practices of working with webhooks here.
Store Access Controls

This feature detalizes the access level of all team members of your Partner Dashboard.
As you may know, there are 3 types of stores in your dashboard: development, managed stores, and Shopify Plus sandbox stores.
From now on, each of your staff members can be assigned to several levels of access, such as No access, Access to all stores, or Access to specific stores. The same applies to the rights to add, archive, or transfer ownership of stores.
This is an extremely important thing to have for every Shopify agency. If you have newbies or some temporary members of the team, it is important to hide some stores from them, not to share merchant-sensitive data from these stores.
Here is link to the docs as well.