Skip to content
courionDownload

~/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.

Courion's request editor: a GET request to {{baseUrl}}/v1/orders with query parameters, and the JSON response below it with 1 of 1 tests passing.

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.
create-order.req.yaml
1id: 6e0c3f0e-8d52-4c56-9a51-1d7f0d7a5c11
2name: Create order
3method: POST
4url: '{{baseUrl}}/v1/orders'
5body:
6 mode: json
7 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.
The source control view: a changed environment file shown as 'Variable added', 'Variable updated' and 'Variable removed', next to the branch history.

.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.
terminal
$ claude mcp add courion -- courion-mcp --workspace ./api-tests
.mcp.json
1{
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.
api.yml
1- name: API tests
2 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
$ trax run api-tests -e CI
Orders 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 failed

collections/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.
collection.yaml
1id: 0c9a6a1e-58b5-4c1f-9d64-0b8e0a1f3c2d
2name: Orders API
3contract:
4 openapi: ../openapi.yaml
trax
✗ 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 property

And 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.