Manta handbook · 11 of 12
How to Trigger Manta from Your CI/CD Pipeline
Call the CI/CD API from GitHub Actions, GitLab CI, or any pipeline to start an exploration or test run and gate a deploy on the result.
By the end of this guide, your pipeline will start a Manta run on its own — on a merge, before a release, whenever you say — and your deploy step will wait on the result instead of someone checking the dashboard by hand.
CI/CD triggering is available on paid plans. If your organization is on a free plan, the endpoint returns /billing/feature-not-available/ci-triggers until you upgrade.
Step 1 — Create an API key
From Settings → CI/CD (OWNER or ADMIN only), create a key and give it a name that says where it's used, e.g. "GitHub Actions – web". The key is shown once — copy it straight into your CI provider's secrets (MANTA_API_KEY or similar). If you lose it, revoke it and create a new one; there's no way to view it again.
[Screenshot: the CI/CD settings page with a newly generated key]
By default (Notifications: Off), runs triggered by a key notify no one — your pipeline is expected to read the result from the API. Set a key's Notifications to Failures only to notify people only about failed, timed-out or cancelled runs, or to All outcomes to notify about every run. Each person's own notification preferences still apply on top of this.
Step 2 — Trigger a run
POST /v1/ci/runs, authenticated with Authorization: Bearer <key> (or X-Api-Key: <key>). It returns immediately with 202 and a run id to poll. Swap <your-manta-api-host> below for your Manta API base URL — the same host your dashboard talks to.
Exploration (full or diff crawl):
curl -X POST https://<your-manta-api-host>/v1/ci/runs \
-H "Authorization: Bearer $MANTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"projectId": "<project-id>",
"environmentId": "<environment-id>",
"type": "CRAWL",
"crawlingMode": "DIFF",
"idempotencyKey": "'"$GITHUB_SHA"'"
}'
A DIFF crawl needs a prior full crawl on the environment to diff against — run a FULL crawl first if this is a new environment.
Test execution (a suite or a single plan):
curl -X POST https://<your-manta-api-host>/v1/ci/runs \
-H "Authorization: Bearer $MANTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"projectId": "<project-id>",
"environmentId": "<environment-id>",
"type": "TEST_EXECUTION",
"testSuiteId": "<test-suite-id>",
"idempotencyKey": "'"$GITHUB_SHA"'"
}'
Provide exactly one of testSuiteId or testPlanId. projectId and environmentId are visible on the project/environment pages in the dashboard.
The idempotencyKey is optional but worth setting to something stable for the trigger, like the commit SHA — if a retry sends the same key again, you get the original run back (200, not a second run) instead of starting a duplicate.
Step 3 — Poll for the result — your deploy gate
GET /v1/ci/runs/:id returns the current status:
QUEUED/RUNNING/PROCESSING— still going, keep polling.PASSED— proceed with the deploy.FAILED/TIMEOUT/CANCELLED— block the deploy.
curl https://<your-manta-api-host>/v1/ci/runs/$RUN_ID \
-H "Authorization: Bearer $MANTA_API_KEY"
For a test-execution run, the response also carries a tests object (total, passed, failed, errored, pending) and a reportUrl deep link into the dashboard. status goes terminal as soon as the run itself is done, so the gate never sits waiting on the AI write-up to finish generating.
For per-test detail in your pipeline log — which test failed and why — call GET /v1/ci/runs/:id/results.
Step 4 — Wire it into your pipeline
The same trigger-then-poll shape works anywhere curl and jq are available — here it is as a GitHub Actions step and a GitLab CI job.
GitHub Actions
Add MANTA_API_KEY as a repository secret, then:
- name: Manta test gate
env:
MANTA_API_KEY: ${{ secrets.MANTA_API_KEY }}
run: |
RUN_ID=$(curl -sf -X POST https://<your-manta-api-host>/v1/ci/runs \
-H "Authorization: Bearer $MANTA_API_KEY" -H "Content-Type: application/json" \
-d '{"projectId":"'"$MANTA_PROJECT_ID"'","environmentId":"'"$MANTA_ENVIRONMENT_ID"'",
"type":"TEST_EXECUTION","testSuiteId":"'"$MANTA_SUITE_ID"'",
"idempotencyKey":"'"$GITHUB_SHA"'"}' | jq -r .runId)
while :; do
STATUS=$(curl -sf https://<your-manta-api-host>/v1/ci/runs/$RUN_ID \
-H "Authorization: Bearer $MANTA_API_KEY" | jq -r .status)
case $STATUS in
PASSED) echo "Manta tests passed"; exit 0 ;;
FAILED|TIMEOUT|CANCELLED) echo "Manta tests did not pass"; exit 1 ;;
*) sleep 15 ;;
esac
done
GitLab CI
Add MANTA_API_KEY as a masked CI/CD variable (Settings → CI/CD → Variables), then:
manta_test_gate:
stage: test
image: alpine:latest
before_script:
- apk add --no-cache curl jq
script:
- |
RUN_ID=$(curl -sf -X POST https://<your-manta-api-host>/v1/ci/runs \
-H "Authorization: Bearer $MANTA_API_KEY" -H "Content-Type: application/json" \
-d '{"projectId":"'"$MANTA_PROJECT_ID"'","environmentId":"'"$MANTA_ENVIRONMENT_ID"'",
"type":"TEST_EXECUTION","testSuiteId":"'"$MANTA_SUITE_ID"'",
"idempotencyKey":"'"$CI_COMMIT_SHA"'"}' | jq -r .runId)
while :; do
STATUS=$(curl -sf https://<your-manta-api-host>/v1/ci/runs/$RUN_ID \
-H "Authorization: Bearer $MANTA_API_KEY" | jq -r .status)
case $STATUS in
PASSED) echo "Manta tests passed"; exit 0 ;;
FAILED|TIMEOUT|CANCELLED) echo "Manta tests did not pass"; exit 1 ;;
*) sleep 15 ;;
esac
done
CircleCI, Jenkins, and any other pipeline that can run curl follow the same shape — trigger, poll, exit non-zero on a bad status.
Running against a private target instead of the cloud
If the environment isn't reachable from Manta's cloud runners, add "executionEnv": "LOCAL" and "platform" (LINUX, MAC_SILICON, MAC_INTEL, or WINDOWS) to the trigger body. The response includes a package with a downloadUrl and a short-lived runKey — your pipeline downloads the runner, executes it inside your network, and gates on its exit code. This is the CI equivalent of a private-environment Runner.
Tips and common mistakes
- Poll, don't sleep-and-hope. A run's duration depends on what it finds — poll on an interval and act on
status, not a fixed timeout. - Set
idempotencyKeyto something tied to the trigger, like the commit SHA. A retried CI step then resumes the same run instead of starting a second one and doubling your credit spend. DIFFcrawls need a baseline. If the environment has never had a full crawl, triggerFULLfirst — aDIFFon a fresh environment fails.- Match run depth to the moment, the same as any other trigger — see fitting Manta into your release process for what to run on a merge versus before a release.
- One key per pipeline makes it easy to see which pipeline is spending credits, and to revoke just that one if a secret leaks.
What to try next
- How to Fit Manta Into Your Release Process — where the CI trigger fits next to schedules and on-demand runs.
- How to Test a Staging or Private Environment with the Manta Runner — the same idea for a target CI can't reach directly.
- How to Review a Run — reading the results the gate is acting on.
Generate an API key and add the trigger step to your pipeline.
Try it on your own app
Point Manta at a URL and see what it finds — no scripts, no setup. Free, no credit card.