--- title: App proxy description: >- App proxies take requests to Shopify links, and redirect them to external links. api_version: v3 api_name: shopify-app-remix source_url: html: >- https://shopify.dev/docs/api/shopify-app-remix/v3/authenticate/public/app-proxy md: >- https://shopify.dev/docs/api/shopify-app-remix/v3/authenticate/public/app-proxy.md --- # App proxy [App proxies](https://shopify.dev/docs/apps/online-store/app-proxies) take requests to Shopify links, and redirect them to external links. The `authenticate.public.appProxy` function validates requests made to app proxies, and returns a context to enable querying Shopify APIs. **Note:** If the store has not installed the app, store-related properties such as `admin` or `storefront` will be `undefined` ## authenticate.​public.​app​Proxy(**[request](#authenticatepublicappproxy-propertydetail-request)**​) Authenticates requests coming to the app from Shopify app proxies. ### Parameters * **request** **Request** **required** ### Returns * **Promise< AppProxyContext | AppProxyContextWithSession\ >** ### AppProxyContext * 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. ```ts undefined ``` * liquid A utility for creating a Liquid Response. ```ts LiquidResponseFunction ``` * 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. ```ts undefined ``` * storefront No session is available for the shop that made this request. Therefore no method for interacting with the Storefront API is available. ```ts undefined ``` ### LiquidResponseFunction * body ```ts string ``` * initAndOptions ```ts number | (ResponseInit & Options) ``` returns ```ts Response ``` ### Options * layout Whether to use the shop's theme layout around the Liquid content. ```ts boolean ``` ### AppProxyContextWithSession * admin Methods for interacting with the GraphQL / REST Admin APIs for the store that made the request. ```ts AdminApiContext ``` * liquid A utility for creating a Liquid Response. ```ts LiquidResponseFunction ``` * 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. ```ts Session ``` * storefront Method for interacting with the Shopify Storefront Graphql API for the store that made the request. ```ts StorefrontContext ``` ### AdminApiContext Provides utilities that apps can use to make requests to the Admin API. ```ts FeatureEnabled extends true ? AdminApiContextWithoutRest : AdminApiContextWithRest ``` ### FeatureEnabled ```ts Future extends FutureFlags ? Future[Flag] extends true ? true : false : false ``` ### FutureFlags 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. * removeRest When enabled, methods for interacting with the admin REST API will not be returned. This affects: \* \`authenticate.admin(request)\` \* \`authenticate.webhook(request)\` \* \`authenticate.flow(request)\` \* \`authenticate.appProxy(request)\` \* \`authenticate.fulfillmentService(request)\` \* \`unauthenticated.admin(shop)\` In a future release we will remove REST from the package completely. Please see: \[https://www\.shopify.com/ca/partners/blog/all-in-on-graphql]\(https://www\.shopify.com/ca/partners/blog/all-in-on-graphql) ```ts boolean ``` * unstable\_newEmbeddedAuthStrategy When enabled, embedded apps will fetch access tokens via \[token exchange]\(/docs/apps/auth/get-access-tokens/token-exchange). This assumes the app has scopes declared for \[Shopify managing installation]\(/docs/apps/auth/installation#shopify-managed-installation). Learn more about this \[new embedded app auth strategy]\(/docs/api/shopify-app-remix#embedded-auth-strategy). ```ts boolean ``` ### AdminApiContextWithoutRest * graphql Methods for interacting with the Shopify Admin GraphQL API ```ts GraphQLClient ``` ### GraphQLClient * query ```ts Operation extends keyof Operations ``` * options ```ts GraphQLQueryOptions ``` returns ```ts interface Promise { /** * 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(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; /** * 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(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; }, interface Promise {}, Promise: PromiseConstructor, interface Promise { readonly [Symbol.toStringTag]: string; }, interface Promise { /** * 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; } ``` ### GraphQLQueryOptions * apiVersion The version of the API to use for the request. ```ts ApiVersion ``` * headers Additional headers to include in the request. ```ts Record ``` * signal An optional AbortSignal to cancel the request. ```ts AbortSignal ``` * tries The total number of times to try the request if it fails. ```ts number ``` * variables The variables to pass to the operation. ```ts ApiClientRequestOptions ``` ### ApiVersion * October24 ```ts 2024-10 ``` * January25 ```ts 2025-01 ``` * April25 ```ts 2025-04 ``` * July25 ```ts 2025-07 ``` * October25 ```ts 2025-10 ``` * January26 ```ts 2026-01 ``` * April26 ```ts 2026-04 ``` * Unstable ```ts unstable ``` ### AdminApiContextWithRest * graphql Methods for interacting with the Shopify Admin GraphQL API ```ts GraphQLClient ``` * rest Methods for interacting with the Shopify Admin REST API ```ts RestClientWithResources ``` ### RestClientWithResources ```ts RemixRestClient & {resources: Resources} ``` ### RemixRestClient * session ```ts Session ``` * get Performs a GET request on the given path. ```ts (params: GetRequestParams) => Promise ``` * post Performs a POST request on the given path. ```ts (params: PostRequestParams) => Promise ``` * put Performs a PUT request on the given path. ```ts (params: PostRequestParams) => Promise ``` * delete Performs a DELETE request on the given path. ```ts (params: GetRequestParams) => Promise ``` ### 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. ```ts string ``` * shop The Shopify shop domain, such as \`example.myshopify.com\`. ```ts string ``` * state The state of the session. Used for the OAuth authentication code flow. ```ts string ``` * isOnline Whether the access token in the session is online or offline. ```ts boolean ``` * scope The desired scopes for the access token, at the time the session was created. ```ts string ``` * expires The date the access token expires. ```ts Date ``` * accessToken The access token for the session. ```ts string ``` * onlineAccessInfo Information on the user for the session. Only present for online sessions. ```ts OnlineAccessInfo ``` * isActive Whether the session is active. Active sessions have an access token that is not expired, and has has the given scopes if scopes is equal to a truthy value. ```ts (scopes: string | string[] | AuthScopes, withinMillisecondsOfExpiry?: number) => boolean ``` * isScopeChanged Whether the access token includes the given scopes if they are provided. ```ts (scopes: string | string[] | AuthScopes) => boolean ``` * isScopeIncluded Whether the access token includes the given scopes. ```ts (scopes: string | string[] | AuthScopes) => boolean ``` * isExpired Whether the access token is expired. ```ts (withinMillisecondsOfExpiry?: number) => boolean ``` * toObject Converts an object with data into a Session. ```ts () => SessionParams ``` * equals Checks whether the given session is equal to this session. ```ts (other: Session) => boolean ``` * toPropertyArray Converts the session into an array of key-value pairs. ```ts (returnUserData?: boolean) => [string, string | number | boolean][] ``` ### OnlineAccessInfo * associated\_user The user associated with the access token. ```ts OnlineAccessUser ``` * associated\_user\_scope The effective set of scopes for the session. ```ts string ``` * expires\_in How long the access token is valid for, in seconds. ```ts number ``` ### OnlineAccessUser * account\_owner Whether the user is the account owner. ```ts boolean ``` * collaborator Whether the user is a collaborator. ```ts boolean ``` * email The user's email address. ```ts string ``` * email\_verified Whether the user has verified their email address. ```ts boolean ``` * first\_name The user's first name. ```ts string ``` * id The user's ID. ```ts number ``` * last\_name The user's last name. ```ts string ``` * locale The user's locale. ```ts string ``` ### AuthScopes A class that represents a set of access token scopes. * has Checks whether the current set of scopes includes the given one. ```ts (scope: string | string[] | AuthScopes) => boolean ``` * equals Checks whether the current set of scopes equals the given one. ```ts (otherScopes: string | string[] | AuthScopes) => boolean ``` * toString Returns a comma-separated string with the current set of scopes. ```ts () => string ``` * toArray Returns an array with the current set of scopes. ```ts (returnOriginalScopes?: boolean) => any[] ``` ### SessionParams * \[key: string] ```ts any ``` * accessToken The access token for the session. ```ts string ``` * expires The date the access token expires. ```ts Date ``` * id The unique identifier for the session. ```ts string ``` * isOnline Whether the access token in the session is online or offline. ```ts boolean ``` * onlineAccessInfo Information on the user for the session. Only present for online sessions. ```ts OnlineAccessInfo | StoredOnlineAccessInfo ``` * scope The scopes for the access token. ```ts string ``` * shop The Shopify shop domain. ```ts string ``` * state The state of the session. Used for the OAuth authentication code flow. ```ts string ``` ### StoredOnlineAccessInfo ```ts Omit & { associated_user: Partial; } ``` ### StorefrontContext Provides utilities that apps can use to make requests to the Storefront API. * 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). ```ts GraphQLClient ``` Examples ### Examples * #### ##### Description Authenticate and fetch product information ##### /app/routes/\*\*.ts ```ts import type {LoaderFunctionArgs} from '@remix-run/node'; import {authenticate} from '../shopify.server'; export const loader = async ({request}: LoaderFunctionArgs) => { const {storefront, liquid} = await authenticate.public.appProxy(request); if (!storefront) { return new Response(); } const response = await storefront.graphql( `#graphql query productTitle { products(first: 1) { nodes { title } } }`, ); const body = await response.json(); const title = body.data.products.nodes[0].title; return liquid(`Found product ${title} from {{shop.name}}`); }; ``` * #### ##### Description Use the \`admin\` object to interact with the admin GraphQL API. ##### app/routes/\*\*\\/.ts ```ts import { json } from "@remix-run/node"; import { authenticate } from "../shopify.server"; export async function action({ request }: ActionFunctionArgs) { const { admin } = await authenticate.public.appProxy(request); const response = await admin.graphql( `#graphql mutation populateProduct($input: ProductInput!) { productCreate(input: $input) { product { id } } }`, { variables: { input: { title: "Product Name" } } } ); const productData = await response.json(); return json({ data: productData.data }); } ``` * #### ##### Description Use the \`liquid\` helper to render a \`Response\` with Liquid content using the shop's theme. See the \[Liquid reference]\(https://shopify.dev/docs/api/liquid) for all the features it enables. ##### /app/routes/\*\*\\/\*.ts ```ts import {authenticate} from "~/shopify.server" export async function loader({ request }) { const {liquid} = await authenticate.public.appProxy(request); return liquid("Hello {{shop.name}}"); } ``` * #### ##### Description Set the \`layout\` option to \`false\` to render the Liquid content without a theme. ##### /app/routes/\*\*\\/\*.ts ```ts import {authenticate} from "~/shopify.server" export async function loader({ request }) { const {liquid} = await authenticate.public.appProxy(request); return liquid( "Hello {{shop.name}}", { layout: false } ); } ``` * #### ##### Description Handle form submissions through an app proxy. ##### app/routes/apps.proxy.my-action.tsx ```ts import { redirect } from "@remix-run/node"; import { authenticate } from "~/shopify.server"; export async function loader({ request }) { const { liquid } = await authenticate.public.appProxy(request); return liquid(`
`); } export async function action({ request }) { await authenticate.public.appProxy(request); const formData = await request.formData(); const field = formData.get("field")?.toString(); // Perform actions here if (field) { console.log("Field:", field); } // Return to the form page return redirect("/apps/proxy/my-action"); } ``` * #### ##### Description Get the session for the shop that initiated the request to the app proxy. ##### app/routes/\*\*\\/.ts ```ts import { json } from "@remix-run/node"; import { authenticate } from "../shopify.server"; import { getMyAppModelData } from "~/db/model.server"; export const loader = async ({ request }) => { // Get the session for the shop that initiated the request to the app proxy. const { session } = await authenticate.public.appProxy(request); // Use the session data to make to queries to your database or additional requests. return json( await getMyAppModelData({shop: session.shop}) ); }; ``` * #### ##### Description Use the \`storefront\` object to interact with the GraphQL API. ##### app/routes/\*\*\\/.ts ```ts import { json } from "@remix-run/node"; import { authenticate } from "../shopify.server"; export async function action({ request }: ActionFunctionArgs) { const { storefront } = await authenticate.public.appProxy(request); const response = await storefront.graphql( `#graphql query blogIds { blogs(first: 10) { edges { node { id } } } }` ); return json(await response.json()); } ``` *** ## Related [Interact with the Admin API. - Admin API context](https://shopify.dev/docs/api/shopify-app-remix/v3/apis/admin-api) [Interact with the Storefront API. - Storefront API context](https://shopify.dev/docs/api/shopify-app-remix/v3/apis/storefront-api) [Use the shop's theme to render a template. - Liquid reference](https://shopify.dev/docs/api/liquid) ***