The shopifyApi reference does not have a private app permanent access token property. I have a custom private app that is installed on only one store and I have the permanent access token so I don't need to oAuth every time I'm calling the REST API. Would be great to have a documented straight forward example of how to do this. The docs are hairy, IMO.
@shopify/shopify-api
version: 6.1.0Is the following close? I'm looking at the Session object and trying to understand how to load an offline session and set the Session
with correct SessionParams
.
import '@shopify/shopify-api/adapters/node'
import { shopifyApi, LATEST_API_VERSION, Session } from '@shopify/shopify-api'
const shopify = shopifyApi({
apiKey: 'myprivateappkey',
apiSecretKey: 'myprivateappsecret',
apiVersion: LATEST_API_VERSION,
isPrivateApp: true,
scopes: ['read_products'],
isEmbeddedApp: false,
hostName: 'shop.myshopify.com',
})
const sessionId = shopify.session.getOfflineId('shop.myshopify.com')
const session = new Session({
id: sessionId,
shop: 'shop.myshopify.com',
state: 'state',
isOnline: false,
accessToken: 'permanentAccessToken',
})
const client = new shopify.clients.Rest({ session: session })
On older v5 version of shopify-api
, with two lines I could access any REST API, but I see this is now deprecated, So I'm trying to unravel offline sessions, but it doesn't make sense to provide the api key and api secret and then create a session using the permanent access token.
import Shopify from '@shopify/shopify-api'
const client = new Shopify.Clients.Rest(
'mystore.myshopify.com',
'permanentAccessTokenString',
)
See answer from Shopify here.
When creating the client in a private app, a dummy session can be created like so
const session = new Session({
id: 'not-a-real-session-id',
shop: 'shop.myshopify.com,
state: 'state',
isOnline: false,
});
const client = new shopify.clients.Rest({ session: session })
When config.isPrivateApp is set to true only the shop property is used by the client - the other three (id, state, isOnline) properties are ignored (but are required when creating a Session object). config.apiSecretKey is used as the access token, and is read directly from the config (no need to set the accessToken property of the dummy session as it will be ignored). Essentially, config.apiSecretKey is the permanent access token for a private app.
The scopes can be omitted, as it defaults to an empty scopes array internally anyway and (from a quick search through the library code) is only used when doing OAuth, validating sessions, etc., which won't apply to private apps.
As for the apiKey, while it's mostly used as part of the OAuth process, it is also used in a few other places (e.g., shopify.auth.getEmbeddedAppUrl()), so I'd recommend setting the apiKey to be that of your private app.
However, in my testing, scopes, even when isPrivateApp
, are currently required. If you leave the array empty for scopes
it will have a config error.
Also, my shopifyApi
config mounts rest resources so that when you're in Shopify REST docs on the nodejs tab, you can easily use the REST resources examples on the nodejs to make calls, rather than creating a REST client and use standard post
, etc.
Complete code to setup a private app connection to Shopify:
import '@shopify/shopify-api/adapters/node'
import { shopifyApi, LATEST_API_VERSION, Session } from '@shopify/shopify-api'
import { restResources } from '@shopify/shopify-api/rest/admin/2023-01'
const debug = process.env.FUNCTIONS_EMULATOR === 'true'
const shopify = shopifyApi({
apiKey: 'myprivateAppApiKey',
apiSecretKey: 'myPermanentAccessToken',
apiVersion: LATEST_API_VERSION,
isPrivateApp: true,
scopes: [
'read_customers',
'write_customers',
'read_fulfillments',
'write_fulfillments',
'read_inventory',
'write_inventory',
'write_order_edits',
'read_order_edits',
'write_orders',
'read_orders',
'write_products',
'read_products',
],
isEmbeddedApp: false,
hostName: debug ? '127.0.0.1:5001' : 'shop.myshopify.com',
// Mount REST resources.
restResources,
})
// Create a sanitized "fake" sessionId. E.g.
// "offline_my.myshopify.com".
const sessionId = shopify.session.getOfflineId('shop.myshopify.com')
const session = new Session({
id: sessionId,
shop: 'shop.myshopify.com,
state: 'state',
isOnline: false,
})
// Use mounted REST resources to make calls.
const transactions = await shopify.rest.Transaction.all({
session,
order_id: 123456789,
})
// Alternatively, if not using mounted REST resources
// you could create a standard REST client.
const client = new shopify.clients.Rest({ session })