--- title: Flow description: >- Contains functions for verifying Shopify Flow extensions. See the [Flow documentation](https://shopify.dev/docs/apps/flow/actions/endpoints) for more information. api_version: v3 api_name: shopify-app-remix source_url: html: 'https://shopify.dev/docs/api/shopify-app-remix/v3/authenticate/flow' md: 'https://shopify.dev/docs/api/shopify-app-remix/v3/authenticate/flow.md' --- # Flow Contains functions for verifying Shopify Flow extensions. See the [Flow documentation](https://shopify.dev/docs/apps/flow/actions/endpoints) for more information. ## authenticate.​flow([request](#authenticateflow-propertydetail-request)​) Verifies requests coming from Shopify Flow extensions. ### Parameters * request Request required ### Returns * Promise\> ### FlowContext * admin An admin context for the Flow request. Returned only if there is a session for the shop. ```ts AdminApiContext ``` * payload The payload from the Flow request. ```ts any ``` * session A session with an offline token for the shop. Returned only if there is a session for the shop. ```ts Session ``` ````ts export interface FlowContext< ConfigArg extends AppConfigArg, Resources extends ShopifyRestResources = ShopifyRestResources, > { /** * A session with an offline token for the shop. * * Returned only if there is a session for the shop. * * @example * Shopify session for the Flow request. * Use the session associated with this request. * ```ts * // /app/routes/flow.tsx * import { ActionFunctionArgs } from "@remix-run/node"; * import { authenticate } from "../shopify.server"; * * export const action = async ({ request }: ActionFunctionArgs) => { * const { session, admin } = await authenticate.flow(request); * * console.log(session.id) * * return new Response(); * }; * ``` */ session: Session; /** * The payload from the Flow request. * * @example * Flow payload. * Get the request's POST payload. * ```ts * // /app/routes/flow.tsx * import { ActionFunctionArgs } from "@remix-run/node"; * import { authenticate } from "../shopify.server"; * * export const action = async ({ request }: ActionFunctionArgs) => { * const { payload } = await authenticate.flow(request); * return new Response(); * }; * ``` */ payload: any; /** * An admin context for the Flow request. * * Returned only if there is a session for the shop. * * @example * Flow admin context. * Use the `admin` object in the context to interact with the Admin API. * ```ts * // /app/routes/flow.tsx * import { ActionFunctionArgs } from "@remix-run/node"; * import { authenticate } from "../shopify.server"; * * export async function action({ request }: ActionFunctionArgs) { * const { admin } = await authenticate.flow(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 }); * } * ``` */ admin: AdminApiContext; } ```` Examples ### Examples * #### Set a metafield on a customer after a flow call ##### Description Handle a flow action call ##### /app/routes/\*\*.ts ```typescript import {type ActionFunctionArgs} from '@remix-run/node'; import {authenticate} from '../shopify.server'; export const action = async ({request}: ActionFunctionArgs) => { const {admin, payload} = await authenticate.flow(request); const customerId = payload.properties.customer_id; const response = await admin.graphql( `#graphql mutation setMetafield($customerId: ID!, $time: String!) { metafieldsSet(metafields: { ownerId: $customerId namespace: "my-app", key: "last_flow_update", value: $time, type: "string", }) { metafields { key value } } } `, { variables: { customerId, time: new Date().toISOString(), }, }, ); const body = await response.json(); console.log('Updated value', body.data!.metafieldsSet!.metafields![0].value); return new Response(); }; ``` * #### Flow admin context ##### Description Use the \`admin\` object in the context to interact with the Admin API. ##### /app/routes/flow\.tsx ```typescript import { ActionFunctionArgs } from "@remix-run/node"; import { authenticate } from "../shopify.server"; export async function action({ request }: ActionFunctionArgs) { const { admin } = await authenticate.flow(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 }); } ``` * #### Flow payload ##### Description Get the request's POST payload. ##### /app/routes/flow\.tsx ```typescript import { ActionFunctionArgs } from "@remix-run/node"; import { authenticate } from "../shopify.server"; export const action = async ({ request }: ActionFunctionArgs) => { const { payload } = await authenticate.flow(request); return new Response(); }; ``` * #### Shopify session for the Flow request ##### Description Use the session associated with this request. ##### /app/routes/flow\.tsx ```typescript import { ActionFunctionArgs } from "@remix-run/node"; import { authenticate } from "../shopify.server"; export const action = async ({ request }: ActionFunctionArgs) => { const { session, admin } = await authenticate.flow(request); console.log(session.id) return new Response(); }; ``` ## Related [Interact with the Admin API. - Admin API context](https://shopify.dev/docs/api/shopify-app-remix/apis/admin-api) [Receive requests from Flow. - Flow action endpoints](https://shopify.dev/docs/apps/flow/actions/endpoints)