For GitHub Actions, use certyn-one/action@v1.
Use these endpoints directly for GitLab CI, Jenkins, CircleCI, Azure DevOps, Bitbucket Pipelines, and other systems.
These endpoints are for systems that need direct HTTP control. They cover both directions:
| Endpoint | Direction | Scope |
|---|---|---|
POST /api/ci/runs | Ask Certyn to run a suite | ci:trigger |
GET /api/ci/runs/:runId | Poll it | ci:status |
POST /api/ci/runs/:runId/cancel | Stop it | ci:cancel |
POST /api/ci/results | Push your own test report in | ci:results |
Create run
/api/ci/runsAPI KeyHeaders
| Header | Value |
|---|---|
Content-Type | application/json |
X-API-Key | your API key |
Idempotency-Key | recommended |
Body
{
"projectSlug": "my-app",
"environmentKey": "staging",
"processSlug": "smoke-suite",
"repository": "org/repo",
"ref": "main",
"commitSha": "a1b2c3d4",
"event": "push",
"externalUrl": "https://ci.example.com/build/123"
}
Notes:
projectSlugis required.environmentKeyis optional; if omitted, the default project environment is used.- Specify exactly one of:
processSlug(recommended), ortags(non-empty array)
- Use
Idempotency-Keyto prevent duplicate runs on retried CI jobs.
Example request
CERTYN_API_URL="https://api.certyn.io"
curl -sS -X POST "$CERTYN_API_URL/api/ci/runs" \
-H "Content-Type: application/json" \
-H "X-API-Key: $CERTYN_API_KEY" \
-H "Idempotency-Key: $CI_JOB_ID" \
-d '{
"projectSlug": "my-app",
"environmentKey": "staging",
"processSlug": "smoke-suite",
"commitSha": "a1b2c3d4"
}'
Get run status
/api/ci/runs/{runId}API KeyStatus fields used for gating
state(in_progress,completed,cancelled)failedblockedappUrlretryAfterSeconds
Polling guidance
- Poll every 10-30 seconds.
- Prefer
retryAfterSecondswhen returned. - Gate fail condition:
failed > 0 || blocked > 0.
Example polling loop
#!/usr/bin/env bash
set -euo pipefail
CERTYN_API_URL="${CERTYN_API_URL:-https://api.certyn.io}"
RUN_ID="${1:?Usage: $0 <run-id>}"
MAX_ATTEMPTS=60
for i in $(seq 1 "$MAX_ATTEMPTS"); do
resp="$(curl -sS -H "X-API-Key: $CERTYN_API_KEY" "$CERTYN_API_URL/api/ci/runs/$RUN_ID")"
state="$(echo "$resp" | jq -r '.state')"
failed="$(echo "$resp" | jq -r '.failed')"
blocked="$(echo "$resp" | jq -r '.blocked')"
interval="$(echo "$resp" | jq -r '.retryAfterSeconds // 15')"
echo "poll=$i state=$state failed=$failed blocked=$blocked"
if [ "$state" = "completed" ] || [ "$state" = "cancelled" ]; then
if [ "$failed" != "0" ] || [ "$blocked" != "0" ]; then
exit 1
fi
exit 0
fi
sleep "$interval"
done
echo "Timed out waiting for run completion"
exit 1
Cancel run
/api/ci/runs/{runId}/cancelAPI KeyOptional JSON body:
{
"reason": "Cancelled by pipeline"
}
Push results
/api/ci/resultsAPI KeyUploads a report from a suite your CI ran. Certyn ingests it as an already-finished run, so it appears next to the runs Certyn started, with pass and fail history per test. Nothing is executed by an agent.
For the framework-by-framework recipes, see Bring Your Test Framework.
Headers
| Header | Value |
|---|---|
X-API-Key | an API key with the ci:results scope |
Idempotency-Key | recommended; a replayed key returns the original run with Idempotency-Replayed: true |
Query parameters
The report is the raw request body. Everything else is a query parameter.
| Parameter | Required | Notes |
|---|---|---|
projectSlug | yes | |
suite | yes | Stable slug for this suite, for example e2e. A process is created for it on first push and reused after. |
suiteName | no | Display name for that process |
environmentKey | no | Defaults to the project's default environment |
format | no | playwright or junit. Sniffed from the body when omitted: a leading < means JUnit XML, anything else means Playwright JSON. Passing it explicitly is still recommended. |
repository | no | For example org/repo |
ref | no | Branch or tag |
commitSha | no | |
commitMessage | no | |
event | no | For example push or pull_request |
externalUrl | no | Link back to the CI job |
Body limit is 32 MB.
Example request
CERTYN_API_URL="https://api.certyn.io"
curl -sS -X POST \
"$CERTYN_API_URL/api/ci/results?projectSlug=my-app&suite=e2e&environmentKey=staging&format=junit" \
-H "X-API-Key: $CERTYN_API_KEY" \
-H "Idempotency-Key: $CI_JOB_ID" \
-H "Content-Type: application/xml" \
--data-binary @junit.xml
Response
201 Created on first ingest, 200 OK on an idempotent replay.
{
"runId": "run-id",
"processSlug": "e2e",
"total": 128,
"passed": 124,
"failed": 3,
"skipped": 1,
"hasFailures": true,
"statusPath": "/api/ci/runs/run-id",
"statusUrl": "https://api.certyn.io/api/ci/runs/run-id",
"appUrl": "https://app.certyn.io/...",
"message": null
}
Gate on hasFailures, or on failed if you want to allow a threshold. The statusUrl is the same run status endpoint documented above.
Errors
| Status | When |
|---|---|
400 | Missing projectSlug or suite, empty body, unknown format, or a report Certyn could not parse |
404 | Project or environment not found |
409 | The suite slug already belongs to a process of a different kind, or the idempotency key was reused with a different report |