# shopifyApp Returns a set of functions that can be used by the app's backend to be able to respond to all Shopify requests. The shape of the returned object changes depending on the value of `distribution`. If it is `AppDistribution.ShopifyAdmin`, then only `ShopifyAppBase` objects are returned, otherwise `ShopifyAppLogin` objects are included. ### The minimum viable configuration ```typescript import { shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ apiKey: process.env.SHOPIFY_API_KEY!, apiSecretKey: process.env.SHOPIFY_API_SECRET!, scopes: process.env.SCOPES?.split(",")!, appUrl: process.env.SHOPIFY_APP_URL!, }); export default shopify; ``` ## shopifyApp Function to create a new Shopify API object. ### ShopifyAppGeneratedType Creates an object your app will use to interact with Shopify. #### Returns: ShopifyApp<Config extends AppConfigArg<Resources, Storage, Future>> `ShopifyApp` An object constructed using your appConfig. It has methods for interacting with Shopify. #### Params: - appConfig: Readonly<Config> export function shopifyApp< Config extends AppConfigArg<Resources, Storage, Future>, Resources extends ShopifyRestResources, Storage extends SessionStorage, Future extends FutureFlagOptions = Config['future'], >(appConfig: Readonly<Config>): ShopifyApp<Config> { const api = deriveApi(appConfig); const config = deriveConfig<Storage>(appConfig, api.config); const logger = overrideLogger(api.logger); if (appConfig.webhooks) { api.webhooks.addHandlers(appConfig.webhooks); } const params: BasicParams = {api, config, logger}; const authStrategy = authStrategyFactory<Config, Resources>({ ...params, strategy: config.future.unstable_newEmbeddedAuthStrategy && config.isEmbeddedApp ? new TokenExchangeStrategy(params) : new AuthCodeFlowStrategy(params), }); const shopify: | AdminApp<Config> | AppStoreApp<Config> | SingleMerchantApp<Config> = { sessionStorage: config.sessionStorage, addDocumentResponseHeaders: addDocumentResponseHeadersFactory(params), registerWebhooks: registerWebhooksFactory(params), authenticate: { admin: authStrategy, flow: authenticateFlowFactory<Resources>(params), public: authenticatePublicFactory<Future, Resources>(params), fulfillmentService: authenticateFulfillmentServiceFactory<Resources>(params), webhook: authenticateWebhookFactory< Future, Resources, keyof Config['webhooks'] | MandatoryTopics >(params), }, unauthenticated: { admin: unauthenticatedAdminContextFactory(params), storefront: unauthenticatedStorefrontContextFactory(params), }, }; if ( isAppStoreApp(shopify, appConfig) || isSingleMerchantApp(shopify, appConfig) ) { shopify.login = loginFactory(params); } logDisabledFutureFlags(config, logger); return shopify as ShopifyApp<Config>; } ### ShopifyApp An object your app can use to interact with Shopify. By default, the app's distribution is `AppStore`. Config['distribution'] extends AppDistribution.ShopifyAdmin ? AdminApp<Config> : Config['distribution'] extends AppDistribution.SingleMerchant ? SingleMerchantApp<Config> : Config['distribution'] extends AppDistribution.AppStore ? AppStoreApp<Config> : AppStoreApp<Config> ### AppDistribution ### AppStore ### SingleMerchant ### ShopifyAdmin ### AdminApp ### sessionStorage The `SessionStorage` instance you passed in as a config option. ### addDocumentResponseHeaders Adds the required Content Security Policy headers for Shopify apps to the given Headers object. ### registerWebhooks Register webhook topics for a store using the given session. Most likely you want to use this in combination with the afterAuth hook. ### authenticate Ways to authenticate requests from different surfaces across Shopify. ### unauthenticated Ways to get Contexts from requests that do not originate from Shopify. ### SessionStorageType Config['sessionStorage'] extends SessionStorage ? Config['sessionStorage'] : SessionStorage ### AddDocumentResponseHeaders #### Returns: void #### Params: - request: Request - headers: Headers type AddDocumentResponseHeaders = (request: Request, headers: Headers) => void; ### Headers Record<string, string | string[]> ### RegisterWebhooks #### Returns: Promise<RegisterReturn | void> #### Params: - options: RegisterWebhooksOptions type RegisterWebhooks = ( options: RegisterWebhooksOptions, ) => Promise<RegisterReturn | void>; ### RegisterWebhooksOptions ### session The Shopify session used to register webhooks using the Admin API. ### Session Stores App information from logged in merchants so they can make authenticated requests to the Admin API. ### id The unique identifier for the session. ### shop The Shopify shop domain, such as `example.myshopify.com`. ### state The state of the session. Used for the OAuth authentication code flow. ### isOnline Whether the access token in the session is online or offline. ### scope The desired scopes for the access token, at the time the session was created. ### expires The date the access token expires. ### accessToken The access token for the session. ### onlineAccessInfo Information on the user for the session. Only present for online sessions. ### isActive Whether the session is active. Active sessions have an access token that is not expired, and has the given scopes. ### isScopeChanged Whether the access token has the given scopes. ### isExpired Whether the access token is expired. ### toObject Converts an object with data into a Session. ### equals Checks whether the given session is equal to this session. ### toPropertyArray Converts the session into an array of key-value pairs. ### OnlineAccessInfo ### expires_in How long the access token is valid for, in seconds. ### associated_user_scope The effective set of scopes for the session. ### associated_user The user associated with the access token. ### OnlineAccessUser ### id The user's ID. ### first_name The user's first name. ### last_name The user's last name. ### email The user's email address. ### email_verified Whether the user has verified their email address. ### account_owner Whether the user is the account owner. ### locale The user's locale. ### collaborator Whether the user is a collaborator. ### AuthScopes A class that represents a set of access token scopes. ### has Checks whether the current set of scopes includes the given one. ### equals Checks whether the current set of scopes equals the given one. ### toString Returns a comma-separated string with the current set of scopes. ### toArray Returns an array with the current set of scopes. ### SessionParams ### [key: string] ### id The unique identifier for the session. ### shop The Shopify shop domain. ### state The state of the session. Used for the OAuth authentication code flow. ### isOnline Whether the access token in the session is online or offline. ### scope The scopes for the access token. ### expires The date the access token expires. ### accessToken The access token for the session. ### onlineAccessInfo Information on the user for the session. Only present for online sessions. ### StoredOnlineAccessInfo Omit<OnlineAccessInfo, 'associated_user'> & { associated_user: Partial<OnlineAccessUser>; } ### RegisterReturn Record<string, RegisterResult[]> ### Authenticate ### admin Authenticate an admin Request and get back an authenticated admin context. Use the authenticated admin context to interact with Shopify. Examples of when to use this are requests from your app's UI, or requests from admin extensions. If there is no session for the Request, this will redirect the merchant to correct auth flows. ### flow Authenticate a Flow extension Request and get back an authenticated context, containing an admin context to access the API, and the payload of the request. If there is no session for the Request, this will return an HTTP 400 error. Note that this will always be a POST request. ### fulfillmentService Authenticate a request from a fulfillment service and get back an authenticated context. ### public Authenticate a public request and get back a session token. ### webhook Authenticate a Shopify webhook request, get back an authenticated admin context and details on the webhook request ### AuthenticateAdmin #### Returns: Promise<AdminContext<Config, Resources>> #### Params: - request: Request export type AuthenticateAdmin< Config extends AppConfigArg, Resources extends ShopifyRestResources = ShopifyRestResources, > = (request: Request) => Promise<AdminContext<Config, Resources>>; ### AdminContext Config['isEmbeddedApp'] extends false ? NonEmbeddedAdminContext<Config, Resources> : EmbeddedAdminContext<Config, Resources> ### NonEmbeddedAdminContext ### session The session for the user who made the request. This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice. Use this to get shop or user-specific data. ### admin Methods for interacting with the GraphQL / REST Admin APIs for the store that made the request. ### billing Billing methods for this store, based on the plans defined in the `billing` config option. ### cors A function that ensures the CORS headers are set correctly for the response. ### AdminApiContext ### rest Methods for interacting with the Shopify Admin REST API There are methods for interacting with individual REST resources. You can also make `GET`, `POST`, `PUT` and `DELETE` requests should the REST resources not meet your needs. ### graphql Methods for interacting with the Shopify Admin GraphQL API ### RestClientWithResources RemixRestClient & {resources: Resources} ### RemixRestClient ### session ### get Performs a GET request on the given path. ### post Performs a POST request on the given path. ### put Performs a PUT request on the given path. ### delete Performs a DELETE request on the given path. ### GetRequestParams ### path The path to the resource, relative to the API version root. ### type The type of data expected in the response. ### data The request body. ### query Query parameters to be sent with the request. ### extraHeaders Additional headers to be sent with the request. ### tries The maximum number of times the request can be made if it fails with a throttling or server error. ### DataType ### JSON ### GraphQL ### URLEncoded ### HeaderParams Headers to be sent with the request. Record<string, string | number | string[]> ### PostRequestParams GetRequestParams & { data: Record<string, any> | string; } ### GraphQLClient #### Returns: interface Promise<T> { /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>; /** * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>; }, interface Promise<T> {}, Promise: PromiseConstructor, interface Promise<T> { readonly [Symbol.toStringTag]: string; }, interface Promise<T> { /** * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The * resolved value cannot be modified from the callback. * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). * @returns A Promise for the completion of the callback. */ finally(onfinally?: (() => void) | undefined | null): Promise<T>; } #### Params: - query: Operation extends keyof Operations - options: GraphQLQueryOptions<Operation, Operations> export type GraphQLClient<Operations extends AllOperations> = < Operation extends keyof Operations, >( query: Operation, options?: GraphQLQueryOptions<Operation, Operations>, ) => Promise<GraphQLResponse<Operation, Operations>>; ### GraphQLQueryOptions ### variables The variables to pass to the operation. ### apiVersion The version of the API to use for the request. ### headers Additional headers to include in the request. ### tries The total number of times to try the request if it fails. ### ApiVersion ### October22 ### January23 ### April23 ### July23 ### October23 ### January24 ### April24 ### Unstable ### BillingContext ### require Checks if the shop has an active payment for any plan defined in the `billing` config option. ### check Checks if the shop has an active payment for any plan defined in the `billing` config option. ### request Requests payment for the plan. ### cancel Cancels an ongoing subscription, given its ID. ### RequireBillingOptions ### plans The plans to check for. Must be one of the values defined in the `billing` config option. ### onFailure How to handle the request if the shop doesn't have an active payment for any plan. ### isTest Whether to consider test purchases. ### BillingCheckResponseObject ### hasActivePayment Whether the user has an active payment method. ### oneTimePurchases The one-time purchases the shop has. ### appSubscriptions The active subscriptions the shop has. ### OneTimePurchase ### id The ID of the one-time purchase. ### name The name of the purchased plan. ### test Whether this is a test purchase. ### status The status of the one-time purchase. ### AppSubscription ### id The ID of the app subscription. ### name The name of the purchased plan. ### test Whether this is a test subscription. ### lineItems ### ActiveSubscriptionLineItem ### id ### plan ### AppPlan ### pricingDetails ### RecurringAppPlan ### interval ### price ### discount ### BillingInterval ### OneTime ### Every30Days ### Annual ### Usage ### Money ### amount ### currencyCode ### AppPlanDiscount ### durationLimitInIntervals ### remainingDurationInIntervals ### priceAfterDiscount ### value ### AppPlanDiscountAmount BillingConfigSubscriptionPlanDiscountAmount | BillingConfigSubscriptionPlanDiscountPercentage ### BillingConfigSubscriptionPlanDiscountAmount ### amount The amount to discount. Cannot be set if `percentage` is set. ### percentage The percentage to discount. Cannot be set if `amount` is set. ### BillingConfigSubscriptionPlanDiscountPercentage ### amount The amount to discount. Cannot be set if `percentage` is set. ### percentage The percentage to discount. Cannot be set if `amount` is set. ### UsageAppPlan ### balanceUsed ### cappedAmount ### terms ### CheckBillingOptions ### plans The plans to check for. Must be one of the values defined in the `billing` config option. ### isTest Whether to consider test purchases. ### RequestBillingOptions ### plan The plan to request. Must be one of the values defined in the `billing` config option. ### isTest Whether to use the test mode. This prevents the credit card from being charged. Test shops and demo shops cannot be charged. ### returnUrl The URL to return to after the merchant approves the payment. ### CancelBillingOptions ### subscriptionId The ID of the subscription to cancel. ### prorate Whether to prorate the cancellation. ### isTest ### EnsureCORSFunction export interface EnsureCORSFunction { (response: Response): Response; } ### EmbeddedAdminContext ### sessionToken The decoded and validated session token for the request. Returned only if `isEmbeddedApp` is `true`. ### redirect A function that redirects the user to a new page, ensuring that the appropriate parameters are set for embedded apps. Returned only if `isEmbeddedApp` is `true`. ### session The session for the user who made the request. This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice. Use this to get shop or user-specific data. ### admin Methods for interacting with the GraphQL / REST Admin APIs for the store that made the request. ### billing Billing methods for this store, based on the plans defined in the `billing` config option. ### cors A function that ensures the CORS headers are set correctly for the response. ### JwtPayload ### iss The shop's admin domain. ### dest The shop's domain. ### aud The client ID of the receiving app. ### sub The User that the session token is intended for. ### exp When the session token expires. ### nbf When the session token activates. ### iat When the session token was issued. ### jti A secure random UUID. ### sid A unique session ID per user and app. ### RedirectFunction #### Returns: TypedResponse<never> #### Params: - url: string - init: RedirectInit export type RedirectFunction = ( url: string, init?: RedirectInit, ) => TypedResponse<never>; ### RedirectInit number | (ResponseInit & {target?: RedirectTarget}) ### RedirectTarget '_self' | '_parent' | '_top' ### RestResourcesType Config['restResources'] extends ShopifyRestResources ? Config['restResources'] : ShopifyRestResources ### ShopifyRestResources Record<string, any> ### AuthenticateFlow #### Returns: Promise<FlowContext<Resources>> #### Params: - request: Request export type AuthenticateFlow< Resources extends ShopifyRestResources = ShopifyRestResources, > = (request: Request) => Promise<FlowContext<Resources>>; ### FlowContext ### session A session with an offline token for the shop. Returned only if there is a session for the shop. ### payload The payload from the Flow request. ### admin An admin context for the Flow request. Returned only if there is a session for the shop. ### AuthenticateFulfillmentService #### Returns: Promise<FulfillmentServiceContext<Resources>> #### Params: - request: Request export type AuthenticateFulfillmentService< Resources extends ShopifyRestResources = ShopifyRestResources, > = (request: Request) => Promise<FulfillmentServiceContext<Resources>>; ### FulfillmentServiceContext ### session A session with an offline token for the shop. Returned only if there is a session for the shop. ### admin An admin context for the fulfillment service request. Returned only if there is a session for the shop. ### payload The payload from the fulfillment service request. ### AuthenticatePublic FeatureEnabled<Future, 'v3_authenticatePublic'> extends true ? AuthenticatePublicObject : AuthenticatePublicLegacy ### AuthenticatePublicObject ### checkout Authenticate a request from a checkout extension ### appProxy Authenticate a request from an app proxy ### AuthenticateCheckout #### Returns: Promise<CheckoutContext> #### Params: - request: Request - options: AuthenticateCheckoutOptions export type AuthenticateCheckout = ( request: Request, options?: AuthenticateCheckoutOptions, ) => Promise<CheckoutContext>; ### AuthenticateCheckoutOptions ### corsHeaders ### CheckoutContext Authenticated Context for a checkout request ### sessionToken The decoded and validated session token for the request Refer to the OAuth docs for the [session token payload](https://shopify.dev/docs/apps/auth/oauth/session-tokens#payload). ### cors A function that ensures the CORS headers are set correctly for the response. ### AuthenticateAppProxy #### Returns: Promise<AppProxyContext | AppProxyContextWithSession> #### Params: - request: Request export type AuthenticateAppProxy = ( request: Request, ) => Promise<AppProxyContext | AppProxyContextWithSession>; ### AppProxyContext ### session No session is available for the shop that made this request. This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice. ### admin No session is available for the shop that made this request. Therefore no methods for interacting with the GraphQL / REST Admin APIs are available. ### storefront No session is available for the shop that made this request. Therefore no method for interacting with the Storefront API is available. ### liquid A utility for creating a Liquid Response. ### LiquidResponseFunction #### Returns: Response #### Params: - body: string - initAndOptions: number | (ResponseInit & Options) export type LiquidResponseFunction = ( body: string, initAndOptions?: number | (ResponseInit & Options), ) => Response; ### Options ### layout Whether to use the shop's theme layout around the Liquid content. ### AppProxyContextWithSession ### session The session for the shop that made the request. This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice. Use this to get shop or user-specific data. ### admin Methods for interacting with the GraphQL / REST Admin APIs for the store that made the request. ### storefront Method for interacting with the Shopify Storefront Graphql API for the store that made the request. ### liquid A utility for creating a Liquid Response. ### StorefrontContext ### graphql Method for interacting with the Shopify Storefront GraphQL API If you're getting incorrect type hints in the Shopify template, follow [these instructions](https://github.com/Shopify/shopify-app-template-remix/tree/main#incorrect-graphql-hints). ### AuthenticatePublicLegacy Methods for authenticating Requests from Shopify's public surfaces To maintain backwards compatability this is a function and an object. Do not use `authenticate.public()`. Use `authenticate.public.checkout()` instead. `authenticate.public()` will be removed in v2. Methods are: - `authenticate.public.checkout()` for authenticating requests from checkout extensions - `authenticate.public.appProxy()` for authenticating requests from app proxies AuthenticateCheckout & AuthenticatePublicObject ### AuthenticateWebhook #### Returns: Promise<WebhookContext<Future, Resources, Topics>> #### Params: - request: Request export type AuthenticateWebhook< Future extends FutureFlagOptions, Resources extends ShopifyRestResources, Topics = string | number | symbol, > = (request: Request) => Promise<WebhookContext<Future, Resources, Topics>>; ### WebhookContext WebhookContextWithoutSession<Topics> | WebhookContextWithSession<Future, Resources, Topics> ### WebhookContextWithoutSession ### session ### admin ### apiVersion The API version used for the webhook. ### shop The shop where the webhook was triggered. ### topic The topic of the webhook. ### webhookId A unique ID for the webhook. Useful to keep track of which events your app has already processed. ### payload The payload from the webhook request. ### subTopic The sub-topic of the webhook. This is only available for certain webhooks. ### WebhookContextWithSession ### session A session with an offline token for the shop. Returned only if there is a session for the shop. ### admin An admin context for the webhook. Returned only if there is a session for the shop. ### apiVersion The API version used for the webhook. ### shop The shop where the webhook was triggered. ### topic The topic of the webhook. ### webhookId A unique ID for the webhook. Useful to keep track of which events your app has already processed. ### payload The payload from the webhook request. ### subTopic The sub-topic of the webhook. This is only available for certain webhooks. ### WebhookAdminContext FeatureEnabled<Future, 'v3_webhookAdminContext'> extends true ? AdminApiContext<Resources> : LegacyWebhookAdminApiContext<Resources> ### LegacyWebhookAdminApiContext ### rest A REST client. ### graphql A GraphQL client. ### RestClient ### loggedDeprecations ### client ### session ### apiVersion ### get Performs a GET request on the given path. ### post Performs a POST request on the given path. ### put Performs a PUT request on the given path. ### delete Performs a DELETE request on the given path. ### RestRequestReturn ### body ### headers ### pageInfo ### PageInfo ### limit ### fields ### previousPageUrl ### nextPageUrl ### prevPage ### nextPage ### PageInfoParams ### path ### query ### MandatoryTopics 'CUSTOMERS_DATA_REQUEST' | 'CUSTOMERS_REDACT' | 'SHOP_REDACT' ### Unauthenticated ### admin Get an admin context by passing a shop **Warning** This should only be used for Requests that do not originate from Shopify. You must do your own authentication before using this method. This method throws an error if there is no session for the shop. ### storefront Get a storefront context by passing a shop **Warning** This should only be used for Requests that do not originate from Shopify. You must do your own authentication before using this method. This method throws an error if there is no session for the shop. ### GetUnauthenticatedAdminContext #### Returns: Promise<UnauthenticatedAdminContext<Resources>> #### Params: - shop: string export type GetUnauthenticatedAdminContext< Resources extends ShopifyRestResources, > = (shop: string) => Promise<UnauthenticatedAdminContext<Resources>>; ### UnauthenticatedAdminContext ### session The session for the given shop. This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice. This will always be an offline session. You can use to get shop-specific data. ### admin Methods for interacting with the GraphQL / REST Admin APIs for the given store. ### GetUnauthenticatedStorefrontContext #### Returns: Promise<UnauthenticatedStorefrontContext> #### Params: - shop: string export type GetUnauthenticatedStorefrontContext = ( shop: string, ) => Promise<UnauthenticatedStorefrontContext>; ### UnauthenticatedStorefrontContext ### session The session for the given shop. This comes from the session storage which `shopifyApp` uses to store sessions in your database of choice. This will always be an offline session. You can use this to get shop specific data. ### storefront Method for interacting with the Shopify GraphQL Storefront API for the given store. ### SingleMerchantApp ShopifyAppBase<Config> & ShopifyAppLogin ### ShopifyAppBase ### sessionStorage The `SessionStorage` instance you passed in as a config option. ### addDocumentResponseHeaders Adds the required Content Security Policy headers for Shopify apps to the given Headers object. ### registerWebhooks Register webhook topics for a store using the given session. Most likely you want to use this in combination with the afterAuth hook. ### authenticate Ways to authenticate requests from different surfaces across Shopify. ### unauthenticated Ways to get Contexts from requests that do not originate from Shopify. ### ShopifyAppLogin ### login Log a merchant in, and redirect them to the app root. Will redirect the merchant to authentication if a shop is present in the URL search parameters or form data. This function won't be present when the `distribution` config option is set to `AppDistribution.ShopifyAdmin`, because Admin apps aren't allowed to show a login page. ### Login #### Returns: Promise<LoginError | never> #### Params: - request: Request type Login = (request: Request) => Promise<LoginError | never>; ### LoginError ### shop ### LoginErrorType ### MissingShop ### InvalidShop ### AppStoreApp ShopifyAppBase<Config> & ShopifyAppLogin ### AppConfigArg ### appUrl The URL your app is running on. The `@shopify/cli` provides this URL as `process.env.SHOPIFY_APP_URL`. For development this is probably a tunnel URL that points to your local machine. If this is a production app, this is your production URL. ### sessionStorage An adaptor for storing sessions in your database of choice. Shopify provides multiple session storage adaptors and you can create your own. ### useOnlineTokens Whether your app use online or offline tokens. If your app uses online tokens, then both online and offline tokens will be saved to your database. This ensures your app can perform background jobs. ### webhooks The config for the webhook topics your app would like to subscribe to. This can be in used in conjunction with the afterAuth hook to register webhook topics when a user installs your app. Or you can use this function in other processes such as background jobs. ### hooks Functions to call at key places during your apps lifecycle. These functions are called in the context of the request that triggered them. This means you can access the session. ### isEmbeddedApp Does your app render embedded inside the Shopify Admin or on its own. Unless you have very specific needs, this should be true. ### distribution How your app is distributed. Default is `AppDistribution.AppStore`. ### apiVersion What version of Shopify's Admin API's would you like to use. ### authPathPrefix A path that Shopify can reserve for auth related endpoints. This must match a $ route in your Remix app. That route must export a loader function that calls `shopify.authenticate.admin(request)`. ### future Features that will be introduced in future releases of this package. You can opt in to these features by setting the corresponding flags. By doing so, you can prepare for future releases in advance and provide feedback on the new features. ### apiKey The API key for your app. Also known as Client ID in your Partner Dashboard. ### apiSecretKey The API secret key for your app. Also known as Client Secret in your Partner Dashboard. ### scopes The scopes your app needs to access the API. ### adminApiAccessToken An app-wide API access token. Only applies to custom apps. ### userAgentPrefix The user agent prefix to use for API requests. ### privateAppStorefrontAccessToken An app-wide API access token for the storefront API. Only applies to custom apps. ### customShopDomains Override values for Shopify shop domains. ### billing Billing configurations for the app. ### restResources REST resources to access the Admin API. You can import these from `@shopify/shopify-api/rest/admin/*`. ### logger Customization options for Shopify logs. ### _logDisabledFutureFlags Whether to log disabled future flags at startup. ### WebhookConfig Record<string, WebhookHandler | WebhookHandler[]> ### HooksConfig ### afterAuth A function to call after a merchant installs your app ### AfterAuthOptions ### session ### admin ### BillingConfig Billing configuration options, indexed by an app-specific plan name. ### [plan: string] ### BillingConfigItem FeatureEnabled<Future, 'v10_lineItemBilling'> extends true ? BillingConfigOneTimePlan | BillingConfigSubscriptionLineItemPlan : BillingConfigLegacyItem ### BillingConfigOneTimePlan ### interval Interval for this plan. Must be set to `OneTime`. ### amount Amount to charge for this plan. ### currencyCode Currency code for this plan. ### BillingConfigSubscriptionLineItemPlan ### replacementBehavior The replacement behavior to use for this plan. ### trialDays How many trial days to give before charging for this plan. ### lineItems The line items for this plan. ### BillingReplacementBehavior ### ApplyImmediately ### ApplyOnNextBillingCycle ### Standard ### BillingConfigRecurringLineItem ### interval The recurring interval for this line item. Must be either `Every30Days` or `Annual`. ### discount An optional discount to apply for this line item. ### amount The amount to charge for this line item. ### currencyCode The currency code for this line item. ### BillingConfigSubscriptionPlanDiscount ### durationLimitInIntervals The number of intervals to apply the discount for. ### value The discount to apply. ### BillingConfigUsageLineItem ### interval The usage interval for this line item. Must be set to `Usage`. ### terms Usage terms for this line item. ### amount The amount to charge for this line item. ### currencyCode The currency code for this line item. ### BillingConfigLegacyItem BillingConfigOneTimePlan | BillingConfigSubscriptionPlan | BillingConfigUsagePlan ### BillingConfigSubscriptionPlan ### interval Recurring interval for this plan. Must be either `Every30Days` or `Annual`. ### trialDays How many trial days to give before charging for this plan. ### replacementBehavior The behavior to use when replacing an existing subscription with a new one. ### discount The discount to apply to this plan. ### amount Amount to charge for this plan. ### currencyCode Currency code for this plan. ### RecurringBillingIntervals RecurringBillingIntervals ### BillingConfigUsagePlan ### interval Interval for this plan. Must be set to `Usage`. ### usageTerms Usage terms for this plan. ### trialDays How many trial days to give before charging for this plan. ### replacementBehavior The behavior to use when replacing an existing subscription with a new one. ### amount Amount to charge for this plan. ### currencyCode Currency code for this plan. ### LogFunction A function used by the library to log events related to Shopify. #### Returns: void #### Params: - severity: LogSeverity - msg: string export type LogFunction = (severity: LogSeverity, msg: string) => void; ### LogSeverity ### Error ### Warning ### Info ### Debug ## Related - [Authenticated contexts](/docs/api/shopify-app-remix/authenticate) - [Unauthenticated contexts](/docs/api/shopify-app-remix/unauthenticated) ## Examples Returns a set of functions that can be used by the app's backend to be able to respond to all Shopify requests. The shape of the returned object changes depending on the value of `distribution`. If it is `AppDistribution.ShopifyAdmin`, then only `ShopifyAppBase` objects are returned, otherwise `ShopifyAppLogin` objects are included. ### sessionStorage ### Storing sessions with Prisma ```typescript import { shopifyApp } from "@shopify/shopify-app-remix/server"; import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma"; import prisma from "~/db.server"; const shopify = shopifyApp({ sessionStorage: new PrismaSessionStorage(prisma), // ...etc }) // shopify.sessionStorage is an instance of PrismaSessionStorage ``` ### addDocumentResponseHeaders ### Return headers on all requests ```typescript import { shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ // ...etc }); export default shopify; export const addDocumentResponseheaders = shopify.addDocumentResponseheaders; ``` ```typescript import { addDocumentResponseHeaders } from "~/shopify.server"; export default function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext ) { const markup = renderToString( <RemixServer context={remixContext} url={request.url} /> ); responseHeaders.set("Content-Type", "text/html"); addDocumentResponseHeaders(request, responseHeaders); return new Response("<!DOCTYPE html>" + markup, { status: responseStatusCode, headers: responseHeaders, }); } ``` ### registerWebhooks ### Registering webhooks after install ```typescript import { DeliveryMethod, shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ hooks: { afterAuth: async ({ session }) => { shopify.registerWebhooks({ session }); } }, webhooks: { APP_UNINSTALLED: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/webhooks", }, }, // ...etc }); ``` ### authenticate ### Authenticate Shopify requests ```typescript import { LATEST_API_VERSION, shopifyApp } from "@shopify/shopify-app-remix/server"; import { restResources } from "@shopify/shopify-api/rest/admin/2023-04"; const shopify = shopifyApp({ restResources, // ...etc }); export default shopify; ``` ```typescript import { LoaderFunctionArgs, json } from "@remix-run/node"; import shopify from "../../shopify.server"; export async function loader({ request }: LoaderFunctionArgs) { const {admin, session, sessionToken, billing} = shopify.authenticate.admin(request); return json(await admin.rest.resources.Product.count({ session })); } ``` ### unauthenticated ### Using unauthenticated contexts ```typescript import { LATEST_API_VERSION, shopifyApp } from "@shopify/shopify-app-remix/server"; import { restResources } from "@shopify/shopify-api/rest/admin/2023-04"; const shopify = shopifyApp({ restResources, // ...etc }); export default shopify; ``` ```typescript import { LoaderFunctionArgs, json } from "@remix-run/node"; import { authenticateExternal } from "~/helpers/authenticate" import shopify from "../../shopify.server"; export async function loader({ request }: LoaderFunctionArgs) { const shop = await authenticateExternal(request) const {admin} = await shopify.unauthenticated.admin(shop); return json(await admin.rest.resources.Product.count({ session })); } ``` ### login ### Creating a login page ```typescript import { LATEST_API_VERSION, shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ // ...etc }); export default shopify; ``` ```typescript import shopify from "../../shopify.server"; export async function loader({ request }: LoaderFunctionArgs) { const errors = shopify.login(request); return json(errors); } export async function action({ request }: ActionFunctionArgs) { const errors = shopify.login(request); return json(errors); } export default function Auth() { const actionData = useActionData<typeof action>(); const [shop, setShop] = useState(""); return ( <Page> <Card> <Form method="post"> <FormLayout> <Text variant="headingMd" as="h2"> Login </Text> <TextField type="text" name="shop" label="Shop domain" helpText="e.g: my-shop-domain.myshopify.com" value={shop} onChange={setShop} autoComplete="on" error={actionData?.errors.shop} /> <Button submit primary> Submit </Button> </FormLayout> </Form> </Card> </Page> ); } ``` ## Future flags Set future flags using the `future` configuration field to opt in to upcoming breaking changes. With this feature, you can prepare for major releases ahead of time, as well as try out new features before they are released. ### FutureFlags ### v3_webhookAdminContext When enabled, returns the same `admin` context (`AdminApiContext`) from `authenticate.webhook` that is returned from `authenticate.admin`. ### v3_authenticatePublic When enabled authenticate.public() will not work. Use authenticate.public.checkout() instead. ### v3_lineItemBilling When enabled allows you to pass billing plans with line items when creating a new app subscriptions. ### unstable_newEmbeddedAuthStrategy When enabled, embedded apps will fetch access tokens via [token exchange](https://shopify.dev/docs/apps/auth/get-access-tokens/token-exchange). This assumes the app has scopes declared for [Shopify managing installation](https://shopify.dev/docs/apps/auth/installation#shopify-managed-installation). Learn more about this [new embedded app auth strategy](https://shopify.dev/docs/api/shopify-app-remix#embedded-auth-strategy). ## Related - [Authenticated contexts](/docs/api/shopify-app-remix/authenticate) - [Unauthenticated contexts](/docs/api/shopify-app-remix/unauthenticated) ## Examples Returns a set of functions that can be used by the app's backend to be able to respond to all Shopify requests. The shape of the returned object changes depending on the value of `distribution`. If it is `AppDistribution.ShopifyAdmin`, then only `ShopifyAppBase` objects are returned, otherwise `ShopifyAppLogin` objects are included. ### sessionStorage ### Storing sessions with Prisma ```typescript import { shopifyApp } from "@shopify/shopify-app-remix/server"; import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma"; import prisma from "~/db.server"; const shopify = shopifyApp({ sessionStorage: new PrismaSessionStorage(prisma), // ...etc }) // shopify.sessionStorage is an instance of PrismaSessionStorage ``` ### addDocumentResponseHeaders ### Return headers on all requests ```typescript import { shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ // ...etc }); export default shopify; export const addDocumentResponseheaders = shopify.addDocumentResponseheaders; ``` ```typescript import { addDocumentResponseHeaders } from "~/shopify.server"; export default function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext ) { const markup = renderToString( <RemixServer context={remixContext} url={request.url} /> ); responseHeaders.set("Content-Type", "text/html"); addDocumentResponseHeaders(request, responseHeaders); return new Response("<!DOCTYPE html>" + markup, { status: responseStatusCode, headers: responseHeaders, }); } ``` ### registerWebhooks ### Registering webhooks after install ```typescript import { DeliveryMethod, shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ hooks: { afterAuth: async ({ session }) => { shopify.registerWebhooks({ session }); } }, webhooks: { APP_UNINSTALLED: { deliveryMethod: DeliveryMethod.Http, callbackUrl: "/webhooks", }, }, // ...etc }); ``` ### authenticate ### Authenticate Shopify requests ```typescript import { LATEST_API_VERSION, shopifyApp } from "@shopify/shopify-app-remix/server"; import { restResources } from "@shopify/shopify-api/rest/admin/2023-04"; const shopify = shopifyApp({ restResources, // ...etc }); export default shopify; ``` ```typescript import { LoaderFunctionArgs, json } from "@remix-run/node"; import shopify from "../../shopify.server"; export async function loader({ request }: LoaderFunctionArgs) { const {admin, session, sessionToken, billing} = shopify.authenticate.admin(request); return json(await admin.rest.resources.Product.count({ session })); } ``` ### unauthenticated ### Using unauthenticated contexts ```typescript import { LATEST_API_VERSION, shopifyApp } from "@shopify/shopify-app-remix/server"; import { restResources } from "@shopify/shopify-api/rest/admin/2023-04"; const shopify = shopifyApp({ restResources, // ...etc }); export default shopify; ``` ```typescript import { LoaderFunctionArgs, json } from "@remix-run/node"; import { authenticateExternal } from "~/helpers/authenticate" import shopify from "../../shopify.server"; export async function loader({ request }: LoaderFunctionArgs) { const shop = await authenticateExternal(request) const {admin} = await shopify.unauthenticated.admin(shop); return json(await admin.rest.resources.Product.count({ session })); } ``` ### login ### Creating a login page ```typescript import { LATEST_API_VERSION, shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ // ...etc }); export default shopify; ``` ```typescript import shopify from "../../shopify.server"; export async function loader({ request }: LoaderFunctionArgs) { const errors = shopify.login(request); return json(errors); } export async function action({ request }: ActionFunctionArgs) { const errors = shopify.login(request); return json(errors); } export default function Auth() { const actionData = useActionData<typeof action>(); const [shop, setShop] = useState(""); return ( <Page> <Card> <Form method="post"> <FormLayout> <Text variant="headingMd" as="h2"> Login </Text> <TextField type="text" name="shop" label="Shop domain" helpText="e.g: my-shop-domain.myshopify.com" value={shop} onChange={setShop} autoComplete="on" error={actionData?.errors.shop} /> <Button submit primary> Submit </Button> </FormLayout> </Form> </Card> </Page> ); } ```