Skip to main content

API Reference

Reference documentation for the UnfoldCI GitHub Action and REST API.

GitHub Action

Usage

- name: Analyze Flaky Tests with UnfoldCI
uses: UnfoldAI-Labs/UnfoldCI-flaky-autopilot-action@v1
with:
api-key: ${{ secrets.FLAKY_AUTOPILOT_KEY }}
results-path: '**/test-results/**/*.xml'
comment-on-pr: 'true'

Inputs

InputRequiredDefaultDescription
api-keyNoUnfoldCI API key for authentication. Generate from dashboard settings.
api-urlNoProduction URLUnfoldCI API endpoint. Only change for testing.
results-pathNo**/test-results/**/*.xmlGlob pattern for locating JUnit XML test result files.
comment-on-prNotrueWhen true, posts a comment on PRs when flaky tests are detected.
enable-historical-backfillNotrueFetch past CI runs on first execution for instant analysis.
max-historical-runsNo50Number of past runs to fetch for backfill.

Outputs

OutputDescription
flakes_detectedNumber of flaky tests detected in this run.
tests_analyzedTotal number of tests analyzed from result files.
dashboard_urlURL to the UnfoldCI dashboard for detailed analysis.
statusAction status: success, rate_limited, or api_error.

REST API

Base URL: https://api.unfoldci.com

Authentication

All API requests require authentication via Bearer token:

Authorization: Bearer unfold_ci_your_api_key

Rate Limits

LimitValue
Tests per month (free)Varies by plan
API calls per minute60

When rate limited, the API returns:

{
"error": "Rate limit exceeded",
"retry_after": 60
}

Endpoints

Test Results

Submit Test Results
POST /api/webhooks/github

Submit test results from CI.

Request Body:

{
"repo_url": "https://github.com/org/repo",
"commit_sha": "abc123...",
"test_results": [
{
"name": "should handle async operations",
"file": "src/tests/async.test.ts",
"outcome": "passed",
"duration_ms": 150,
"code_hash": "sha256:..."
}
],
"source": "github_action"
}

Response:

{
"success": true,
"tests_received": 42,
"flakes_detected": 2
}

Repositories

List Repositories
GET /api/repos

Returns all repositories for the authenticated user.

Response:

{
"repos": [
{
"id": "uuid",
"name": "my-repo",
"full_name": "org/my-repo",
"url": "https://github.com/org/my-repo",
"test_count": 150,
"flaky_count": 3,
"health_score": 87.5
}
]
}
Get Repository Details
GET /api/repos/:id

Returns detailed repository information.

Response:

{
"id": "uuid",
"name": "my-repo",
"full_name": "org/my-repo",
"test_count": 150,
"flaky_count": 3,
"pass_rate": 94.2,
"recent_runs": 25,
"last_updated": "2024-01-15T10:30:00Z"
}

Tests

List Tests
GET /api/repos/:id/tests

Returns tests for a repository.

Query Parameters:

ParameterTypeDescription
statusstringFilter: all, flaky, failing, passing
sortstringSort by: flake_score, pass_rate, last_seen
limitnumberResults per page (default: 50)
offsetnumberPagination offset

Response:

{
"tests": [
{
"id": "uuid",
"name": "should handle async operations",
"file": "src/tests/async.test.ts",
"flake_score": 0.73,
"pass_rate": 68.5,
"run_count": 25,
"last_seen": "2024-01-15T10:30:00Z"
}
],
"total": 150,
"limit": 50,
"offset": 0
}
Get Test Details
GET /api/tests/:id

Returns detailed test information including AI analysis.

Response:

{
"id": "uuid",
"name": "should handle async operations",
"file": "src/tests/async.test.ts",
"flake_score": 0.73,
"pass_rate": 68.5,
"run_count": 25,
"status": "flaky",
"analysis": {
"category": "race_condition",
"hypothesis": "State is modified concurrently...",
"suggested_fix": "Add proper synchronization...",
"confidence": 0.85
},
"history": [
{
"outcome": "passed",
"duration_ms": 150,
"commit_sha": "abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
]
}

Fix Attempts

List Fix Attempts
GET /api/repos/:id/fixes

Returns AI-generated fix attempts for a repository.

Query Parameters:

ParameterTypeDescription
statusstringFilter: all, pending, merged, rejected
limitnumberResults per page (default: 20)

Response:

{
"fixes": [
{
"id": "uuid",
"test_id": "uuid",
"test_name": "should handle async operations",
"status": "pending",
"confidence": 0.85,
"pr_url": "https://github.com/org/repo/pull/123",
"created_at": "2024-01-15T10:30:00Z"
}
]
}

Analytics

Get CI Savings
GET /api/analytics/ci-savings

Returns CI time and cost savings metrics.

Response:

{
"time_saved_hours": 24.5,
"reruns_avoided": 156,
"estimated_cost_saved": 245.00,
"period": "last_30_days"
}
Get Pattern Analysis
GET /api/analytics/patterns/:repo_id

Returns code pattern analysis for a repository.

Response:

{
"health_score": 78,
"patterns_detected": [
{
"type": "hardcoded_wait",
"severity": "medium",
"count": 5,
"files": ["test/async.test.ts", "test/api.test.ts"]
},
{
"type": "shared_state",
"severity": "high",
"count": 2,
"files": ["test/integration.test.ts"]
}
],
"recommendations": [
"Replace setTimeout with proper async assertions",
"Isolate test state using beforeEach/afterEach hooks"
]
}

Notifications

Get Notification Config
GET /api/notifications/config

Returns notification configuration for the current installation.

Response:

{
"isEnabled": true,
"hasSlack": true,
"hasDiscord": false,
"hasTeams": false,
"slackWebhookUrl": "https://hooks.slack.com/services/...",
"enabledEvents": ["flaky_test_detected", "pr_created", "pr_merged"]
}
Update Notification Config
PUT /api/notifications/config

Updates notification configuration.

Request Body:

{
"isEnabled": true,
"slackWebhookUrl": "https://hooks.slack.com/services/...",
"discordWebhookUrl": "https://discord.com/api/webhooks/...",
"teamsWebhookUrl": "https://outlook.office.com/webhook/...",
"enabledEvents": ["flaky_test_detected", "pr_created"]
}

Response:

{
"success": true,
"config": { ... }
}
Remove Webhook
DELETE /api/notifications/webhook/:platform

Removes a specific platform webhook.

Parameters:

ParameterTypeDescription
platformstringslack, discord, or teams

Response:

{
"success": true,
"message": "Slack webhook removed"
}
Test Notification
POST /api/notifications/test/:platform

Sends a test notification to verify webhook configuration.

Response:

{
"success": true,
"message": "Test notification sent successfully"
}

Supported Test Result Formats

The action parses JUnit XML format, which is the standard output format for most test frameworks.

JUnit XML Structure

<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="MyTestSuite" tests="3" failures="1" time="1.234">
<testcase name="test_example" classname="tests.test_module" time="0.5">
</testcase>
<testcase name="test_failure" classname="tests.test_module" time="0.3">
<failure message="AssertionError">Expected true, got false</failure>
</testcase>
</testsuite>
</testsuites>

Parsed Test Result Fields

FieldDescription
nameTest name from the name attribute
fileTest file path, extracted from file attribute or classname
outcomepassed or failed based on presence of <failure> or <error>
duration_msTest duration in milliseconds
error_messageFailure message if test failed
code_hashHash of test file and dependencies for change detection

Configuration File

Create .flaky-autopilot.json in your repository root for advanced configuration:

{
"$schema": "https://unfoldci.com/schemas/flaky-autopilot-config.json",
"version": "1.0",
"importResolver": {
"aliases": {
"@": "./src",
"@utils": "./src/utils",
"@tests": "./tests"
},
"pythonPaths": [
".",
"./src",
"./tests"
],
"extensions": [
".js",
".ts",
".jsx",
".tsx",
".py"
],
"moduleDirectories": [
"node_modules"
]
}
}

Import Resolver Options

OptionDescription
aliasesPath aliases (e.g., @./src). Supports tsconfig/jsconfig paths.
pythonPathsPython module search paths. Parsed from pytest.ini if not specified.
extensionsFile extensions to try when resolving imports.
moduleDirectoriesDirectories to search for modules (default: node_modules).

API Key Format

API keys are prefixed with unfold_ci_ followed by a 64-character hexadecimal string:

unfold_ci_abc123def456789...

Key Scope

  • Keys are scoped to a GitHub App installation
  • A single key works for all repositories in that installation
  • Generate keys from the dashboard Settings page

Key Management

ActionLocation
GenerateDashboard → Settings → Generate New API Key
ViewDashboard → Settings (shows masked preview)
RevokeDashboard → Settings → Revoke button

Error Handling

The action is designed to be non-blocking:

  • API errors: Logged as warnings, workflow continues
  • Rate limits: Logged as warnings, workflow continues
  • Parse errors: Individual files skipped, others processed
  • Missing files: Warning logged, action completes successfully

Status Codes

StatusDescription
successResults submitted successfully
rate_limitedUsage limit exceeded, analysis skipped
api_errorAPI error occurred, analysis skipped

Webhook Events

The UnfoldCI GitHub App receives the following webhook events automatically:

EventPurpose
installationApp installed, updated, or uninstalled
installation_repositoriesRepositories added or removed
workflow_runCI workflow completed
pushCode changes detected
pull_requestPR opened or updated

No manual webhook configuration is required.