~/payments-service/api-tests
Your API tests belong in your repo.
Courion is a desktop API client that stores every request, environment and test as a YAML file next to the service it tests. You review them in pull requests, run them in CI, and your coding agent can write them for you.
macOS builds aren't ready yet.

collections/orders-api/create-order.req.yaml
One small file per request
Most API clients keep a collection in one big file, so two people editing it means a merge conflict. Courion writes one file per request, named after it. A diff says which request changed, and two people editing different requests never touch the same file.
- Bodies and scripts are stored as YAML block text, so a one-line change is a one-line diff.
- Values your scripts set, like a fresh token, stay on your machine instead of turning into a commit.
- Secrets go to the OS keychain, or stay as a 1Password, HashiCorp Vault or Azure Key Vault reference the whole team shares.
1id: 6e0c3f0e-8d52-4c56-9a51-1d7f0d7a5c112name: Create order3method: POST4url: '{{baseUrl}}/v1/orders'5body:6 mode: json7 text: |-8 {9 "customerId": "{{customerId}}"10 }11scripts:12 postResponse: |13 trax.test("order created", () => {14 trax.expect(trax.response.status).toBe(201);15 });git diff main...feature/refunds
Git, without leaving the app
Commit, pull, push, branch and merge from the source control view. Changes are described by what they mean, like a header that changed or a test that was added, next to the raw diff.
- A field-level three-way merge for requests and environments, with a conflict editor for when two people change the same header.
- Open, review and merge GitHub and GitLab pull requests, with review comments pinned to a request's headers or scripts.
- A background fetch keeps every workspace current and fast-forwards when it's safe, so teammates' changes show up on their own.

.mcp.json
Your coding agent writes the tests
Courion comes with an MCP server. After an agent builds or changes an endpoint, it can add the request, attach tests, run them against your local service and read the failures, until everything passes. Its work shows up in the app right away, as files you review like any other change.
- You decide what agents may do: edit requests, run them, read responses, edit environments or see secret values.
- Agents never send anything to an environment you marked protected.
- Works with Claude Code, Cursor, VS Code and other MCP clients.
$ claude mcp add courion -- courion-mcp --workspace ./api-tests1{2 "mcpServers": {3 "courion": {4 "command": "courion-mcp",5 "args": ["--workspace", "./api-tests"]6 }7 }8}.github/workflows/api.yml
The same tests in CI
The trax CLI runs your collections with the same runner, scripts and auth as the app, and writes JUnit, JSON and Markdown reports.
- Secrets come from the pipeline (
--secret apiKey=API_KEY) and are masked in every line of output. - Run once per row of a CSV or JSON file with
--data. - It exits with 1 when a test fails and 2 when it can't run at all, so a typo in an environment name fails the build.
1- name: API tests2 env:3 API_KEY: ${{ secrets.API_KEY }}4 run: |5 ./trax run api-tests -e CI \6 --secret apiKey=API_KEY \7 --junit trax-report.xml \8 --markdown "$GITHUB_STEP_SUMMARY"$ trax run api-tests -e CIOrders API ✓ POST Create order 201 · 171 ms · 2 tests ✓ GET Get order 200 · 112 ms · 1 test ✗ DELETE Cancel order 500 · 34 ms · 1 of 1 test failed DELETE http://localhost:8080/v1/orders/ord_494 ✗ status is 204: Expected: 500 to be 204 ✗ 1 of 3 requests failed · 1 of 4 tests failedcollections/orders-api/collection.yaml
Checked against your OpenAPI spec
Give a collection your OpenAPI document and every response is checked against it: the path, method, status, content type, required headers and the body's schema. When the API drifts from its spec, a test fails.
- Point a folder at another spec, or let one request opt out.
- Importing a spec can set this up for you and add a status test to every request.
- Failures read like test failures, in the app, for agents and in CI reports.
1id: 0c9a6a1e-58b5-4c1f-9d64-0b8e0a1f3c2d2name: Orders API3contract:4 openapi: ../openapi.yaml ✗ GET Get order 200 · 98 ms · 1 of 2 tests failed GET http://localhost:8080/v1/orders/ord_494 ✗ contract: GET /v1/orders/{id}: "total" is a required propertyAnd the rest of a daily driver
Import what you have
Postman collections and environments, Insomnia, Bruno, OpenAPI 3 and Swagger 2, HAR files and cURL commands. Postman's pm.* scripts keep working.
Scripts and tests
Pre-request and post-response JavaScript with Jest- and Chai-style expect, at request, folder and collection level.
Auth that real APIs use
OAuth 2.0 (authorization code with PKCE, client credentials, device code), AWS Signature v4, Digest, NTLM, API keys and client certificates.
Data-driven runs
Run a collection once per row of a CSV or JSON file, with the row's values as variables, in the app or from the CLI.
Environments
Shared values in git, your own values on your machine, and protected environments that ask before anything is sent.
Everyday tools
Variable autocomplete, code export (cURL, fetch, axios, Python, Go, Rust), JSONPath and JMESPath filters and a cookie jar.
Download
These are early releases, so expect rough edges, and please report what you find. The installers include the MCP server; the CLI and the MCP server are also on the release page as standalone binaries.
Windows
.msi or .exe installer
Get it for WindowsLinux
.deb, .rpm or AppImage
Get it for LinuxmacOS
Needs signing and notarisation first.
Not yet