New from the DevTools team: Stresseur, the AI test engineer for APIs →
DevTools
Back to Blog
Abstract illustration of a branching version-control history connecting geometric nodes representing chained API test steps

Keep API Tests in Version Control With Code

Mustafa BayramogluMustafa Bayramoglu

Keeping API tests in version control means storing them as plain-text files in the same Git repository as the application code they test, not exporting them from a GUI tool as a JSON or XML collection. For a tool like DevTools, that test file is a single YAML workflow chaining multi-step requests together, written in plain text so it diffs and reviews like any other source file. Get that part right, and the rest follows: the test changes alongside the API in the same pull request, and runs in CI on every commit instead of sitting in a folder no one revisits.

What it means to keep API tests in version control

Keeping API tests in version control means treating each test the same way you treat the code it exercises: as a plain-text file, committed to the same repository, tracked through the same commit history, and reviewed through the same pull request process. It does not mean saving a backup copy of a test collection somewhere, or exporting a snapshot of a GUI tool's state into a shared folder once a quarter.

The qualifying property is the file format, not the fact that a file exists somewhere. A test file has to be readable and diffable the way source code is: plain text, one logical change per commit, and small enough that a reviewer can see exactly what changed between two versions. Traditional GUI API clients export collections as large, monolithic JSON or XML files that are difficult to track, diff, and merge in Git. Modern tooling favors modular, text-based formats instead.

Once a test lives in this form, version control stops being a place tests are backed up and starts being the same discipline the rest of the codebase already runs on: branches, diffs, pull requests, and a history of who changed what and why.

Why this matters for API tests

Most of what gets published about version control for test automation is written about UI or mobile test suites, not API tests. The top-ranking guide on this exact question frames the topic as general test automation for Maestro's mobile and UI flows: its own framing is that "test automation without version control is a recipe for chaos", and none of its four sections, repositories and artifacts, branching, commits and review, or CI/CD integration, is about API contracts.

That distinction matters because an API test's job is different from a UI test's job. A UI test checks that a flow still works from a human's point of view. An API test checks that a contract still holds: the shape of a request, the shape of a response, the status codes, and the data the two sides agree on. When the API changes and the test suite doesn't change with it in the same commit, the tests don't just get stale. They start asserting a contract the API no longer honors, and nothing in the repository says so until the test runs and fails somewhere downstream, or worse, passes against a mock that no longer matches production.

That is the specific failure mode version control fixes for API tests: not "we lost a test file," but "the test and the endpoint drifted apart, silently, because they were never versioned together." A test suite that lives outside the repository, in a shared workspace or a separate tool's cloud storage, has no mechanism to catch that drift before it ships. Putting the test file in the same repository, under the same history, is what gives the drift somewhere to show up: a diff a reviewer can actually see.

What version-controlled API tests look like in a repo

For DevTools, this isn't a hypothetical. DevTools is an open-source API testing tool that chains multi-step requests into reusable YAML workflows. Each workflow is a single YAML file: plain text, checked into the repository next to the application code it tests, and readable from top to bottom the way any other source file is.

That format is what makes the file diff and review like code. A change to an endpoint that adds a new required field shows up as a small, readable diff in the test file: a line added, a line removed, nothing else disturbed. A reviewer looking at the pull request sees the API change and the test change together, in the same review, instead of trusting that a test exists somewhere and was updated to match.

This is also where DevTools' own workflow model helps: it records real traffic and auto-maps variables between steps, so a multi-step test, such as log in, create a resource, verify it, then delete it, is one YAML file with variables passed from one step's response into the next step's request, instead of several disconnected requests a reviewer has to mentally chain together.

Git workflow: branching, secrets, and review

Storing tests as files in the repository only pays off if the team applies the same Git discipline to them that it applies to application code. Three practices carry most of that weight.

Branch test changes the same way you branch code changes. Editing a test suite directly on the main branch reintroduces the same risk version control is meant to prevent: an unreviewed change with no record of why it happened. SmartBear's own guide to Git for API test creation frames this as a core version-control practice: a feature branch for the test change, instead of editing tests directly on the main branch.

Keep secrets out of the committed files. A YAML test file is still a text file, and a text file committed to Git is effectively permanent unless the history itself is rewritten. Tokens, passwords, and environment-specific URLs belong in environment variables or a .gitignore-excluded local file, not hardcoded into the test.

Review the test change in the same pull request as the API change it covers. Postman's own engineering blog makes the same case: reviewing API test structural changes alongside the backend changes they cover, in the same pull request. That is the practice that actually closes the drift problem from the previous section: a reviewer approving an endpoint change sees the corresponding test change in the same diff.

None of this requires special tooling beyond what a team already runs for its application code. The test files use the same branches, the same review tooling, and the same secret-handling conventions, because they are the same kind of file, not a separate artifact that needs its own process.

Making version control mean something: gating CI on every pull request

A test file committed to Git is a record. It is not a safeguard until something actually runs it. The second half of version-controlled API tests is wiring that file into CI so it executes automatically on every pull request, without waiting for someone to remember to run it locally.

DevTools runs these YAML-defined, multi-step tests in CI, with parallel execution and JUnit reports. That combination matters for two practical reasons. Parallel execution keeps a growing suite from turning into a slow gate that teams start skipping or disabling under deadline pressure. JUnit output is a format most CI systems already know how to parse into a pass or fail summary on the pull request, so a failing API test shows up next to a failing unit test, in the same check list, instead of in a separate dashboard nobody checks before merging.

Put together with the branching and review practices from the previous section, this is the full loop: a test change lives in the same commit history and the same pull request as the API change it covers, and it runs automatically the moment that pull request opens. Version control without that last step is still just a filing system, no matter how disciplined the commit history looks.

Why a GUI client works against this

The mechanics behind the format label are what make a GUI client's export step costly. An exported collection is typically one large file holding every request in the workspace, and large, monolithic files like that are difficult to track, diff, and merge in Git. A format built to live in Git from the start avoids that failure by keeping each test as its own small, plain-text file, so a change to one test stays a small, isolated diff instead of a change to one giant file.

Frequently asked questions

Do API tests need their own repo, separate from the application code?

No, the accepted practice is the opposite. Store the API test suite in the same repository as the backend application code it tests, so a pull request that changes an endpoint updates the corresponding test file in the same commit.

What happens to secrets and tokens when API tests are committed to Git?

They should not be committed at all. Keep tokens, passwords, and environment-specific URLs in environment variables or a .gitignore-excluded file, and inject them at run time instead of hardcoding them into the test file.

Can API tests reviewed in a pull request block a merge if they fail?

That depends on how the CI job is configured, but it is the point of running version-controlled tests in CI at all: a test that only lives in the repository without running in the pipeline cannot stop a bad change from merging.

Version-controlled API tests are plain-text files that live in the same repository as the code they test, get reviewed in the same pull requests as the changes they cover, and run in CI on every one of those pull requests. That is the whole discipline: co-location, a diffable format, ordinary Git workflow, and a CI job that actually executes the file instead of leaving it to sit. None of it depends on exotic tooling. It depends on treating a test file the way the rest of the codebase is already treated, as source, not as an export.