The statement of work says “ERP integration, six weeks”. It does not say who owns the order sync when your ERP renames a field in month four. On the Container One build, four price faults took a median of six days to trace to a cause, fifteen days at worst, between April and June 2026. None of that tracing sat in anyone’s scope.
That gap is where a fixed price breaks. Not on the headline features. On the small question of who is on the hook when a system nobody named changes shape.
A software development contract scope holds when it names four things for every system the build touches: who owns each side, what “done” means as a test somebody can run, who pays for rework after the agreed number of passes, and what happens to your data and code on the last day. Dates and totals are the easy part.
This is for the operator who signs, not the developer who estimates
You are about to sign for a build or a migration. After launch you are the one who answers when an order does not reach the warehouse. You are reading the scope to find out what you have actually bought.
This guide is for you if you sign the statement of work and stay accountable for the store afterwards. It is not for you if you are the agency writing the estimate, or if you are buying a theme install with no systems behind it. A clause that names an owner only helps when somebody on your side can be named too.
A statement of work is a scope document, not a safety net
A statement of work, usually shortened to SOW, is the document that lists what gets built, by when, and on what conditions. Scope is the part that says which systems are in and which are out.
The moment either side says “let’s check the SOW”, the project has stopped being a build. It has become a negotiation about what “user authentication module” was supposed to mean. Both copies of the document are months old. Neither anticipated the thing you are arguing about.
That is not an argument for skipping the contract. It is an argument for writing the scope so the argument never has to happen. Our own engineering engagements are scoped one piece at a time for exactly this reason: the Container One work ran as a systems audit followed by scoped builds agreed individually, not as a retainer.
| Clause | The question it settles | The figure behind it |
|---|---|---|
| System ownership | Who traces a fault, on each side | 6 days median and 15 at worst to confirm the cause of 4 price faults, April to June 2026 |
| Acceptance | What counts as done for one integration | 41 of 41 products priced the same as the old system before any traffic moved, 2026 |
| Rework | Who pays for the third pass | 3 faults fixed in the old application while its replacement was built, merged 2 April to 5 June 2026 |
| Platform change | Who absorbs a vendor deadline | Shopify ships a new API version every 3 months and supports each one for at least 12 |
Name an owner on both sides for every system the build touches
List every system an order passes through: the store, the payment gateway, the ERP, the warehouse or 3PL, the email platform, the accounting ledger. A 3PL is a third-party warehouse that picks and ships your orders on your behalf.
Against each one, the scope names two people. One on the build team. One on yours. Not a company, not a department, a role that a person holds today.
This matters most when a fault has no obvious home. At Container One the price sync, the job that copies prices into the store, reported success while dropping every record it was given. Nothing failed loudly. Somebody had to go looking, and the scope had not said who.
Ask one question of every row: when this breaks at 9am on a Tuesday, whose phone rings? If the answer is “we would raise a ticket”, the row is unowned.
Done is a test you can run, not a demo you watch
Acceptance criteria are the conditions that let you say an integration is finished. Written well, they are testable by somebody who was not in the room.
“Orders sync to NetSuite” is not testable. “100 orders placed in the last 24 hours appear in NetSuite with matching line items, tax and shipping, and a failed write raises an alert within 5 minutes” is.
The Container One rule: the new pricing system had to return the same price as the old one, product by product, before a single customer request reached it. Not a better price. The same price. That gate was 41 of 41 products, checked one at a time, and it was written down before the work started.
Two more acceptance tests belong in almost every scope. First, what happens on failure: a system that silently swallows an error has not passed. Second, what proves it keeps working: at Container One that is 26 test modules with checks running on every change, as of 10 September 2026. The full engagement is written up at Container One.
Also name where “done” is demonstrated. A sandbox, meaning a private copy of the store, is not the live store. Container One’s delivered-price checkout code was built and sandbox tested, and it was still not switched on in the live store as of 10 September 2026. That is a legitimate state, as long as the scope said so in advance.
Rework has a count, and the count belongs in the scope
Rework is the work of doing something again because it did not meet the criteria. Every build has some. Fixed prices survive when the amount is named and fail when it is not.
Put a number in the scope: how many revision passes each deliverable includes, and what happens on the pass after that. Two is common. The number matters less than its existence.
Then separate the two causes, because they are paid for differently. If the build did not meet the written criteria, that is a defect and it is theirs. If you changed the criteria, that is a change and it is yours. Without testable criteria you cannot tell them apart, which is precisely why the third rework pass turns into an email chain.
Our own SOW template keeps assumptions and exclusions as a named section, recommended whenever scope is complex. It is the cheapest page in the document. Every assumption you write down is a change order you do not have to argue about later.
The platform will change under a fixed price, so name who absorbs it
This is the clause almost nobody writes, and it is the one that breaks six-month builds. Shopify moves whether or not your project is finished.
| What changes | What Shopify states | When |
|---|---|---|
| API versions | A new version every 3 months, each stable version supported for at least 12 months, with at least 9 months of overlap | Ongoing, quarterly |
| A retired version | Requests fall forward to the oldest accessible stable version | On retirement |
| Checkout pages | Deadline for stores on a non-Plus plan to upgrade the Thank you and Order status pages | 26 August 2026 |
| Additional scripts | The additional scripts box in Checkout settings became view only | 28 August 2025 |
Those dates come from Shopify’s API versioning policy and its checkout upgrade guidance. Read them before you sign, not during month five.
The scope should then say three things. Which API version the integration targets. Who monitors Shopify’s deprecation notices during the build. And who pays when a published platform deadline lands inside your delivery window. Silence on that last point means you pay, because the work is real and it is not in the estimate.
The data and access clause decides what you hold on the last day
Most scopes describe the build. Few describe the ending. Write the ending while everyone still likes each other.
| What you take back | What the scope states | The clock that already exists |
|---|---|---|
| Source code | Named repositories transferred to your organisation, with full commit history | No platform default, so the date is yours to set |
| Store and customer data | Who exports what, in which format, before access ends | `shop/redact` reaches an uninstalled app 48 hours after uninstall |
| Customer deletion requests | Who answers one after the build team has gone | Shopify requires 3 privacy webhooks of every public app |
| Credentials | Which accounts are revoked, on which day, by whom | An app has 30 days to complete a redaction request |
Those webhook facts come from Shopify’s app privacy compliance documentation. They matter because a custom app built for you carries the same obligations, and after handover they are yours.
One honest note. We hold no Container One specific code-assignment document. Client code ownership is our standing policy, and on that engagement it was never written into a paper of its own. That is the gap this clause exists to close, and we found it in our own record rather than a client’s.
What breaks, and who owns it
Scope clauses fail in predictable ways. Name the owner of each failure now.
Testable criteria written by the build team alone tend to test what was built. You own reviewing them before signature. If you cannot understand a criterion well enough to check it yourself, it is not finished.
Ownership rows go stale when people change roles. You own refreshing that list at each milestone, because the build team cannot see your org chart.
A rework count with no defect definition becomes a way to bill revisions. The build team owns writing the defect definition. You own refusing a count without one.
And a scope this specific takes longer to agree. That is the trade. The five questions worth asking before any of this begins are in the uncomfortable questions to ask a technical partner guide. Transparency during the build still matters, but it is not a substitute for a scope that names owners. It is what makes the named owners reachable.
Questions operators ask about scope
What should a software development contract scope actually list?
Every system the build touches, with an owner named on both sides, a testable acceptance condition per integration, a rework count with a defect definition, and a data and access handover. Dates and totals are the easy part and they are rarely what disputes are about.
How do I write acceptance criteria I can check myself?
Write the test, not the outcome. Name a volume, a time window and a failure behaviour. “41 of 41 products return the same price as the old system before any traffic moves” is checkable by anyone. “Pricing works correctly” is not.
Who pays when Shopify changes something mid-build?
Whoever the scope says. Shopify publishes a new API version every three months and supports each stable version for at least twelve months, so the changes are scheduled rather than surprising. If your contract is silent, expect the cost to land on you.
Is a fixed price safer than paying for time?
A fixed price is only as firm as the criteria underneath it. With testable criteria and a rework count, it holds. Without them, the fixed price becomes a floor and every disagreement becomes a change order.
What do I ask for on the last day of an engagement?
Repository transfer with full history, an export of store and customer data, a written list of credentials to revoke and their revocation date, and a named person who answers a customer deletion request afterwards. Shopify gives an app thirty days to complete such a request, and that obligation becomes yours.
See which handoffs in your store have no owner today
You can apply all of this to your next contract. You can also check what the last one left you with.



