Most API tests start in a GUI: you create requests, add assertions, and run them manually. That breaks down when the same tests need to run on every push, on a schedule, or inside CI where no one is clicking buttons. For that workflow, you need one command that can run your API tests, fail the build, and export reports.
Apidog CLI gives you that command. In this tutorial, you’ll test a real REST API from the terminal: install the CLI, import an API, configure an environment, create a test scenario, run assertions, feed test data, and generate reports. The examples use Apidog CLI 2.2.2 against a public API.
If you also want to design tests visually, you can download Apidog and run the same scenarios from the CLI later.
What you’ll build
You’ll test restful-api.dev, a free public REST API with CRUD operations over an /objects resource.
By the end, you’ll have:
- An Apidog project created from an OpenAPI file
- A three-step test scenario:
- Create an object
- Read it back
- Delete it
- Assertions at each step
- A data-driven run using JSON test data
- CLI, HTML, JSON, JUnit, and cloud reports
The same flow applies to your own API and is the foundation for running API tests in CI/CD.
Prerequisites
You need:
- Node.js 16 or newer
- An Apidog account
- An Apidog API access token
If you’re comparing API test runners, Apidog CLI runs full test scenarios and manages API resources as code, which makes it different from Newman and the Postman CLI.
Step 1: Install Apidog CLI
Install the CLI globally from npm:
npm install -g apidog-cli@latest
Verify the installation:
apidog --version
# 2.2.2
Step 2: Log in with an API token
In the Apidog app, open:
Avatar menu → Account Settings → API Access Token
Copy your token, then run:
apidog login --with-token <YOUR_TOKEN>
The token is saved to:
~/.apidog/config.toml
Check the authenticated account:
CLI commands return structured JSON with a success flag and agentHints, so you can script against the output or pipe it into tools like jq.
Step 3: Create a project
List your teams:
apidog team list
Create a new project under the target team:
apidog project create --team 329562 --name "CLI Field Test"
The command returns the new project ID.
Save it as a shell variable:
PID=1314366 # replace with your project id
apidog project get $PID
Using variables keeps the remaining commands copy-paste friendly.
Step 4: Import the REST API from OpenAPI
You can create endpoints manually, but importing an OpenAPI file is faster and closer to how most teams start.
Create a file named objects-api.openapi.json:
{
"openapi": "3.0.3",
"info": { "title": "Objects API", "version": "1.0.0" },
"servers": [{ "url": "https://api.restful-api.dev" }],
"paths": {
"/objects": {
"get": { "summary": "List objects" },
"post": { "summary": "Create object" }
},
"/objects/{id}": {
"get": { "summary": "Get object by id" },
"put": { "summary": "Update object" },
"delete": { "summary": "Delete object" }
}
}
}
Import it into your project:
apidog import --project $PID --format openapi --file ./objects-api.openapi.json
# "createCount": 5 (5 endpoints created, 0 errors)
Apidog CLI can also import formats such as:
openapipostmanharinsomniajmeter
List the imported endpoints:
apidog endpoint list --project $PID
# 37921721 get /objects
# 37921722 post /objects
# 37921723 get /objects/{id}
# 37921724 put /objects/{id}
# 37921725 delete /objects/{id}
Step 5: Create an environment
An environment stores the base URL and reusable variables for test runs.
Create a production environment:
apidog environment create "Production" \
--project $PID \
--base-url "https://api.restful-api.dev"
List environments and copy the ID:
apidog environment list --project $PID
# { "id": 6334917, "name": "Production", "baseUrls": { "default": "https://api.restful-api.dev" } }
Save it:
ENV=6334917 # replace with your environment id
You’ll pass this environment to apidog run later:
-e $ENV
Step 6: Handle the automation write gate
Test scenarios and test data are automation resources. By default, writing them to the main branch from an external tool is blocked:
apidog test-scenario create \
--project $PID \
--name "x" \
--description "" \
--folder-id 0 \
--priority 1
# "error": { "code": "403075", "message": "Automation caller branch required" }
This is a guardrail. You have two options:
- Enable direct edit permission in the Apidog desktop app:
Project Settings → Feature Settings → AI Feature Settings → External AI Edit Permissions
- Work on an AI branch and merge later.
This tutorial uses the branch-based workflow.
Create an AI branch from main:
apidog branch create --project $PID --type ai \
--name "ai/20260616-from-main-cli-field-test" \
--from main
Save the branch name:
BR="ai/20260616-from-main-cli-field-test"
The expected naming pattern is:
ai/YYYYMMDD-from-<source>-<feature>
Only automation resources are gated. Commands such as import, environment create, and endpoint edits are not gated.
Step 7: Create a test scenario
A scenario is an ordered flow of API requests with assertions.
Create the scenario shell:
apidog test-scenario create --project $PID --branch "$BR" \
--name "Object CRUD lifecycle" \
--description "Create, read, then delete an object and assert each step" \
--folder-id 0 \
--priority 1
Save the returned scenario ID:
SID=1836498 # replace with your scenario id
Step 8: Define scenario steps as JSON
You add steps with test-scenario update and a JSON file.
Before writing JSON payloads, inspect and validate the expected schema:
apidog cli-schema get test-scenario-update
apidog cli-schema validate test-scenario-update --file ./steps-crud.json
# "data file is valid"
Each step contains:
- The HTTP request
- The request body, if needed
- Post-processing scripts
- Assertions
- Variables passed to later steps
Here is the shape of the first step, which creates an object and stores its id:
{
"type": "customHttp",
"name": "Create object",
"customHttpRequest": {
"path": "https://api.restful-api.dev/objects",
"method": "post",
"requestBody": {
"type": "json",
"data": "{\"name\":\"Apidog CLI Field Test\",\"data\":{\"price\":42}}"
},
"postProcessors": [
{
"type": "customScript",
"data": "pm.test('create returns 200', function () { pm.response.to.have.status(200); });\nvar body = pm.response.json();\npm.globals.set('objId', body.id);",
"enable": true
}
],
"projectId": 1314366
}
}
The next steps can reuse the saved ID with:
{{objId}}
For example:
https://api.restful-api.dev/objects/{{objId}}
Apply the full three-step file:
apidog test-scenario update $SID \
--project $PID \
--branch "$BR" \
--file ./steps-crud.json
# "success": true
You can also build scenarios visually in Apidog and run them from the CLI. The JSON workflow is useful when you want test definitions version-controlled and reviewed like application code.
Step 9: Run the scenario from the terminal
Run the scenario with the CLI reporter:
apidog run -t $SID \
--project $PID \
--branch "$BR" \
-e $ENV \
-r cli
Example output:
❏ Object CRUD lifecycle
↳ Create object POST .../objects [200 OK]
✓ create returns 200 ✓ response has an id ✓ name was echoed back
↳ Get the created object GET .../objects/ff80...3de [200 OK]
✓ get returns 200 ✓ id matches the created object ✓ price persisted in data
↳ Delete the object DELETE .../objects/ff80...3de [200 OK]
✓ delete returns 200
Http Requests 3 / 0 failed
Assertions 7 / 0 failed
The scenario made three requests, ran seven assertions, and passed the created id from the first step into the read and delete steps.
Step 10: Generate local reports
For CI or sharing, generate multiple report formats in one run:
apidog run -t $SID \
--project $PID \
--branch "$BR" \
-e $ENV \
-r cli,html,json,junit \
--out-dir ./reports \
--out-file "crud-report"
Check the generated files:
ls ./reports
# crud-report.html crud-report.json crud-report.xml
Use the reports as follows:
-
cli: terminal feedback -
html: human-readable report for teammates -
json: machine-readable run data -
junit: CI-compatible pass/fail output
Step 11: Run the same test with multiple inputs
Real API tests usually need multiple cases. Data-driven runs execute a scenario once per row of data, similar to parameterized testing from CSV and JSON.
Create objects-data.json:
[
{ "name": "Pixel 8 Pro", "price": 999 },
{ "name": "iPhone 15", "price": 899 },
{ "name": "Galaxy S24", "price": 799 }
]
Update your scenario so the request body reads values from each row:
{
"name": "{{name}}",
"data": {
"price": "{{price}}"
}
}
Run the scenario with the data file:
apidog run -t $DID \
--project $PID \
--branch "$BR" \
-e $ENV \
-d ./objects-data.json \
-r cli
Example output:
Iteration 1/3 … ✓ row created (200) ✓ name matches the data row
Iteration 2/3 … ✓ row created (200) ✓ name matches the data row
Iteration 3/3 … ✓ row created (200) ✓ name matches the data row
Iterations 3 / 0 failed Assertions 6 / 0 failed
Three rows produce three test iterations. You can swap the JSON file for CSV without changing the scenario structure.
Step 12: Upload a cloud report
Local reports are useful in CI. For a browser-accessible report your team can open, add --upload-report:
apidog run -t $SID \
--project $PID \
--branch "$BR" \
-e $ENV \
-r cli \
--upload-report
# Apidog CLI runs data uploaded to the cloud successfully.
# https://app.apidog.com/link/project/1314366/api-test/test-report/2605398
A cloud report is associated with the branch it ran on. Because this run used your AI branch, this command targets main and may not show it:
apidog test-report list --project $PID
Fetch the report by ID instead:
apidog test-report get 2605398 --project $PID
Download it as JSON:
apidog test-report download 2605398 \
--project $PID \
--format json \
--output ./cloud-report.json
Step 13: Export your API as a spec or docs
The CLI can also export project data.
Export OpenAPI:
apidog export \
--project $PID \
--format openapi \
--oas-version 3.0 \
--output ./openapi-export.json
Export Markdown docs:
apidog export \
--project $PID \
--format markdown \
--output ./api-docs.md
Export HTML docs:
apidog export \
--project $PID \
--format html \
--output ./api-docs.html
This is useful when you want to commit a fresh API spec or publish static docs from a pipeline.
Step 14: Add the test run to CI/CD
Everything you ran locally can become a CI job.
The minimum pipeline flow is:
- run: npm install -g apidog-cli@latest
- run: apidog login --with-token $APIDOG_TOKEN
- run: apidog run -t $SID --project $PID -e $ENV -r junit --out-dir ./reports
In CI:
- Store
APIDOG_TOKENas a secret - Use the JUnit reporter for test result parsing
- Archive
./reportsas build artifacts - Let the CLI fail the job when tests fail
The CLI returns a non-zero exit code on failures, so most CI systems fail the build automatically.
For a complete workflow, see the guide to running Apidog CLI tests in GitHub Actions, or compare API test automation tools that fit a pipeline.
Wrapping up
You now have an end-to-end API test running from the terminal:
- Import an API definition
- Create an environment
- Build a scenario with assertions
- Run it with
apidog run - Feed it test data
- Export local and cloud reports
- Move the same command into CI
Point the same workflow at your own API, commit scenario files alongside your code, and your API tests can run anywhere a shell is available.
To get started visually, download Apidog. For quick one-off checks, keep these curl alternatives for REST API testing handy.



Top comments (0)