Where Should Your OpenAPI Spec Live?
· The Routebase Team

Every corporate lobby has the same wall, with four identical clocks in a row, one per office. It works because each clock is labelled with a different city.
Now imagine the same four clocks, all labelled with the same city, showing four different times. Nobody standing in front of that wall asks which clock is broken. They ask which one is right. There is no way to tell from looking, because all four are running, all four look official, and each one was correct on the day somebody set it.
That is the state of the API contract at most companies, and it is not fixed by deciding where the spec file goes.
The argument everyone has instead
Ask where an OpenAPI spec should live and you get a storage answer. It belongs in the repo, next to the code, in version control, like every other artefact. Or it belongs in a tool, where people who do not have a Git client can reach it.
Teams argue this for an afternoon, pick the repo, and consider the matter settled. Then someone counts, and the spec turns out to live in four places. There is the YAML in the repo and the docs portal that was generated from it in March. There is the Confluence page a solutions engineer maintains by hand, and the PDF a partner was emailed at integration time and has been building against ever since.
All four are real. All four are being read. None of them is labelled with the version it came from. The storage question was answered. The contract still has four values.
What the repo is genuinely good at
It is worth being precise about this, because the case for keeping the spec in Git is strong and mostly correct.
The spec becomes a build artefact. It moves with the branch, so a feature that changes the API changes the contract in the same commit, and the two cannot be merged apart from each other. Review happens where review already happens, in a pull request with the same reviewers, the same threads and the same approval rules the team already agreed on. It does not happen in a second tool with a second set of permissions nobody audits.
CI can gate on it, so it can lint the document, diff it against the previous version, and
fail the build on a breaking change before it reaches anyone. git blame on a
schema line answers "who changed this and why" better than any audit log,
because it lands you in the commit, the pull request and the discussion in one
step.
And there is no lock-in worth the name. It is a text file in a directory. If the tooling around it disappoints you, you keep the file.
Anyone who tells you this is a bad setup is selling something. It is a good setup. It just does not answer the question the four clocks are asking.
The moment a copy is born
Watch where a spec-in-the-repo actually breaks, and it is never at the repo. It is at the first reader who cannot get to it.
A support engineer needs to know whether status can still return pending. A
partner integrating next month wants the current contract. A QA lead is writing
a regression plan, product is scoping the next quarter, and a customer's
developer, who will never have access to your repository under any
circumstances, is building against your API today. Increasingly the reader is
not a person at all but an agent that reads the contract and calls the endpoint
without asking anyone first.
Every one of them gets served the same way. Somebody exports the file, or pastes it into a wiki, or attaches it to an email, or publishes a portal and does not publish it again. That is the moment the copy is born, and from that second on it is a statement about the past that looks exactly like a statement about the present.
The copies are not the failure. Copies are how a contract reaches the people who need it. The failure is that none of them carries the one piece of information that would make it safe to read, namely which version of the source it came from.
The question worth arguing about
Replace "where should the spec live" with three questions that actually have consequences.
Can someone without repository access read the current contract without being sent it? If the honest answer is "they ask us and we export it", you do not have one contract. You have one contract and an unbounded number of snapshots in other people's inboxes, with no way to recall them.
When the spec changes, is there a named step that brings the derived surfaces forward, or does somebody have to remember? A portal, a mock, a test suite and a generated client are all downstream of the same document. "We regenerate when we think of it" is not a process. It is a person, and that person will be on holiday during your next breaking change.
Can you tell, by looking at a copy, which version it came from? This is the cheapest of the three and the one most often skipped. An unstamped copy cannot be triaged. A stamped one can be, in seconds, by someone who was not involved.
Notice that none of these is a hosting question. A disciplined Git-first setup answers all three. The spec in the repo is the source, CI regenerates the portal and the clients on every merge and publishes them, and each artefact carries the commit it was built from. That works. It is a pipeline you build and then maintain, and the maintenance is the part teams underestimate, because it is invisible right up until the day it silently stops running.
The hosted answer moves the same responsibility into a tool, where the source sits somewhere non-developers can reach without asking, and publishing is an act with a record. That works too, and it also has a cost, because it is one more system, with credentials, and a place where the spec can be edited outside your review process if you let it.
Both need discipline. They just need it in different places, and the useful comparison is which kind of discipline your team actually sustains, not which architecture reads better in a blog post.
How we treat it, and what we deliberately do not do
Routebase keeps the spec in a system rather than a file, so the second and third questions have structural answers. But it is worth being exact about what that does and does not mean, because this is the area where API tooling routinely overpromises.
A version is draft, review, published or deprecated. While it is a
draft, it moves. Once it is published, it is frozen on purpose, because a
version that changes underneath a reader is not a version. The whole point
of stamping a copy is defeated if the thing it points at is a moving target.
What we do not claim is that everything downstream stays in sync by itself. It does not. When a published spec moves on, a mock or a test suite pinned to the older version stays where it is, and the honest description of what the product gives you is detection. It compares what the surface was built from against the current contract and shows you the gap, and pulling it forward is a step someone takes. The clocks still drift. You can see which ones.
And the repo stays in the picture rather than being replaced. The spec exports as YAML, JSON, Postman or Insomnia, which is the file you would have had, when you want it. Documentation is genuinely docs-as-code in both directions. The CLI pulls a version down to Markdown files and pushes edits back, and it exits with a conflict code rather than overwriting when a page moved remotely in the meantime. And after a deploy, CI can pin the version an environment is running with a single command. That is how the environment stops being folklore and starts being a fact you can assert in a test.
If you are working out how the pieces fit together, from design and review to mock, test, and publish, we lay out that shape in more detail on our API design page.
The wall of clocks
The reason the lobby wall works is not that the clocks are accurate. Clocks drift, because that is what clocks do. It works because each one is labelled, so a wrong clock is a visibly wrong clock rather than a plausible one.
Your spec does not need to live in any particular place. It needs one location that everybody agrees is the source, and a way for people without repository access to read it without being sent a copy. It also needs a stamp on everything derived from it saying where it came from. Get those three right and the storage argument answers itself, in either direction, which is the honest conclusion.
Get them wrong and it does not matter how good your YAML is. There will be four clocks on the wall, all of them running, and the next person who needs the right time will pick one.