Extension to create draft order on button click

Topic summary

A developer is building a checkout extension to allow certain customers to convert their cart into a draft order (quote request) via a button click. The button renders successfully and can handle regular queries, but mutations are failing.

Key Technical Issues:

  • Cannot trigger mutations from the button’s onPress handler
  • Receiving errors: “Invalid hook call” and “Fetches to the iframe’s origin are not allowed”
  • Uncertain whether mutations are even supported in checkout extensions

Current Approach:

  • Using purchase.checkout.actions.render-before extension point
  • Attempting to call draftOrderCreate mutation via fetch to shopify://customer-account/api/2025-07/graphql.json
  • Code includes malformed GraphQL query syntax in the example

Status: The discussion remains open with no responses yet. The developer is seeking guidance, examples, or confirmation on whether this approach is viable for checkout UI extensions.

Summarized with AI on October 29. AI used: claude-sonnet-4-5-20250929.

We have some customers set up to only submit draft orders which we treat as quote requests. One tier of customers, however, is allowed to submit actual orders, but I want them to still have the option to submit it as a draft “quote”.
Ideally, I would make an extension that adds a button to the checkout page which, when clicked, would query the contents of the shopping cart and then send a mutation that creates a draft order for the customer. I can get the button to show up, I can get API response data if it’s a regular query, but I cannot for the life of me figure out how to get the button’s onPress to trigger a function to send the mutation. Is it even possible to do a mutation via an extension? I can’t tell if I’m close to a solution or on a different continent because I can’t find examples to compare to.

Any guidance, pointing in the right direction, or examples to adapt from would be hugely appreciated!

Some examples of errors I get:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
Error: Fetches to the iframe’s origin are not allowed.

Below is one example of the many attempts I’ve tried within my Checkout.jsx file (I’m not even close to setting up the part where it queries the shopping cart, I’m just trying to make a draft order):

import {
  Button,
  reactExtension,
} from "@shopify/ui-extensions-react/checkout";

async function draftOrderCreate() {
  const orderQuery = {
    query: 'mutation draftOrderCreate($input: DraftOrderInput!) { draftOrderCreate(input: $input) { draftOrder { id } } }',
 "variables": {
    "input": {
      "note": "Test draft order",
      "email": "test.user@shopify.com",
      "shippingAddress": {
        "address1": "123 Main St",
        "city": "Waterloo",
        "province": "Ontario",
        "country": "Canada",
        "zip": "A1A 1A1"
      },
      "billingAddress": {
        "address1": "456 Main St",
        "city": "Toronto",
        "province": "Ontario",
        "country": "Canada",
        "zip": "Z9Z 9Z9"
      },
      "appliedDiscount": {
        "description": "damaged",
        "value": 5,
        "amount": 5,
        "valueType": "FIXED_AMOUNT",
        "title": "Custom"
      },
      "lineItems": [
        {
          "title": "Custom product",
          "originalUnitPrice": 14.99,
          "quantity": 5,
        }
      ]
      },
    },
  }
  const result = await fetch(
      "shopify://customer-account/api/2025-07/graphql.json",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(orderQuery),
      }
    );
    const { data } = await result.json()
  }


  export default reactExtension(
    "purchase.checkout.actions.render-before",
    () => {
      return <Button
      onPress={
        () => {
          draftOrderCreate();
        }
      }
    >
        Submit as quote
          </Button>
    }
  )

Hi @SP_Young

Yes, this is a very common workflow, especially for stores that take custom orders or B2B sales. You cannot do this with just an extension; you need an app backend to communicate with the Admin API.

When the customer clicks your button, it needs to send the product information to your app’s backend. Your backend must then use the GraphQL Admin API (with the write_draft_orders scope) to run the draftOrderCreate mutation. This will create the draft order in your admin.

For a no-code solution, the easiest way is to use an app from the Shopify App Store. Search for “Request a Quote” or “Add to Quote” apps. These are designed to do exactly what you described: they add a button to your product page, and when a customer submits their “quote,” the app automatically generates a draft order for you to review.

Hope this helps!

1 Like