Create a customer-facing purchase option portal
This tutorial describes how to create an automated, secure purchase option portal where customers can manage their purchase option information without interacting with merchants. Customers can use an email link or button to access the portal.
Anchor to What you'll learnWhat you'll learn
In this tutorial, you'll learn how to do the following tasks:
- Expose a link or button to send an email
- Authenticate and access the customer-facing portal
- Make requests to the GraphQL Admin API to implement relevant views and forms on your app
- Update a customer's payment method
Anchor to RequirementsRequirements
- Most subscriptions, pre-order and try before you buy apps need to request API access through the Partner Dashboard. We give API access to apps that are designed according to our [principles for subscriptions, pre-order and TBYB apps] (/docs/apps/selling-strategies/purchase-options#shopifys-principles).
- Public apps that use subscriptions, pre-order or TBYB need to meet specific requirements to be published on the Shopify App Store.
- Custom apps created in the Shopify admin can't use subscriptions, pre-order or TBYB because these apps can't use extensions or request access to protected scopes. If you're building a solution for a single store, then build your custom app in the Partner Dashboard.
-
Create a subscription or deferred purchase option app.
-
Set up an app proxy with the following app proxy configuration:
- Subpath prefix: apps
- Subpath: my-purchase-option-app
- Proxy URL:
https://my-purchase-option-app.com/app_proxy
Anchor to Access scopesAccess scopes
Your app requires the following access scopes:
Anchor to SubscriptionsSubscriptions
write_products
read_customer_payment_methods
read_own_subscription_contracts
write_own_subscription_contracts
Anchor to Deferred purchase optionsDeferred purchase options
write_products
read_all_orders
read_customer_payment_methods
read_purchase_options
write_purchase_options
read_payment_mandate
write_payment_mandate
Provide a link or button that triggers an email to be sent to a customer. You should place a link or button in an area that's accessible to the customer.
You can provide a link or button in one of the following areas:
-
On the customer account page on the storefront
-
On the Order status page, by customizing the Order status page to expose a link or button
-
In an email, sent directly to the customer after the app receives an order creation webhook or a subscription contract creation webhook. The email should contain a secure login link for the customer. For example:
https://example.com/apps/my-purchase-option-app/customer_area?customer_id={customer_id}&shop_id={shop_id}&authentication_token={authentication_token}
You shouldn't render the login link on the shop's storefront because untrusted JavaScript in themes and apps can read and steal information.
Anchor to Step 2: Authenticate and access the customer-facing portalStep 2: Authenticate and access the customer-facing portal
After you've exposed an action to send an email, the customer can use an email link to access the secure purchase option portal. Use an authentication scheme of your choice.
- The login link should be revocable. A fixed URL isn't safe to use because emails can be forwarded.
- Just verifying the authenticity of the URL isn't a secure method. Ideally, a tuple that includes the shop, customer, and token should be stored in the database.
- The token should be deleted whenever convenient. For example, you can expire the token after X minutes or when the customer signs off. In the case of a sign off, the customer can start the process again with another email that contains a new login URL. Learn about considerations for customer-facing portals.
Anchor to Step 3: Make requests to the GraphQL Admin APIStep 3: Make requests to the Graph QL Admin API
After clicking the link, the customer is redirected to an endpoint predetermined by the URL.
For example, if the following URL is provided:
Then Shopify makes a request to the following endpoint:
The app can then implement the relevant views and forms. For example, the app might do the following implementation tasks:
- Updating billing and shipping addresses
- Pausing, unpausing, skipping, and canceling subscriptions
- Canceling and modifying pre-orders
All endpoints are forwarded from the app proxy into your app, as long as the links and form actions start with https://example.com/apps/my-purchase-option-app/
.
When your app receives the request, you can make further requests to the GraphQL Admin API. For example, you can use the sellingPlanCreate
mutation and the subscriptionContractCreate
mutation.
Anchor to Step 4: Update a customer's payment methodStep 4: Update a customer's payment method
For security reasons, customer payment methods, such as credit cards, can't be updated using the API. Customers need to authenticate their payment method where applicable or request a second email that redirects them to a secure flow where their payment method can be safely updated.
After a customer has updated their payment method, the information is available to the app using the same customer payment method ID.
The following request returns a secure URL to send to the customer to update their payment method:
Request: POST /admin/api/2025-07.json
JSON response:
If the response is an error message or if the customer needs to update their payment method at a later date, then you can use the customerPaymentMethodSendUpdateEmail mutation to send an email to the email address associated with the specified ID.
Request: POST /admin/api/2025-07.json
JSON response: