--- title: Unauthenticated admin description: |- Allows interacting with the Admin API when working outside of Shopify requests. This enables apps to integrate with 3rd party services and perform background tasks. > Caution: > This function doesn't perform **any** validation and shouldn't rely on raw user input. When using this function, consider the following: #### Background tasks Apps should ensure that the shop domain is authenticated when enqueueing jobs. #### 3rd party service requests Apps must obtain the shop domain from the 3rd party service in a secure way. api_version: v4 latest api_name: shopify-app-remix source_url: html: https://shopify.dev/docs/api/shopify-app-remix/latest/unauthenticated/unauthenticated-admin md: https://shopify.dev/docs/api/shopify-app-remix/latest/unauthenticated/unauthenticated-admin.md --- # Unauthenticated adminobject Allows interacting with the Admin API when working outside of Shopify requests. This enables apps to integrate with 3rd party services and perform background tasks. Caution This function doesn't perform **any** validation and shouldn't rely on raw user input. When using this function, consider the following: #### Background tasks Apps should ensure that the shop domain is authenticated when enqueueing jobs. #### 3rd party service requests Apps must obtain the shop domain from the 3rd party service in a secure way. ## unauthenticated.​admin([shop](#unauthenticatedadmin-propertydetail-shop)​) Creates an unauthenticated Admin context. ### Parameters * shop string required ### Returns * Promise\ ### UnauthenticatedAdminContext * admin Methods for interacting with the GraphQL Admin API for the given store. ```ts AdminApiContext ``` * 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. ```ts Session ``` ````ts export interface UnauthenticatedAdminContext { /** * 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. * * @example * Using the offline session. * Get your app's shop-specific data using the returned offline `session` object. * ```ts * // /app/routes/**\/*.ts * import { LoaderFunctionArgs, json } from "@remix-run/node"; * import { unauthenticated } from "../shopify.server"; * import { getMyAppData } from "~/db/model.server"; * * export const loader = async ({ request }: LoaderFunctionArgs) => { * const shop = getShopFromExternalRequest(request); * const { session } = await unauthenticated.admin(shop); * return json(await getMyAppData({shop: session.shop)); * }; * ``` */ session: Session; /** * Methods for interacting with the GraphQL Admin API for the given store. * * @example * Querying the GraphQL API. * Use `admin.graphql` to make query / mutation requests. * ```ts * // /app/routes/**\/*.ts * import { ActionFunctionArgs } from "@remix-run/node"; * import { unauthenticated } from "../shopify.server"; * * export async function action({ request }: ActionFunctionArgs) { * const shop = getShopFromExternalRequest(request); * const { admin } = await unauthenticated.admin(shop); * * 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 }); * } * ``` * * ```ts * // /app/shopify.server.ts * import { shopifyApp } from "@shopify/shopify-app-remix/server"; * * const shopify = shopifyApp({ * // ...etc * }); * export default shopify; * export const unauthenticated = shopify.unauthenticated; * ``` */ admin: AdminApiContext; } ```` ### AdminApiContext * graphql Methods for interacting with the Shopify Admin GraphQL API ```ts GraphQLClient ``` ````ts export interface AdminApiContext { /** * Methods for interacting with the Shopify Admin GraphQL API * * {@link https://shopify.dev/docs/api/admin-graphql} * {@link https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/clients/Graphql.md} * * @example * Querying the GraphQL API. * Use `admin.graphql` to make query / mutation requests. * ```ts * // /app/routes/**\/*.ts * import { ActionFunctionArgs } from "@remix-run/node"; * import { authenticate } from "../shopify.server"; * * export const action = async ({ request }: ActionFunctionArgs) => { * const { admin } = await authenticate.admin(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({ * productId: productData.data?.productCreate?.product?.id, * }); * } * ``` * * ```ts * // /app/shopify.server.ts * import { shopifyApp } from "@shopify/shopify-app-remix/server"; * * const shopify = shopifyApp({ * // ... * }); * export default shopify; * export const authenticate = shopify.authenticate; * ``` * * @example * Handling GraphQL errors. * Catch `GraphqlQueryError` errors to see error messages from the API. * ```ts * // /app/routes/**\/*.ts * import { ActionFunctionArgs } from "@remix-run/node"; * import { authenticate } from "../shopify.server"; * * export const action = async ({ request }: ActionFunctionArgs) => { * const { admin } = await authenticate.admin(request); * * try { * const response = await admin.graphql( * `#graphql * query incorrectQuery { * products(first: 10) { * nodes { * not_a_field * } * } * }`, * ); * * return json({ data: await response.json() }); * } catch (error) { * if (error instanceof GraphqlQueryError) { * // error.body.errors: * // { graphQLErrors: [ * // { message: "Field 'not_a_field' doesn't exist on type 'Product'" } * // ] } * return json({ errors: error.body?.errors }, { status: 500 }); * } * return json({ message: "An error occurred" }, { status: 500 }); * } * } * ``` * * ```ts * // /app/shopify.server.ts * import { shopifyApp } from "@shopify/shopify-app-remix/server"; * * const shopify = shopifyApp({ * // ... * }); * export default shopify; * export const authenticate = shopify.authenticate; * ``` */ graphql: GraphQLClient; } ```` ### GraphQLClient * query ```ts Operation extends keyof Operations ``` * options ```ts GraphQLQueryOptions ``` 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\; } ```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; } ``` ```ts < Operation extends keyof Operations, >( query: Operation, options?: GraphQLQueryOptions, ) => 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["variables"] ``` ```ts export interface GraphQLQueryOptions< Operation extends keyof Operations, Operations extends AllOperations, > { /** * The variables to pass to the operation. */ variables?: ApiClientRequestOptions['variables']; /** * The version of the API to use for the request. */ apiVersion?: ApiVersion; /** * Additional headers to include in the request. */ headers?: Record; /** * The total number of times to try the request if it fails. */ tries?: number; /** * An optional AbortSignal to cancel the request. */ signal?: AbortSignal; } ``` ## Examples ### admin Querying the GraphQL API Use `admin.graphql` to make query / mutation requests. ### Examples * #### Querying the GraphQL API ##### Description Use \`admin.graphql\` to make query / mutation requests. ##### /app/routes/\*\*\\/\*.ts ```typescript import { ActionFunctionArgs } from "@remix-run/node"; import { unauthenticated } from "../shopify.server"; export async function action({ request }: ActionFunctionArgs) { const shop = getShopFromExternalRequest(request); const { admin } = await unauthenticated.admin(shop); 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 }); } ``` ##### /app/shopify.server.ts ```typescript import { shopifyApp } from "@shopify/shopify-app-remix/server"; const shopify = shopifyApp({ // ...etc }); export default shopify; export const unauthenticated = shopify.unauthenticated; ``` ### session Using the offline session Get your app's shop-specific data using the returned offline `session` object. ### Examples * #### Using the offline session ##### Description Get your app's shop-specific data using the returned offline \`session\` object. ##### /app/routes/\*\*\\/\*.ts ```typescript import { LoaderFunctionArgs, json } from "@remix-run/node"; import { unauthenticated } from "../shopify.server"; import { getMyAppData } from "~/db/model.server"; export const loader = async ({ request }: LoaderFunctionArgs) => { const shop = getShopFromExternalRequest(request); const { session } = await unauthenticated.admin(shop); return json(await getMyAppData({shop: session.shop)); }; ``` ## Related [Interact with the Admin API. - API context](https://shopify.dev/docs/api/shopify-app-remix/apis/admin-api)