How to Version-Control API Collections with Git
Your API requests and their tests describe how your API is supposed to behave. That makes them documentation and a regression suite — and both belong in version control, next to the code they describe. Teams that keep collections in a cloud workspace lose three things Git gives for free: history, review, and the guarantee that the tests for version X of the API travel with version X of the code.
Why files beat cloud workspaces
- Reviewable changes. "Added the
refundsendpoint and its error cases" becomes a pull request a teammate can read line by line — instead of an unnoticed edit in a shared workspace. - History and blame. When a test starts failing,
git logtells you whether the request changed, the assertion changed, or neither — so the API did. - Branches match reality. The feature branch carries the new endpoint's requests; main doesn't see them until merge. Cloud workspaces have one shared "now".
- No vendor lock-in. Plain files outlive any tool. If the format is readable JSON, anything can parse it later.
A layout that scales
my-service/
├── src/ # the API's code
└── api-collection/ # the collection — same repo, same PRs
├── auth/
│ ├── login.rr.json
│ └── refresh-token.rr.json
├── orders/
│ ├── create-order.rr.json
│ └── order-validation.csv # data-driven cases
├── security/ # the checks from the security checklist
└── environments/
├── local.json
└── staging.json
Folders mirror the API's resources; a security/ folder holds the security regression checks; data files sit next to the request they feed. In RestRuno this structure is the collection — each request is one *.rr.json file, so the tree above is literally what you commit.
The golden rule: secrets never touch the repo
Request files should reference credentials, not contain them:
// in the request (committed)
"auth": { "type": "bearer", "token": "{{apiToken}}" }
// in an environment (committed): local.json
{ "baseUrl": "http://localhost:3000", "apiToken": "dev-token-anyone-can-know" }
// real secrets: in each developer's own environment file, gitignored
- Commit environment files that hold structure and harmless defaults (local URLs, test accounts).
- Gitignore the ones with real credentials (e.g.
environments/*.local.json), and document in the README which variables a newcomer must fill in. - If a secret ever lands in history, rotate it — deleting the commit is not enough.
Make diffs actually readable
- One request per file. A 4 000-line exported mega-JSON produces useless diffs; per-request files produce three-line diffs.
- Stable formatting. The tool should write keys in a stable order so a re-save doesn't produce a phantom diff.
- Meaningful names.
create-order-missing-currency.rr.jsonreviews itself.
Migrating from Postman
Export your Postman collection (v2.x) and import it into a folder-based tool — RestRuno imports Postman and Bruno collections including folders, auth, scripts and environments, and writes them out as individual files ready for the first commit. From then on, collection changes ride the same pull requests as code changes. (Comparing the two approaches? See RestRuno vs Postman.)
Collections as files, from day one
RestRuno stores every request as a readable .rr.json file in a folder you choose. Commit it, diff it, review it in pull requests — free for Windows, macOS and Linux.