--- title: Intents API description: >- The Intents API lets you invoke built-in customer account workflows like updating payment methods on subscription contracts. Use this API to trigger standard Shopify actions from your extension without rebuilding complex flows from scratch. api_version: 2026-04 api_name: customer-account-ui-extensions source_url: html: >- https://shopify.dev/docs/api/customer-account-ui-extensions/latest/target-apis/platform-apis/intents-api md: >- https://shopify.dev/docs/api/customer-account-ui-extensions/latest/target-apis/platform-apis/intents-api.md --- # Intents API The Intents API lets you invoke built-in customer account workflows like updating payment methods on subscription contracts. Use this API to trigger standard Shopify actions from your extension without rebuilding complex flows from scratch. Intents can be invoked using either a structured object or a string query format. Both approaches return an activity handle that you can `await` to track the workflow's completion. **Note:** The Intents API currently supports a single resource: opening the payment method replacement flow for [subscription contracts](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionContract). See [Supported resources](#supported-resources) for details. ### Use cases * **Update subscription payment methods**: Open the built-in payment method replacement flow for a subscription contract, letting customers swap their vaulted card without leaving the extension. * **Trigger standard account workflows**: Invoke Shopify-managed experiences for common tasks instead of building custom UI for each one. * **Track workflow outcomes**: Await the result of `shopify.intents.invoke()` to detect when a workflow completes and update your extension's UI accordingly. ### Support Targets (24) ### Supported targets * [customer-account.​footer.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/footer#footer-render-after-) * [customer-account.​order-index.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-index-announcement-) * [customer-account.​order-index.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-index-block-) * [customer-account.​order-status.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#order-status-announcement-) * [customer-account.​order-status.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#order-status-block-) * [customer-account.​order-status.​cart-line-item.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#cart-line-item-render-after-) * [customer-account.​order-status.​cart-line-list.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#cart-line-list-render-after-) * [customer-account.​order-status.​customer-information.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-status#customer-information-render-after-) * [customer-account.​order-status.​fulfillment-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/fulfillment-status#fulfillment-status-targets) * [customer-account.​order-status.​payment-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/payments-and-returns#payments-and-returns-targets) * [customer-account.​order-status.​return-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/payments-and-returns#return-details-render-after-) * [customer-account.​order-status.​unfulfilled-items.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/fulfillment-status#unfulfilled-items-render-after-) * [customer-account.​order.​action.​menu-item.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-action-menu-item-) * [customer-account.​order.​action.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/order-actions#order-action-) * [customer-account.​order.​page.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/full-page#order-specific-full-page-) * [customer-account.​page.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/full-page#customer-account-full-page-) * [customer-account.​profile.​addresses.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-default#profile-page-default-targets-) * [customer-account.​profile.​announcement.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-default#profile-announcement-) * [customer-account.​profile.​block.​render](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-default#profile-block-) * [customer-account.​profile.​company-details.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#profile-page-b2b-targets-) * [customer-account.​profile.​company-location-addresses.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#company-location-addresses-render-after-) * [customer-account.​profile.​company-location-payment.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#company-location-payment-render-after-) * [customer-account.​profile.​company-location-staff.​render-after](https://shopify.dev/docs/api/customer-account-ui-extensions/2026-04/targets/profile-page-b2b#company-location-staff-render-after-) * customer-account.​profile.​payment.​render-after ### invoke method The `invoke` method opens a Shopify-managed workflow for managing resources. The method returns a promise that resolves to an activity handle you can await to get the workflow result. The method accepts either: * **String query:** `${action}:${type},${value}` with optional second parameter (`IntentQueryOptions`) * **Object:** Properties for `action`, `type`, `value`, and `data` ### IntentQueryOptions parameters Optional parameters for the `invoke` method when using the string query format: * **`value`** (`string`): The resource identifier (for example, `'gid://shopify/SubscriptionContract/123'`). Required when opening existing resources. * **`data`** (`{ [key: string]: unknown }`): Additional context required by specific resource types. For example, subscription contracts require `{ field: 'paymentMethod' }`. - **invoke** **{ (query: IntentQuery): Promise\; (intentURL: string, options?: IntentQueryOptions): Promise\; }** **required** Triggers a built-in Shopify workflow by passing a structured intent object. Specify an `action` (such as `'open'`), a resource `type`, and an optional `value` identifying the resource. Returns a promise that resolves to an `IntentActivity` you can use to track completion. Triggers a built-in Shopify workflow using a URL string in the format `action:type[,value][?params]`. Use this overload when composing intents from dynamic strings rather than structured objects. ### IntentQuery Structured description of an intent to invoke. Use this object form when programmatically composing an intent at runtime. It pairs an action (verb) with a resource type and optional inputs. * action Verb describing the operation to perform on the target resource. Common values include \`create\` and \`open\`. The set of allowed verbs is intent-specific; unknown verbs will fail validation. ```ts IntentAction ``` * data Optional input payload passed to the intent. Used to seed forms or supply parameters. The accepted shape is intent-specific. For example, replacing a payment method on a subscription contract requires \`{ field: 'paymentMethod' }\`. ```ts Record ``` * type The resource type (such as \`shopify/SubscriptionContract\`). ```ts string ``` * value The resource identifier for edit actions (such as \`gid://shopify/SubscriptionContract/123\`). ```ts string ``` ### IntentAction Allowed actions that can be performed by an intent. Common actions include: - \`'create'\`: Initiate creation of a new resource. - \`'open'\`: Modify an existing resource. ```ts 'create' | 'open' | string ``` ### IntentActivity Activity handle for tracking intent workflow progress. * complete A Promise that resolves when the intent workflow completes, returning the response. ```ts Promise ``` ### IntentResponse Result of an intent activity. Discriminated union representing all possible completion outcomes for an invoked intent. ```ts SuccessIntentResponse | ErrorIntentResponse | ClosedIntentResponse ``` ### SuccessIntentResponse Successful intent completion. - \`code\` is always \`'ok'\` - \`data\` contains the output payload * code Always \`'ok'\` for a successful response. ```ts 'ok' ``` * data Validated output payload produced by the workflow. The shape is intent-specific. Consumers should narrow by \`code === 'ok'\` before accessing. ```ts Record ``` ### ErrorIntentResponse Failed intent completion. - \`code\` is always \`'error'\` - \`message\` summarizes the failure - \`issues\` optionally provides structured details for validation or field-specific problems following the Standard Schema convention * code Set to \`'error'\` when present. This property is optional. ```ts 'error' ``` * issues Structured details for validation or field-specific problems, following the Standard Schema convention. ```ts { path?: string[]; message?: string; }[] ``` * message A human-readable summary of the failure. ```ts string ``` ### ClosedIntentResponse User dismissed or closed the workflow without completing it. Distinct from \`error\`: no failure occurred, the activity was simply abandoned by the user. * code Always \`'closed'\` when the user dismissed the workflow without completing it. ```ts 'closed' ``` ### IntentQueryOptions Options for URL-based invocations. When invoking via URL syntax, \`action\` and \`type\` are parsed from the string. This companion type captures the remaining optional fields that can be provided alongside the URL. * data Optional input payload passed to the intent. Used to seed forms or supply parameters. The accepted shape is intent-specific. For example, replacing a payment method on a subscription contract requires \`{ field: 'paymentMethod' }\`. ```ts Record ``` * value The resource identifier for edit actions (such as \`gid://shopify/SubscriptionContract/123\`). ```ts string ``` ### Supported resources The following table shows which resource types you can open and what values you need to pass for `value` and `data`. #### Subscription contract [Subscription contracts](https://shopify.dev/docs/api/admin-graphql/latest/objects/SubscriptionContract) represent recurring billing agreements. Use this to open the payment method replacement flow for an active subscription. | Action | Type | Value | Data | | - | - | - | - | | `open` | `shopify/SubscriptionContract` | `gid://shopify/SubscriptionContract/{id}` | `{ field: 'paymentMethod' }` | ### Intent​Response The result returned when an intent workflow completes. Check the `code` property to determine the outcome: * `'ok'`: The customer completed the workflow successfully. * `'error'`: The workflow failed due to validation or other errors. * `'closed'`: The customer cancelled without completing. **`SuccessIntentResponse | ErrorIntentResponse | ClosedIntentResponse`** ### ClosedIntentResponse * **code** **'closed'** **required** Always `'closed'` when the user dismissed the workflow without completing it. ### ErrorIntentResponse * **code** **'error'** Set to `'error'` when present. This property is optional. * **issues** **{ path?: string\[]; message?: string; }\[]** Structured details for validation or field-specific problems, following the Standard Schema convention. * **message** **string** A human-readable summary of the failure. ### SuccessIntentResponse * **code** **'ok'** **required** Always `'ok'` for a successful response. * **data** **Record\** **required** Validated output payload produced by the workflow. The shape is intent-specific. Consumers should narrow by `code === 'ok'` before accessing. Examples ### Examples * #### ##### Description Open the built-in payment method replacement flow for a subscription contract. This example invokes the intent using the structured object format and logs the result when the workflow completes. ##### jsx ```tsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default async () => { render(, document.body); }; function Extension() { async function handleReplacePaymentMethod() { const activity = await shopify.intents.invoke( { action: 'open', type: 'shopify/SubscriptionContract', value: 'gid://shopify/SubscriptionContract/123', data: {field: 'paymentMethod'}, }, ); const response = await activity.complete; if (response.code === 'ok') { console.log( 'Intent completed successfully', response.data, ); } } return ( Edit subscription payment method ); } ``` * #### ##### Description Handle different outcomes after an intent workflow completes, including success, cancellation, and errors. This example awaits \`activity.complete\`, checks the response code, and updates the UI with a toast notification based on the result. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; import {useState} from 'preact/hooks'; export default async () => { render(, document.body); }; function Extension() { const [status, setStatus] = useState('idle'); async function handleUpdatePayment() { setStatus('loading'); try { const activity = await shopify.intents.invoke({ action: 'open', type: 'shopify/SubscriptionContract', value: 'gid://shopify/SubscriptionContract/123', data: {field: 'paymentMethod'}, }); const response = await activity.complete; if (response.code === 'ok') { setStatus('success'); shopify.toast.show( 'Payment method updated', ); } else if (response.code === 'closed') { setStatus('idle'); shopify.toast.show( 'Payment update was cancelled', ); } else { setStatus('error'); shopify.toast.show( 'Something went wrong. Please try again.', {isError: true}, ); } } catch (error) { setStatus('error'); shopify.toast.show( 'Something went wrong. Please try again.', {isError: true}, ); } } return ( {status === 'loading' ? 'Opening...' : 'Update payment method'} {status === 'success' && ( Payment method updated successfully. )} ); } ``` *** ## Best practices * **Prefer object syntax for dynamic intents**: When building the intent parameters programmatically from variables, use the structured object format. It's easier to read and less error-prone than string interpolation. * **Use string syntax for static intents**: When the action, type, and value are known at write time, the compact string format keeps your code concise. * **Always await the activity handle**: Call `await activity.complete` to detect when the workflow finishes. This lets you refresh data or update UI in response to the customer's action. * **Check the response code before acting on results**: Verify that `response.code` is `'ok'` before using `response.data`. The workflow may be cancelled or fail, and your extension should handle those cases gracefully. *** ## Limitations * Intent workflows pause your extension until completion. You can't run other operations while an intent is open. * The workflow UI can't be customized. Field order, labels, and validation messages are controlled by Shopify and can't be modified. ***