DS DevShelfHub Projects · AI tools
Articles / Requestly for Data Science: A Practical API Testing Tool for ML and AI Engineers

AI Engineering

Requestly for Data Science: API Testing for ML and AI Engineers

By DevShelfHub

How to test ML and AI APIs faster with Requestly — collections, file uploads, base64 image decoding, environment variables, and pre/post-response scripts. Walkthrough on a real FastAPI YOLO v26 service.

Requestly for Data Science: API Testing for ML and AI Engineers

Introduction

Data scientists and AI engineers spend a surprising amount of time talking to HTTP endpoints. A FastAPI service wraps a YOLO model. A LangGraph agent calls an OpenAI tool. A retrieval service exposes a vector search route. Every one of those workflows depends on requests behaving the way you expect — correct status codes, correct payload shape, correct headers. curl works, but it stops scaling the moment you’re juggling collections of endpoints, environment variables, file uploads, and pre/post-response assertions.

Requestly is an API testing tool now owned by BrowserStack that ships as a desktop app and a Chrome extension. It’s free, open source, and tuned for the kind of workflows data and ML teams actually run — multipart file uploads to vision APIs, base64 image responses, model-size parameters, and quick environment-variable swaps. This article walks through using Requestly to test a real FastAPI YOLO v26 service that exposes object detection, classification, and segmentation endpoints.

Table of contents

  • What Requestly is
  • Why ML and AI engineers need a real API tester
  • Installing Requestly
  • The example project: a FastAPI YOLO v26 service
  • Creating a collection
  • Testing a GET endpoint
  • Testing a POST endpoint with file upload
  • Decoding base64 image responses
  • Environment variables and placeholders
  • Pre-request and post-response test scripts
  • Collection runner for batch testing
  • Integrating with LLM and ML APIs — OpenAI, Anthropic, Hugging Face
  • Requestly vs Postman, Bruno, Hoppscotch, Apidog
  • Best practices for API testing in ML projects
  • Common mistakes to avoid
  • Conclusion
  • Frequently asked questions

What Requestly is

Requestly is an API client and HTTP debugging tool. The product covers three loosely connected jobs in one application: sending and inspecting API requests, intercepting and modifying network traffic in the browser, and writing assertions against responses. For data and ML workflows the first and third parts matter most — the request builder, the collection runner, and the scripting hooks.

Core capabilities

  • HTTP request builder with GET / POST / PUT / DELETE and full header control
  • Multipart form-data uploads for files and binary payloads
  • Collections with descriptions and reusable variables
  • Environment variables with placeholder substitution
  • Pre-request scripts and post-response assertions
  • Collection runner for batch execution

What sets it apart

  • Free and open source after the BrowserStack acquisition
  • Lightweight desktop app — not an Electron monster
  • Inline HTML preview for endpoints that return rendered pages
  • AI-assisted test-case generation for status and header checks
  • Chrome extension for in-browser request interception

Why ML and AI engineers need a real API tester

Most ML tutorials stop at “train a model and call it from a notebook.” Production is where the API layer starts mattering. The moment you wrap a model in FastAPI, Flask, or a serverless function, you’re back in normal web-engineering land — status codes, content types, retries, payload sizes. A scripting REPL won’t catch the regressions that a proper API tester will.

Model endpoint debugging

Did inference fail because the model is bad, or because the request shape was wrong? A dedicated client makes the difference between a 422 validation error and a real modelling bug obvious in seconds.

Reproducible test fixtures

Collections capture the exact request — URL, headers, body, file — so a teammate can hit your endpoint with the same payload and reproduce the bug without copying a 40-line curl command from Slack.

Pre-release smoke tests

Before pushing a model bump, run the collection against staging. Status 200, content-type matches, response size in range — three asserts that catch most breakage without writing pytest fixtures.

Installing Requestly

Head to requestly.com and click download. You get two options: a desktop app (Windows, macOS, Linux) or a Chrome extension. Pick the desktop app for testing local APIs — the extension is more useful for browser traffic interception.

Quick setup

  1. Download the installer for your OS.
  2. Run the installer — double-click on Windows or drag to Applications on macOS.
  3. Open the app and sign in (optional — needed for sync across machines).
  4. Create your first workspace.

The example project: a FastAPI YOLO v26 service

The walkthrough uses a small FastAPI service that wraps YOLO v26 for three computer vision tasks — object detection, classification, and segmentation. Each endpoint takes a multipart file upload and a string parameter for model size.

The service exposes:

  • GET / — HTML home page
  • GET /health — health check
  • POST /api/v1/detect — object detection
  • POST /api/v1/classify — image classification
  • POST /api/v1/segment — instance segmentation
  • GET /test — HTML test client

Spin up the project with uv:

Bash
# create and activate a virtual env
uv venv
source .venv/bin/activate   # or .venv\Scripts\activate on Windows

# install dependencies
uv pip install -r requirements.txt

# run the FastAPI app on port 8080
uvicorn fastapi_app:app --reload --port 8080

Open http://127.0.0.1:8080/docs to confirm Swagger lists every route. From here, Requestly takes over as the testing surface.

Creating a collection

A collection is a folder of related requests. For an ML service, group endpoints by domain — one collection per model, or one per service. The walkthrough uses a single collection called yolo-test-app.

Steps

  1. Click New → Collection.
  2. Name it yolo-test-app.
  3. Add a description — list every endpoint, its method, and what it returns.
  4. Save.

Tip: paste your OpenAPI spec or your FastAPI router code into an LLM and ask it to draft the collection description. It saves ten minutes of typing and gives teammates real context when they open the collection.

Testing a GET endpoint

Start with the simplest case — the home page. Inside the collection, create a new HTTP request named home.

  • Method: GET
  • URL: http://127.0.0.1:8080/
  • Hit Send.

The response panel shows the raw HTML the FastAPI route returned. Requestly also renders the HTML inline, so you can sanity-check what the browser would see without leaving the app. Repeat the same flow for the test-client route at /test.

Testing a POST endpoint with file upload

Now the interesting part. The classify, segment, and detect endpoints take a multipart payload with two fields — file (the image) and model_size (small, medium, or large).

Configuring the classify request

  1. Create a new HTTP request named classify.
  2. Method: POST.
  3. URL: http://127.0.0.1:8080/api/v1/classify.
  4. Body tab → pick multipart/form-data.
  5. Add key file with type file, attach a dog-and-couch image.
  6. Add key model_size with type text, value medium.
  7. Save and Send.

The first call is slow — the model is loading into memory. After that you should see a JSON response like:

JSON
{
  "success": true,
  "classify": {
    "label": "Siberian husky",
    "confidence": 0.91
  },
  "image_data": "iVBORw0KGgoAAAANSUhEUgAA..."
}

Repeat for /api/v1/segment and /api/v1/detect. Same body shape, different routes. Segmentation returns bounding-box coordinates; detection returns class labels plus boxes.

Decoding base64 image responses

Many vision APIs return an annotated image as a base64 string inside the JSON response. That string is unreadable in the response viewer. Two quick options:

  • Paste the string into any online base64-to-image decoder (search base64 decode image) to view the annotated result.
  • Decode it locally with a one-liner:
Python
import base64

with open("annotated.png", "wb") as f:
    f.write(base64.b64decode(response_json["image_data"]))

For detection on a dog-and-couch image, you should see two boxes — one labelled dog 0.83 and one labelled couch.

Environment variables and placeholders

Hard-coding http://127.0.0.1:8080 across ten requests is the kind of mistake you only make once. Requestly supports collection-scoped variables you can reference with a placeholder.

Setting up variables

  1. Open the collection → Variables tab.
  2. Add a variable: name url, type string, initial value http://127.0.0.1:8080.
  3. Add another: name home, value http://127.0.0.1:8080/.
  4. Save.

Now reference them inside any request URL with double-brace placeholders:

Text
{{url}}/api/v1/classify
{{url}}/api/v1/segment
{{url}}/api/v1/detect

Switching from local to staging is one variable edit. For production you’d add a prod_url variable and either swap the placeholder or move to a separate environment.

Mark API keys and tokens as secret when you add them. Requestly will mask the value in the UI and avoid leaking it in shared exports.

Pre-request and post-response test scripts

Each request has a pre-request hook (runs before the call) and a post-response hook (runs after). Use post-response to assert on the response — status codes, headers, JSON shape.

A minimal status and content-type check for the home route:

Text
// post-response script for GET /

rq.test("status is 200", function () {
  rq.expect(rq.response.code).to.equal(200);
});

rq.test("content-type is text/html", function () {
  rq.expect(rq.response.headers["content-type"]).to.include("text/html");
});

The app has an AI-generate option — click it and Requestly drafts assertions based on the request. For routine status and header checks it’s a fair starting point, though you’ll still hand-write the schema-sensitive ones.

A more interesting assertion for the classify endpoint:

Text
// post-response script for POST /api/v1/classify

const body = rq.response.json();

rq.test("success flag is true", function () {
  rq.expect(body.success).to.equal(true);
});

rq.test("classify object has a label", function () {
  rq.expect(body.classify).to.have.property("label");
});

rq.test("confidence is between 0 and 1", function () {
  rq.expect(body.classify.confidence).to.be.within(0, 1);
});

Pre-request hooks are useful for things like generating a timestamp or a request ID:

Text
// pre-request script

const timestamp = Date.now();
const requestId = crypto.randomUUID();

rq.variables.set("timestamp", timestamp);
rq.variables.set("request_id", requestId);

console.log("timestamp:", timestamp);
console.log("request_id:", requestId);

Collection runner for batch testing

Running one request at a time is fine while you’re building. For regression checks you want every endpoint hit in order, with all assertions running, in one click.

Using the runner

  1. Open the collection and click Runner.
  2. Tick the requests you want to include — or run all of them.
  3. Hit Run.
  4. Watch the green and red dots next to each assertion.

Two green ticks per route means status and content-type passed. A red dot is a regression to investigate. The runner becomes a smoke test you can fire before any model deployment — same idea as pytest, but at the HTTP boundary instead of inside the codebase.

Integrating with LLM and ML APIs

The same patterns apply to third-party model APIs. You define a collection per provider, store the API key as a secret variable, and reuse it across every request.

OpenAI Chat Completions

YAML
POST https://api.openai.com/v1/chat/completions

Headers:
  Authorization: Bearer 
  Content-Type: application/json

Body (raw JSON):
{
  "model": "gpt-4o-mini",
  "messages": [
    {"role": "user", "content": "Hello"}
  ]
}

Anthropic Messages

YAML
POST https://api.anthropic.com/v1/messages

Headers:
  x-api-key: 
  anthropic-version: 2023-06-01
  Content-Type: application/json

Body (raw JSON):
{
  "model": "claude-opus-4-5",
  "max_tokens": 256,
  "messages": [
    {"role": "user", "content": "Hello"}
  ]
}

Hugging Face Inference

YAML
POST https://api-inference.huggingface.co/models/bert-base-uncased

Headers:
  Authorization: Bearer 
  Content-Type: application/json

Body (raw JSON):
{
  "inputs": "The capital of France is [MASK]."
}

Local Ollama server

YAML
POST http://localhost:11434/api/generate

Headers:
  Content-Type: application/json

Body (raw JSON):
{
  "model": "llama3",
  "prompt": "Hello",
  "stream": false
}

For streaming responses (server-sent events from OpenAI or Anthropic), the body comes back as chunked text rather than a single JSON object. Requestly will display the stream — useful for confirming that your endpoint actually streams when it claims to.

Requestly vs Postman, Bruno, Hoppscotch, Apidog

Every team already has an API client they like. The question isn’t whether Requestly is objectively better — it’s whether the tradeoffs line up with how you work.

vs Postman

Postman is the incumbent. It’s feature-rich, well-documented, and bloated. Recent pricing changes and a forced cloud-sync default pushed a lot of teams to look elsewhere. Requestly is lighter, free, and keeps your data local unless you opt in.

vs Bruno

Bruno is git-friendly — collections are plain files you commit to a repo. If your team treats API specs as code, Bruno wins. Requestly trades that for a polished UI and better in-app preview.

vs Hoppscotch

Hoppscotch is open source and web-based by default. Great for quick checks from a browser tab. Requestly’s desktop-first approach handles local-network testing and large file uploads more comfortably.

vs Apidog

Apidog leans into the full API lifecycle — design, mock, document, test. If you want a single tool to replace Postman + Swagger + Mockoon, Apidog is the pitch. Requestly stays focused on testing and debugging, which is the lighter footprint.

Best practices for API testing in ML projects

Do this

  • Keep one collection per service — not per project
  • Use environment variables for every URL and API key
  • Pin sample images and payloads inside the repo so collections are reproducible
  • Write post-response assertions for status, content-type, and JSON shape
  • Run the collection runner as a manual smoke test before any deployment
  • Export collections to JSON and commit them next to the FastAPI code

Avoid this

  • Hard-coding hostnames inside every request
  • Storing API keys in plain text variables instead of secrets
  • Letting collections drift from the actual route paths in code
  • Skipping the runner step and trusting that “one good call” means the build is fine
  • Treating an API client as a replacement for proper integration tests in CI

Common mistakes to avoid

  • Confusing form-data with raw JSON. FastAPI’s UploadFile needs multipart form-data. Sending a JSON body with a base64 string is a different endpoint contract entirely.
  • Mismatched field names. The body parameter is file, not image. FastAPI returns 422 with a clear “field required” message — read it instead of assuming the server is broken.
  • First-call latency mistaken for a hang. Loading a vision model takes seconds. Add a longer timeout for the first request after server boot.
  • Forgetting the port. Half the time the request fails because uvicorn is on 8080 and the collection points to 8000.
  • Leaking API keys in exports. Always mark keys as secret before sharing a collection with a teammate.

Conclusion

For data scientists and ML engineers, the API layer is where most production bugs actually live. A focused tester like Requestly turns ad-hoc curl commands into a real test surface — reusable collections, environment variables, multipart file uploads, response assertions, and a runner that catches regressions before users do.

Pick one service, build one collection, write three post-response assertions, and run the collection before your next model deploy. That’s an afternoon of work and a meaningful reduction in “works on my notebook” failures.

Requestly for Data Science: A Practical API Testing Tool for ML and AI Engineers FAQ

Is Requestly free?

Yes. After the BrowserStack acquisition the core product is free and open source. Paid plans exist for team features like shared workspaces and admin controls, but solo and small-team use is unrestricted.

Can I import Postman collections?

Yes. Requestly supports importing Postman v2.1 collection JSON. Environment variables and most request bodies carry over cleanly. Test scripts may need light edits because the assertion helper names are slightly different.

Does Requestly support gRPC or GraphQL?

GraphQL is supported as a request type — you write the query and variables in dedicated tabs and the response is rendered as JSON. gRPC support is limited compared to specialised clients; for heavy gRPC work, a dedicated tool like grpcurl or Kreya is a better fit.

Can I run Requestly collections in CI?

A CLI runner exists. You export the collection to JSON and feed it into the runner with an environment file. That’s the path to integrate smoke tests into GitHub Actions or GitLab CI. For full integration coverage you’ll still want pytest or a similar framework inside the codebase.

How is data stored?

Collections and variables live locally by default. Optional sync ties them to your account so you can move between machines or share with a team. Mark secrets as secret to keep them out of plaintext exports.

Is the AI test-generation feature worth using?

For routine status, header, and shape assertions, yes — it saves typing. For domain-specific checks (confidence ranges, label whitelists, schema validation), you’ll still write those by hand. Treat it as a scaffolding shortcut, not a substitute for thinking about what the assertion should be.

Does it work for testing local models served by Ollama or vLLM?

Yes. Local servers are just HTTP endpoints. Point a request at http://localhost:11434 for Ollama or your vLLM port and treat it like any other API. The desktop app handles localhost traffic without proxy weirdness.