Skip to content

For Shopify agencies

Build vs buy: what a custom Shopify RFQ app has to run in 2026

By Jahangir Alam · October 7, 2026 · 14 min read

Last verified
Shopify API
2026-10
Audience
Shopify agencies and technical merchants deciding whether to build a custom quote or RFQ system
Scope
Custom apps at API 2026-10 (Dev Dashboard, custom distribution, Plus gates for Functions, Flow and checkout extensions, tokens, protected data, hosting), the twenty components of an RFQ system on Shopify, one quote app's dated maintenance log, cost drivers without figures, and a build, buy or hybrid worksheet

Build a custom RFQ app on Shopify when the quoting workflow itself is the product - a procurement rule, a contract-driven negotiation, a document no app produces - and someone will fund the app's upkeep on Shopify's calendar for as long as the store trades. Buy when the workflow is the standard request, price, negotiate, approve, convert loop. Build only the difference when one component is unique and the rest is standard. The hard part of the decision is rarely the first build; it is the second half of that sentence, because Shopify changes on a quarterly schedule whether or not anyone is watching.

Native B2B, quote app, custom build or CPQ is the four-way decision. This page is the deep version of its custom-build branch: what a custom app is in 2026 and where Shopify puts a Plus gate, the twenty components an RFQ system on Shopify actually consists of, a dated maintenance log from one live quote app - ours - and a worksheet to price the obligations instead of the launch.

Everything about Shopify below was checked against Shopify's own pages on 7 October 2026 at API version 2026-10; sources are at the end. The maintenance log is a QuotWay observation: one app's record over a few months, not a rate.

What a custom app is in 2026

A custom app is an app built "exclusively for your Shopify store". Since the admin route closed, it is created and managed in the Dev Dashboard and built with Shopify CLI, then installed through a link you generate. The rules that shape a build decision:

  • Distribution. Custom distribution installs on one store, or on the stores of one Shopify Plus organization. Public distribution means an App Store listing and review. Shopify's own description of who uses which: "Most apps built for a specific merchant or an agency client use custom distribution."
  • The choice is permanent. Shopify: the distribution method can't be changed after it is selected. An agency that may later sell the same app to other merchants has to decide that now.
  • No review, no Billing API. Custom distribution skips app review, and the app can't charge through Shopify's Billing API - the agency invoices outside Shopify.
  • No admin-created apps. Since 1 January 2026, custom apps can no longer be created in the Shopify admin. Existing admin-created apps keep working, but they could never use App Bridge or app extensions, so they are not a starting point for an RFQ system.
  • Several clients, one codebase. Custom distribution stops at one Plus organisation, so an agency serving unrelated stores deploys one app record per client store from the same code - Shopify's deployment guide allows several app records on one codebase - or goes public.

What a custom app can use, and where Plus decides

Surface In a custom app Shopify's gate
Admin GraphQL API and webhooks Yes Access scopes; some scopes need Shopify's approval (read_users, for staff identity, needs Plus or Advanced)
Embedded admin UI (App Bridge) Yes -
Theme app extensions (storefront button, blocks, app embed) Yes Size limits per extension
Customer account UI extensions (the buyer's portal) Yes 64 KB per extension, 128 KB for a full page
Checkout UI extensions on the information, shipping and payment steps Yes Only on Shopify Plus - for every app, not just custom ones
Shopify Functions (validation, cart transform, discounts) Yes Only on Plus stores for custom apps; public apps use them on any plan
Shopify Flow triggers and actions Yes Only on Plus stores for custom apps
Sidekick app extensions Not stated Shopify's Sidekick pages don't say either way
Billing API No Custom distribution can't use it
Built for Shopify Not applicable An App Store programme with install and review prerequisites

Shopify states the extension rule negatively: app extensions are unavailable only to admin-created apps. A CLI-built custom app can use them, within the gates above.

Tokens, data and hosting

Access tokens. An embedded app gets its token by token exchange; a non-embedded app by the authorization code grant; a server-side integration that only touches stores in your own organisation can use the client credentials grant, which issues 24-hour tokens without a merchant approval screen. Expiring offline tokens (one hour, refreshable for 90 days) become mandatory for public apps on 1 January 2027 - and Shopify says "this doesn't apply to custom apps or apps created by merchants", whose tokens stay valid until the app is uninstalled or its client secret is revoked. Opt in to expiring tokens anyway: a permanent credential held by an agency is exactly what a store's security review is told to find.

Scopes. "Any scope that writes a resource also grants read access to it" - and Shopify's granted-scope list then shows only the write scope. That one sentence caused a production bug in our own app (below). read_orders covers the last 60 days; older orders need read_all_orders, which has to be requested.

Customer data. Protected customer data at Level 1 and Level 2 is "always available" to custom apps without review, where public apps need review; Shopify "encourage[s] all apps" to meet the same requirements, and the Help Center adds that "Custom Level 2 PII apps" need the Grow plan or higher. The three compliance webhooks are an App Store requirement, but Shopify sends customers/data_request to any installed app with customer or order access, and the merchant's data-protection law applies regardless - so a custom build implements the handlers too.

Hosting. "Shopify hosts only your extension's code." The backend, its database, its queue and every endpoint Shopify calls - webhook receivers with a five-second timeout, the app proxy behind the storefront form - run on hosting you choose and keep up.

The twenty components of an RFQ system on Shopify

Shopify has no quote object. A draft order is replaced wholesale on update and is deleted after a year without an edit, so it can carry the agreed deal at the end but not the negotiation before it (why a draft order is not a quote). Everything else is yours to build:

# Component Shopify surface it rests on The hard part
1 Request capture: button, form, cart quote Theme app extension; app proxy for signed submissions Eligibility per buyer and company without a slow round trip; theme variety; storefront weight
2 Price visibility Theme app extension; a theme Liquid condition to keep prices out of the HTML A CSS or script hide is visual only (hiding prices)
3 Quote record and immutable versions Your database A sent version never changes; a change is a new version
4 Negotiation and counter-offers Your database and a buyer surface Whose turn it is; a line the buyer didn't pick stays open, not lost
5 Starting price contextualPricing for the company location (with auditTrail from 2026-10) Catalog precedence; never a second price list (the starting price)
6 Totals and money Your code; draftOrderCalculate for Shopify's view Store the agreed figure; never re-sum displayed rows
7 Approvals and audit Your database; staff identity through an approval-gated scope Enforcement on the server, decisions append-only (approval matrix)
8 Documents Your backend One document per version; what a quote must contain
9 Email notifications Your backend and an email provider Deliverability, suppression, safe re-sends
10 Buyer portal Customer account UI extension and a backend you host Authenticating the extension to your backend; guests without accounts (building the portal)
11 Conversion to a draft order draftOrderCalculate, draftOrderCreate with purchasingEntity, price overrides, payment terms No idempotency key on draftOrderCreate, even at 2026-10 (exactly one draft order); drift between quote and conversion (17 failure modes)
12 Webhooks and reconciliation orders/*, draft_orders/*, app/* and compliance topics Duplicates, ordering, the order that arrives before your own write, a sweep for missed deliveries
13 Admin UI Embedded app (App Bridge, Polaris), optional admin blocks Every screen is yours to build and keep in step with Shopify's admin
14 Staff permissions Your own model Who may send, approve and convert (sales-rep quoting)
15 Multi-currency and markets Contextual pricing per country; presentment currency on the draft Locking the rate at quote time
16 Translations Locale files per extension, plus your own strings Every buyer-facing string, in every surface
17 Analytics Your database - Shopify's reports don't see quotes Offered versus accepted value; currency mix
18 Integrations and automation Flow extensions (only on Plus stores in a custom app), your own API and webhooks, Sidekick extensions Each surface has its own versioning (ERP, CRM and PIM patterns)
19 Compliance and data Compliance webhooks, protected customer data Redaction across every table that holds buyer data
20 Hosting and operations Your hosting, database, queue, error tracking Uptime of the endpoints Shopify calls; backups; secrets

For scale, here is one shipped quote app's shape - ours, read from its repository on 7 October 2026: 27 app extensions (one theme app extension with an app embed and four blocks; two customer account UI extensions; one admin block; 19 Flow extensions - ten triggers, three actions, six templates; three Sidekick extensions), 10 webhook topics (the three compliance topics plus seven), and 53 data models. In a custom app on a non-Plus store, all 19 Flow extensions would be unavailable.

What maintaining one actually looks like

This is one app's record, kept by its maintainers. It is not a rate - but every item arrived on Shopify's schedule, not ours.

Eighteen days of Shopify changes. Re-checking our Shopify facts for the 2026-10 release, we logged 17 dated changes on the B2B and app surface between 20 September and 7 October 2026. Among them:

  • Sidekick began invoking intent-only extensions (28 September).
  • A new discount app intent (30 September).
  • API 2026-10 went stable, with 2027-01 as release candidate and 2025-10 out of support from 16 October.
  • priceRule was removed from draft-order discount warnings, and orderUpdate started recalculating tax when the shipping address changes.
  • Market parent and child relationships arrived.
  • The Customer Account API lost lastIncompleteCheckout.
  • Events became generally available, alongside classic webhooks.
  • Buyer-requested order edits arrived.

The same pass corrected nine of our own published claims. The maintainer's understanding drifts too, not only the API; the re-verification records both.

A version upgrade is an audit, not a config edit. Our move from API 2026-04 to 2026-07 changed 40 files: library versions, the API version in all 24 extension configurations, and a regenerated schema with every admin operation validated against it. Shopify's changelog showed no breaking change on our surface. The schema validation still found two operations that had been invalid all along - a draft-order lookup asking for a field that doesn't exist, which made one reconciliation job fail on every row, and a mutation called with the wrong argument shape. For 2026-10, a search of the code for every removed or deprecated field returns nothing, so there is no known break - and the upgrade still touches those 24 configurations and the app's own pins.

The implied scope. On 30 September our payment-terms check required both read_payment_terms and write_payment_terms in the granted scopes. Shopify lists only the write scope when both are granted, because writing implies reading - so stores that had granted the permission were treated as if they hadn't, and converting a quote with payment terms was blocked until a hotfix shipped the same day. The test fixtures had used a scope format Shopify never sends.

Validation errors at conversion. In July, draftOrderCalculate rejected every well-formed company quote with "Cannot send both customer and purchasing_entity" until the two were made mutually exclusive. The next error was "An issue date is required with net payment terms": net terms need a payment schedule, so the convert screen had to ask the merchant for an issue date.

A library advisory. In August, a security advisory against Shopify's app library (app proxy HMAC validation) meant upgrading to the patched major version. Our own proxy check wasn't affected, but the upgrade required a newer Node.js runtime and a code change for a removed property.

The storefront budget. The storefront script is held to 108 KB by a bundle-size check. It is 105,050 bytes today, about three times Shopify's suggested 10 KB compressed, and the budget was raised ten times in four weeks as features shipped in mid-2026 (what that costs a store).

Scopes and permissions. Between May and July 2026, the requested scopes changed repeatedly:

  • A scope that doesn't exist was rejected by deploy validation.
  • The B2B scopes were made required, then reverted to optional, because requiring them blocked installs by staff without permission to view company data.
  • A restricted staff scope was rejected without Shopify's approval.
  • Two unused scopes were removed before App Store submission.

A custom app skips the App Store half of this, not the rest.

The budget follows from the log: one API audit per quarter at minimum, a scope and permission review whenever a feature touches a new resource, and a reconciliation job from day one. Shopify B2B technical debt keeps the dated surfaces in one calendar.

What drives the cost

We publish no cost figures - there is no dataset behind any we could give. The drivers are countable, though, and each is an ongoing obligation rather than a launch task:

  • Surfaces. Every extension type - storefront, customer account, admin, Flow, checkout - has its own limits and its own upgrade path.
  • Plus dependencies. Functions, Flow extensions in a custom app and checkout-step extensions only exist on Plus stores.
  • Stores and organisations. One app record per unrelated store; distribution can't change later.
  • The buyer portal. A customer account extension plus an authenticated backend you host.
  • Compliance and data. Redaction handlers and protected-data safeguards across every table.
  • Integrations. Each external system adds a sync, a reconciliation and a failure mode.
  • The calendar. Four API releases a year, each supported for at least 12 months, then a silent fall-forward to the oldest supported version.
  • Operations. Hosting, monitoring and someone on call for endpoints Shopify expects to answer within seconds.

The build, buy or hybrid worksheet

Copy the table, one row per component from the inventory above, and fill it in with the client:

Component Build / buy / hybrid Owner Shopify surface Ongoing obligation Plus-gated? Who is paged when it breaks
Request capture Theme app extension, app proxy Theme compatibility, script weight No
Conversion to a draft order Admin API Idempotency, drift, quarterly API audit No
Checkout rule (for example a PO-number requirement) Functions Function API versions Yes, in a custom app
Approvals and audit Your database, staff scope Enforcement, scope approval Staff scope: Plus or Advanced
…

Then answer seven questions:

  1. Is the workflow unique, or one component? One component means hybrid.
  2. Who funds the API audit every quarter for the life of the store?
  3. Is the store on Plus, and does the design need Functions, Flow extensions or checkout-step extensions?
  4. How many stores, in how many organisations? Custom distribution covers one Plus organisation, and the choice is permanent.
  5. Must buyers act in their customer account? That is an extension plus a backend you host.
  6. Who owns compliance - the redaction webhooks and protected-data handling?
  7. What is the exit? Who holds the code, the data and the credentials if the agency relationship ends - remembering that a custom app's token doesn't expire on its own.

The hybrid route

Buy an app for the standard workflow and build only the unique part - an ERP sync, a headless intake, a pricing service whose output a person then applies. The condition is that the app exposes the events and endpoints the unique part needs, so check what its API cannot do before scoping.

QuotWay's REST API and signed webhooks, as an example stated exactly: available on the Enterprise plan, including during the 14-day free trial. The API reads quotes with their lines, totals and events, creates quote requests, posts messages, sends a proposal a person already priced, lists documents and reads analytics. It cannot set or change prices, edit lines, accept or decline for the buyer, or convert a quote to a draft order, and webhook payloads carry no buyer personal data. What you can build with the QuotWay API walks through six integrations; the evaluation checklist is the test for any vendor's API. Plans are on the pricing page, and the API itself is described on the API and webhooks page.

FAQ

What is a Shopify custom app?

An app built for one store, or for the stores of one Shopify Plus organisation, created in the Dev Dashboard and installed through a link you generate. It has no App Store listing and no app review. Since 1 January 2026 it can no longer be created in the Shopify admin.

How do I create a custom app now that the admin option is gone?

Create the app in the Dev Dashboard - with Shopify CLI if it has a UI or extensions - choose custom distribution, and generate the install link for the store. Apps created in the admin before 2026 keep working.

What is the difference between a custom app and a public app?

A custom app installs on one store or one Plus organisation, skips review, can't use the Billing API, and can use Functions and Flow extensions only on Plus. A public app installs on any store through the App Store, goes through review, can bill through Shopify and can use Functions on any plan. The choice can't be changed later.

Can a custom app use Shopify Functions?

Yes, but only on a Shopify Plus store, and the same applies to its Flow extensions. Checkout UI extensions on the information, shipping and payment steps are available only on Shopify Plus, for every app.

Do custom apps need app review, or can they be Built for Shopify?

Custom distribution has no app review. Built for Shopify is an App Store programme with install and review prerequisites, so it doesn't apply to a custom app.

How does a custom app get an access token?

An embedded app uses token exchange; a non-embedded app uses the authorization code grant; a server-side integration on your own organisation's stores can use the client credentials grant, which issues 24-hour tokens. Custom apps are exempt from the 2027 expiring-token requirement, but opting in is safer.

Who hosts a custom app?

You do. Shopify hosts only the extensions' code - theme blocks and UI extensions. The backend, its database and every endpoint Shopify calls run on hosting you choose and maintain.

How much does a custom Shopify RFQ app cost?

We publish no figures. The cost is set by the surfaces you build, the Plus dependencies, the number of stores, the buyer portal, compliance, integrations and hosting - and by the API audit every quarter for as long as the store trades.

Can we buy an app and build only the unique part?

Yes, if the app exposes the events and endpoints the unique part needs. Check what its API can't do first: QuotWay's API, for example, is Enterprise-only and can't set prices, edit lines, accept for the buyer or convert.

Sources

Shopify pages, read on 7 October 2026 at API version 2026-10:

Our own record: the 2026-10 re-verification of the Shopify B2B reference, and the QuotWay app's repository history, read on 7 October 2026 - described here without internal names.

Related articles

See how QuotWay handles this on your store.

We’d like to set analytics cookies to understand how the site is used. They’re not required — declining changes nothing about how the site works, and you can change your mind any time on our privacy page.