Every team that builds an HTTP API ends up choosing between a GUI client, a file-based runner, and raw curl. The right answer depends on whether your requests need to live in version control and run in CI, not on which tool has the nicest dark theme.
Postman is still the default. Collections, environments, a scripting sandbox, mock servers and a request history that saves you constantly. The friction is the account: since the removal of the offline scratch pad, meaningful work assumes a cloud workspace. The free tier caps collection runs and shared collaborators, and paid plans start around $14 per user per month billed annually. Collections export as JSON but the schema is verbose and diffs badly — a one-line header change can produce a 40-line diff.
Bruno stores each request as a .bru text file in a folder you commit to your repo. That single decision fixes the review problem: a request change shows up as three readable lines in a pull request. It has environments, an assertion tab and a JavaScript scripting hook, and the desktop app is free and offline by default. What you give up is the ecosystem — no mock servers, thinner OpenAPI import, and fewer people on your team will already know it.
Hurl is a small binary that runs plain-text files built on curl. A test looks like this:
POST https://api.example.com/v1/login
Content-Type: application/json
{"user":"demo","pass":"demo"}
HTTP 200
[Captures]
token: jsonpath "$.access_token"
[Asserts]
jsonpath "$.expires_in" >= 3600
Run it with hurl --test --variable env=staging login.hurl and you get exit code 1 on failure, JUnit XML with --report-junit, and no runtime to install. For smoke-testing a deployment in a GitHub Actions step, this is usually the least code.
For a single request you are debugging, nothing beats curl -sS -D- -o- -X POST -H 'Content-Type: application/json' -d @body.json https://api.example.com/v1/orders. Add -w '\n%{time_total} %{http_code}\n' and you have latency measurement for free. HTTPie gives you the same thing with colourised JSON and saner syntax (http POST api.example.com/v1/orders name=demo), at the cost of a Python dependency. Both are fine to paste into a bug report, which is a real advantage over any GUI.
Testing only the happy path. A useful suite asserts the 401 when the token is missing, the 422 body shape on a bad payload, the Retry-After header on a 429, and that pagination terminates. Those are the responses your client code handles worst, and they are the ones a GUI click-through never exercises.