You wrote the API tests. They pass on your machine. And that’s exactly where they stay, because running them is a thing someone has to remember to do. A teammate ships a change on Friday afternoon, the auth endpoint quietly starts returning a 500 on one code path, and the first person to find out is a user on Monday. The coverage was there the whole time. Nobody ran it at the moment it would have caught the regression.
The fix is to move the tests out of your editor and into the pipeline, so they run on every push without a human in the loop. That means you need a command that runs your API tests headlessly, returns a clean pass or fail, and slots into whatever CI system you already use. The Apidog CLI does that. You build your test scenarios visually in Apidog, then run them from a single terminal command that any CI runner with Node.js can execute. No GUI, no rewriting tests as code, no extra service to host.
This is a copy-paste guide. Below you’ll find ready-to-use pipeline files for GitHub Actions, GitLab CI, Jenkins, CircleCI, and Azure Pipelines, plus the handful of patterns that keep a green build honest. Grab the block for your platform, swap in your IDs and a secret, and you have API tests gating every merge by the end of the day. If you want the exhaustive flag reference instead, the broader topic of how to automate API tests in CI/CD covers the strategy; this page is about getting a working pipeline pasted in.
What you’re wiring up
The Apidog CLI is an npm package, apidog-cli. It runs the test scenarios you author in the Apidog app: chained requests, assertions, values pulled from one response into the next, data-driven iteration. The CLI doesn’t invent its own test format. It reaches into your project, finds the scenario by ID, runs it the same way the app would, and reports back with an exit code.
That exit code is the whole point. When every assertion passes, the run exits 0. When anything fails, it exits non-zero. CI systems read that exit code, mark the step failed, and block the merge or the deploy. You don’t configure a gate; the gate is the exit code. As long as the apidog run step sits in your pipeline, a broken assertion stops the line.
Three things make a run work, and you’ll see them in every block below:
- An access token, which proves the run is allowed to execute your scenario. Treat it like a password. Store it as a CI secret, never in a committed file.
- A scenario ID (or folder ID, or test suite ID), which says what to run.
- An environment ID, which says where to run it: dev, staging, or production.
You don’t type those IDs by hand. Open the test scenario in Apidog, switch to its CI/CD tab, pick the command-line option, and generate an access token. Apidog hands you the full apidog run command with the scenario ID and environment ID already filled in. Copy it once, then move the token out into a secret. If you haven’t built a scenario yet, start with how to write test scenarios with Apidog and come back when you have one passing.
The one command everything is built on
Here’s the canonical run. Every pipeline file is a wrapper around this line:
apidog run \
--access-token $APIDOG_ACCESS_TOKEN \
-t 605067 \
-e 1629989 \
-n 1 \
-r html,junit \
--out-dir ./apidog-reports
What each piece does:
--access-tokenauthenticates the run. It reads from the$APIDOG_ACCESS_TOKENenvironment variable, which you populate from a secret.-t 605067runs the test scenario with that ID. Swap-tfor-f <folderId>to run an entire folder, or--test-suite <id>to run a curated suite.-e 1629989targets an environment. This is how the same scenario hits staging in a PR check and production in a post-deploy smoke test.-n 1runs the scenario once. Bump it to loop, or pair it with-d <file>to drive iterations from a CSV or JSON data file.-r html,junitpicks the report formats.junitemits the XML your CI dashboard parses into a pass/fail tree;htmlis a browsable report you save as a build artifact. Addcliif you want readable output in the log too.--out-dir ./apidog-reportsis where the reports land.
The reporters are the difference between “the build went red” and “here’s the assertion that failed and the response that broke it.” JUnit XML is the one nearly every platform understands natively, so it shows up in all five blocks below.
GitHub Actions
Drop this in .github/workflows/api-tests.yml. It runs your scenario on every pull request against main, uploads the report as an artifact, and fails the check if any assertion fails.
name: API tests
on:
pull_request:
branches: [main]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Apidog CLI
run: npm install -g apidog-cli
- name: Run API test scenario
run: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 605067 \
-e 1629989 \
-n 1 \
-r html,junit \
--out-dir ./apidog-reports
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: apidog-report
path: ./apidog-reports
Two details that matter. The token lives in Settings → Secrets and variables → Actions as APIDOG_ACCESS_TOKEN and reaches the step through env:. And if: always() on the upload step means you still get the report when the tests fail, which is the one time you actually need to read it. If a scenario breaks, the apidog run step exits non-zero, the job goes red, and the PR shows a failing check. For a deeper walkthrough of this platform specifically, see how to automate API tests in GitHub Actions.
GitLab CI
Same idea in .gitlab-ci.yml. The node:20 image already has the runtime, so the only setup is the install.
stages:
- test
api-tests:
stage: test
image: node:20
script:
- npm install -g apidog-cli
- >
apidog run
--access-token "$APIDOG_ACCESS_TOKEN"
-t 605067
-e 1629989
-r junit,cli
--out-dir ./apidog-reports
artifacts:
when: always
paths:
- apidog-reports/
reports:
junit: apidog-reports/*.xml
Store APIDOG_ACCESS_TOKEN under Settings → CI/CD → Variables as a masked, protected variable so it never prints in a log. The reports: junit: block is the part GitLab users tend to miss: it tells GitLab to parse the XML and render results right in the merge request widget. A reviewer sees which assertions failed without downloading a thing.
Jenkins
For a declarative pipeline, store the token as a Jenkins credential and pull it into the environment, then call the CLI in a stage. The post block feeds the JUnit XML into Jenkins’ test trend graphs and keeps the HTML report on the build.
pipeline {
agent any
environment {
APIDOG_ACCESS_TOKEN = credentials('apidog-access-token')
}
stages {
stage('API tests') {
steps {
sh 'npm install -g apidog-cli'
sh '''
apidog run \
--access-token $APIDOG_ACCESS_TOKEN \
-t 605067 \
-e 1629989 \
-n 1 \
-r html,junit \
--out-dir apidog-reports
'''
}
}
}
post {
always {
junit 'apidog-reports/*.xml'
archiveArtifacts artifacts: 'apidog-reports/**', allowEmptyArchive: true
}
}
}
If your build agents already have the CLI cached, drop the npm install line and call apidog run directly. Apidog ships a Jenkins-specific integration guide too if you want the plugin route rather than a shell step: integrate Apidog automated tests with Jenkins for CI/CD.
CircleCI
In .circleci/config.yml, use the Node convenience image and store the token as a project environment variable under Project Settings → Environment Variables.
version: 2.1
jobs:
api-tests:
docker:
- image: cimg/node:20.11
steps:
- checkout
- run:
name: Install Apidog CLI
command: npm install -g apidog-cli
- run:
name: Run API test scenario
command: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 605067 \
-e 1629989 \
-r junit,cli \
--out-dir ./apidog-reports
- store_test_results:
path: ./apidog-reports
- store_artifacts:
path: ./apidog-reports
destination: apidog-reports
workflows:
test:
jobs:
- api-tests
store_test_results is CircleCI’s equivalent of GitLab’s JUnit block; point it at the report directory and CircleCI surfaces failed assertions in its Tests tab. store_artifacts keeps the HTML report attached so you can open it from the build page.
Azure Pipelines
In azure-pipelines.yml, install Node with the task, run the CLI, and publish the JUnit results. Add APIDOG_ACCESS_TOKEN as a secret variable in the pipeline (or pull it from an Azure Key Vault variable group), then map it into the script step’s env.
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
displayName: 'Install Node.js'
- script: npm install -g apidog-cli
displayName: 'Install Apidog CLI'
- script: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 605067 \
-e 1629989 \
-r junit,html \
--out-dir ./apidog-reports
displayName: 'Run API test scenario'
env:
APIDOG_ACCESS_TOKEN: $(APIDOG_ACCESS_TOKEN)
- task: PublishTestResults@2
condition: always()
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'apidog-reports/*.xml'
testRunTitle: 'Apidog API tests'
The $(APIDOG_ACCESS_TOKEN) macro reads the secret pipeline variable; mapping it through env keeps it out of the visible command line. PublishTestResults@2 with condition: always() makes the results show up in the Tests tab whether the run passed or failed. For a fuller treatment of this platform, Apidog has a dedicated walkthrough on Azure DevOps pipeline API testing.
Patterns that keep the gate honest
A pipeline that runs your tests is the baseline. These recipes are what make it useful day to day.
Smoke test right after a deploy. Run one fast scenario against production the moment a release lands, pointed at the prod environment, and stop at the first failure:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e <prodEnvId> -r cli --on-error end
Full regression overnight. Run an entire folder of scenarios on a schedule and collect every failure into one report instead of stopping at the first:
apidog run --access-token $APIDOG_ACCESS_TOKEN -f <folderId> -r html,junit --on-error continue --out-dir ./nightly-reports
--on-error is the knob here. end fails fast, which you want for a deploy gate. continue runs every step so a nightly report shows all the breakage at once. Either way the run still exits non-zero if anything failed, so the gate holds.
Run one scenario over many inputs. Drive iterations from a data file and treat each row as its own pass:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -d ./test-data.csv -r junit
Test a feature branch, not main. Run the scenarios exactly as they exist on a branch:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 --branch feature-payments -e 1629989 -r cli
Debug a CI-only failure. When a scenario passes locally but fails in the pipeline, add --verbose. It prints the exact request the runner sent and the exact response it got back, which is almost always how you find the environment difference that’s causing the gap.
When the build lies to you
A few failure modes show up often enough to call out, because each one quietly defeats the gate.
The build stays green when a test should fail. This is the dangerous one. It almost always means the exit code is being swallowed. If you wrapped the command in a shell pipeline, or tacked on || true to “stop it from breaking the build,” you also stopped it from catching anything. Remove anything that masks the non-zero exit. The apidog run step has to be the thing the CI step reads.
Authentication errors. The token is wrong, expired, or never reached the command. Confirm the CI secret is actually populated (a masked echo of its length, never the value), and regenerate it from the scenario’s CI/CD tab if needed.
“Scenario not found.” The scenario ID, project ID, or branch doesn’t line up. Re-copy the command from the CI/CD tab so the IDs are guaranteed current, and double-check --branch points where you think.
Passes locally, fails in CI. Nearly always an environment difference. The runner may target a different -e environment, sit behind a firewall that can’t reach your host, or lack a variable the scenario needs. Run with --verbose and diff the request the runner produced against the one you send locally.
TLS failures against internal hosts. If your endpoint uses an internal CA, pass the extra CA cert rather than disabling verification. Reach for -k (skip SSL verification) only as a last resort on a trusted internal host with a self-signed cert, never against anything public.
Why build visually and run headlessly
There’s a real design choice underneath all this, and it’s worth a paragraph. With script-first runners, the test and its execution are the same file, so a brittle script is both your test and your bottleneck. With Apidog, the scenario in your project is the test, and the CLI just runs it where a person can’t be. Nobody maintains two representations of the same check. You author fast in the visual builder, you run automatically in the pipeline, and the two stay in sync because they’re the same artifact. That’s a big part of why teams treat Apidog as a Postman alternative for API testing once CI enters the picture, and why solid API assertions matter more than the runner you wrap them in.
The loop is simple once it’s running. Design and debug requests in the app. Chain them into a scenario with assertions. Push your code, and the CLI runs that scenario in CI on every change. When something breaks, the report names the assertion and the exit code stops the deploy. You fix it, push again, and the same gate confirms the fix.
If your tests are still living in someone’s editor, that’s the gap to close this week. Download Apidog, get one scenario passing, copy the apidog run command from its CI/CD tab, and paste the block above for your platform. You’ll have API tests gating every merge the same afternoon.
Frequently asked questions
Is the Apidog CLI free to use in CI? The CLI is a free npm package: npm install -g apidog-cli. It runs the scenarios from your Apidog project, so what you can run depends on your Apidog plan, but the command-line runner itself isn’t a separate paid product.
Do I have to rewrite my tests as code? No. You build scenarios visually in Apidog and the CLI runs them by ID. The scenario is the test; the CLI is only the executor. That’s the main thing that separates it from script-first runners.
How does a failing test actually fail my build? Through the exit code. When any assertion fails, apidog run exits non-zero. Your CI system reads that, marks the step failed, and blocks the merge or deploy. You don’t add any extra configuration for the gate to work.
Which report format should I use? Use junit for the machine-readable XML your CI dashboard parses into pass/fail results, and add html if you want a browsable report saved as a build artifact. A common pairing is -r junit,html. Keep cli on too if you want readable output in the build log.
Do I need to install Apidog on the CI server? No. The CI runner only needs Node.js (v16 or later) and the apidog-cli package. No desktop app, no GUI, no license file on the box. The package plus an access token is enough.
Can I run it without a global install? Yes. Use npx apidog-cli run ... to execute it without a persistent global install, which is cleaner on ephemeral runners that get torn down after each job.
How is this different from Newman? Newman runs Postman collections from the command line. The Apidog CLI runs Apidog test scenarios. The roles are parallel, but the Apidog runner executes scenarios you authored in the app and ships as the single apidog-cli package. See Postman CLI vs Newman for the Postman side of that comparison.
Where do I get the access token and IDs? All from the test scenario’s CI/CD tab in Apidog. Pick the command-line option, generate an access token, and copy the full apidog run command Apidog builds with the scenario and environment IDs already filled in. Then move the token into a CI secret and reference it as $APIDOG_ACCESS_TOKEN.



