API Reference

TINAA MSP exposes three API surfaces: a REST API over HTTP, 14 MCP tools via the FastMCP 2.0 protocol, and a WebSocket endpoint for real-time streaming. All REST endpoints are served on port 8765 and are prefixed with /api/v1/.

The interactive OpenAPI docs are available at http://localhost:8765/api/docs when the server is running.


Authentication

When TINAA_API_KEY is configured, include the key in every request:

1
X-API-Key: <your-api-key>

Unauthenticated requests return 401 Unauthorized.


Base URL

1
http://localhost:8765

All REST endpoints below are relative to this base URL.


Products API

List products

1
GET /api/v1/products

Returns all products registered in the platform, optionally filtered.

Query parameters

Parameter Type Description
status string Filter by status: active, paused, or archived
search string Case-insensitive substring match on product name
sort string Sort field. Supported: name, created_at, quality_score

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "Checkout Service",
    "slug": "checkout-service",
    "repository_url": "https://github.com/example/checkout-service",
    "description": "Handles cart and payment flows",
    "quality_score": 87.4,
    "status": "active",
    "created_at": "2026-01-15T10:23:44.123456+00:00"
  }
]

Example

1
2
curl -s http://localhost:8765/api/v1/products?status=active \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Register a product

1
POST /api/v1/products

Registers a new product for quality management.

Request body

1
2
3
4
5
6
7
8
9
{
  "name": "Checkout Service",
  "description": "Handles cart and payment flows",
  "repository_url": "https://github.com/example/checkout-service",
  "environments": {
    "production": "https://checkout.example.com",
    "staging": "https://staging-checkout.example.com"
  }
}
Field Type Required Description
name string yes Human-readable product name
description string no Optional description
repository_url string no Git repository URL
environments object no Map of environment name to base URL

Response 201 Created

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "Checkout Service",
  "slug": "checkout-service",
  "repository_url": "https://github.com/example/checkout-service",
  "description": "Handles cart and payment flows",
  "quality_score": null,
  "status": "active",
  "environments": [
    {"name": "production", "base_url": "https://checkout.example.com", "env_type": "production"},
    {"name": "staging", "base_url": "https://staging-checkout.example.com", "env_type": "production"}
  ],
  "created_at": "2026-03-23T09:00:00.000000+00:00"
}

Example

1
2
3
4
5
6
7
8
curl -s -X POST http://localhost:8765/api/v1/products \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{
    "name": "Checkout Service",
    "repository_url": "https://github.com/example/checkout",
    "environments": {"production": "https://checkout.example.com"}
  }' | jq .

Get product details

1
GET /api/v1/products/{id}

Returns full product details. The {id} segment accepts either a UUID or the product slug.

Path parameters

Parameter Description
id Product UUID or slug

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "Checkout Service",
  "slug": "checkout-service",
  "repository_url": "https://github.com/example/checkout-service",
  "description": "Handles cart and payment flows",
  "quality_score": 87.4,
  "status": "active",
  "environments": null,
  "created_at": "2026-01-15T10:23:44.123456+00:00"
}

Example

1
2
curl -s http://localhost:8765/api/v1/products/checkout-service \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Update product

1
PUT /api/v1/products/{id}

Partially updates product fields (PATCH semantics — omitted fields are unchanged).

Request body

1
2
3
4
5
{
  "name": "Checkout Service v2",
  "status": "paused",
  "description": "Updated description"
}

Response 200 OK — updated product object (same shape as GET).

Example

1
2
3
4
curl -s -X PUT http://localhost:8765/api/v1/products/checkout-service \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{"status": "paused"}' | jq .

Delete product

1
DELETE /api/v1/products/{id}

Permanently deletes a product and all associated data (cascading).

Response 204 No Content

Example

1
2
curl -s -X DELETE http://localhost:8765/api/v1/products/checkout-service \
  -H "X-API-Key: $TINAA_API_KEY"

List environments

1
GET /api/v1/products/{id}/environments

Returns all environments registered for a product.

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
[
  {
    "id": "7a1b3c5d-9e2f-4a8b-b6d0-1c2e3f4a5b6c",
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "production",
    "base_url": "https://checkout.example.com",
    "env_type": "production",
    "monitoring_interval_seconds": 300,
    "is_active": true,
    "created_at": "2026-01-15T10:23:44.123456+00:00"
  }
]

Example

1
2
curl -s "http://localhost:8765/api/v1/products/checkout-service/environments" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Add environment

1
POST /api/v1/products/{id}/environments

Adds a new deployment environment to a product.

Request body

1
2
3
4
5
{
  "name": "staging",
  "url": "https://staging.checkout.example.com",
  "type": "staging"
}
Field Type Required Description
name string yes Environment name (e.g. production, staging)
url string yes Base URL for the environment
type string no Environment type. One of production, staging, preview. Defaults to staging

Response 201 Created — environment object.

Example

1
2
3
4
curl -s -X POST "http://localhost:8765/api/v1/products/checkout-service/environments" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{"name": "staging", "url": "https://staging.checkout.example.com", "type": "staging"}' | jq .

Playbooks API

List playbooks

1
GET /api/v1/playbooks

Returns all playbooks, optionally scoped to a product or suite type.

Query parameters

Parameter Type Description
product_id UUID Filter by product
suite_type string Filter by suite type: smoke, regression, accessibility, security, full

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
[
  {
    "id": "pb-a1b2c3d4",
    "name": "checkout-regression",
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "suite_type": "regression",
    "step_count": 14,
    "status": "active",
    "last_run_at": "2026-03-23T08:00:00.000000+00:00",
    "created_at": "2026-01-20T12:00:00.000000+00:00"
  }
]

Example

1
2
curl -s "http://localhost:8765/api/v1/playbooks?product_id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Create playbook

1
POST /api/v1/playbooks

Creates a new test playbook.

Request body

1
2
3
4
5
6
7
8
9
10
11
{
  "name": "checkout-smoke",
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "suite_type": "smoke",
  "steps": [
    {"action": "navigate", "url": "https://checkout.example.com"},
    {"action": "click", "selector": "#add-to-cart"},
    {"action": "click", "selector": "#checkout-btn"},
    {"action": "assert_text", "selector": "h1", "text": "Order Confirmed"}
  ]
}
Field Type Required Description
name string yes Playbook name
product_id UUID yes Owning product
suite_type string yes smoke, regression, accessibility, security, or full
steps array yes Ordered list of action objects

Supported step actions

Action Required params Description
navigate url Navigate to a URL
click selector Click an element
fill selector, value Fill a form field
assert_text selector, text Assert element text
assert_url pattern Assert URL matches pattern
screenshot Capture a screenshot
wait ms Wait N milliseconds

Response 201 Created

1
2
3
4
5
6
7
8
9
10
{
  "id": "pb-a1b2c3d4",
  "name": "checkout-smoke",
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "suite_type": "smoke",
  "step_count": 4,
  "status": "active",
  "validation_errors": [],
  "created_at": "2026-03-23T09:00:00.000000+00:00"
}

Example

1
2
3
4
5
6
7
8
9
10
11
12
curl -s -X POST http://localhost:8765/api/v1/playbooks \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{
    "name": "checkout-smoke",
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "suite_type": "smoke",
    "steps": [
      {"action": "navigate", "url": "https://checkout.example.com"},
      {"action": "assert_text", "selector": "h1", "text": "Checkout"}
    ]
  }' | jq .

Get playbook

1
GET /api/v1/playbooks/{id}

Returns playbook details including all steps.

Response 200 OK — full playbook object with steps array.

Example

1
2
curl -s http://localhost:8765/api/v1/playbooks/pb-a1b2c3d4 \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Execute playbook

1
POST /api/v1/playbooks/{id}/run

Triggers an immediate execution of the playbook.

Request body (optional)

1
2
3
4
{
  "environment": "staging",
  "target_url": "https://staging.checkout.example.com"
}

Response 202 Accepted

1
2
3
4
5
6
7
{
  "run_id": "run-8f3a2b1c",
  "playbook_id": "pb-a1b2c3d4",
  "status": "queued",
  "environment": "staging",
  "started_at": "2026-03-23T09:05:00.000000+00:00"
}

Example

1
2
3
4
curl -s -X POST http://localhost:8765/api/v1/playbooks/pb-a1b2c3d4/run \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{"environment": "staging"}' | jq .

Test Runs API

List test runs

1
GET /api/v1/test-runs

Returns test run history with optional filters.

Query parameters

Parameter Type Description
product_id UUID Filter by product
status string Filter by status: queued, running, passed, failed, error, cancelled
limit integer Maximum results to return (default: 20, max: 100)

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
  {
    "id": "run-8f3a2b1c",
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "environment_id": "7a1b3c5d-9e2f-4a8b-b6d0-1c2e3f4a5b6c",
    "playbook_id": "pb-a1b2c3d4",
    "trigger": "manual",
    "status": "passed",
    "started_at": "2026-03-23T08:00:00.000000+00:00",
    "completed_at": "2026-03-23T08:00:42.500000+00:00",
    "duration_ms": 42500,
    "results_summary": {
      "total": 14,
      "passed": 14,
      "failed": 0,
      "skipped": 0
    },
    "quality_score_before": 85.0,
    "quality_score_after": 87.4,
    "created_at": "2026-03-23T08:00:00.000000+00:00"
  }
]

Example

1
2
curl -s "http://localhost:8765/api/v1/test-runs?status=failed&limit=10" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Get test run details

1
GET /api/v1/test-runs/{id}

Returns full details for a single test run including per-step results.

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "id": "run-8f3a2b1c",
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "environment_id": "7a1b3c5d-9e2f-4a8b-b6d0-1c2e3f4a5b6c",
  "playbook_id": "pb-a1b2c3d4",
  "trigger": "deployment",
  "status": "failed",
  "started_at": "2026-03-23T08:00:00.000000+00:00",
  "completed_at": "2026-03-23T08:00:38.200000+00:00",
  "duration_ms": 38200,
  "commit_sha": "a1b2c3d4e5f6",
  "deployment_url": "https://checkout.example.com",
  "results_summary": {
    "total": 14,
    "passed": 12,
    "failed": 2,
    "skipped": 0
  },
  "quality_score_before": 87.4,
  "quality_score_after": 84.1,
  "error_message": null,
  "artifacts_url": "https://storage.example.com/artifacts/run-8f3a2b1c",
  "created_at": "2026-03-23T08:00:00.000000+00:00"
}

Example

1
2
curl -s http://localhost:8765/api/v1/test-runs/run-8f3a2b1c \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Trigger a test run

1
POST /api/v1/test-runs

Manually triggers a test run for a product.

Request body

1
2
3
4
5
6
7
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "environment_id": "7a1b3c5d-9e2f-4a8b-b6d0-1c2e3f4a5b6c",
  "playbook_id": "pb-a1b2c3d4",
  "trigger": "manual",
  "commit_sha": "a1b2c3d4e5f6"
}
Field Type Required Description
product_id UUID yes Target product
environment_id UUID yes Target environment
playbook_id UUID no Specific playbook (omit for full suite)
trigger string yes manual, deployment, schedule, pr, or anomaly
commit_sha string no Associated Git commit SHA

Response 202 Accepted

1
2
3
4
5
6
7
8
{
  "id": "run-9d4e5f6a",
  "status": "queued",
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "environment_id": "7a1b3c5d-9e2f-4a8b-b6d0-1c2e3f4a5b6c",
  "trigger": "manual",
  "created_at": "2026-03-23T09:10:00.000000+00:00"
}

Example

1
2
3
4
5
6
7
8
curl -s -X POST http://localhost:8765/api/v1/test-runs \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "environment_id": "7a1b3c5d-9e2f-4a8b-b6d0-1c2e3f4a5b6c",
    "trigger": "manual"
  }' | jq .

Metrics API

Query metrics

1
GET /api/v1/metrics

Returns time-series performance metrics for a product or endpoint.

Query parameters

Parameter Type Description
product_id UUID Required. Product to query
metric_type string response_time, ttfb, fcp, lcp, cls, inp, availability, error_rate. Returns all when omitted
time_range string Lookback window: 1h, 6h, 24h, 7d, 30d. Default: 24h
endpoint_path string Scope to a specific endpoint path (e.g. /api/checkout)

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "metric_type": "response_time",
  "time_range": "24h",
  "data_points": [
    {"timestamp": "2026-03-22T09:00:00+00:00", "value": 312.0},
    {"timestamp": "2026-03-22T10:00:00+00:00", "value": 298.0},
    {"timestamp": "2026-03-22T11:00:00+00:00", "value": 340.0}
  ],
  "baseline": {
    "p50": 220.0,
    "p90": 450.0,
    "p99": 900.0,
    "mean": 235.0
  },
  "current_avg": 316.7,
  "trend": "stable"
}

Example

1
2
curl -s "http://localhost:8765/api/v1/metrics?product_id=3fa85f64-5717-4562-b3fc-2c963f66afa6&metric_type=lcp&time_range=7d" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Get baselines

1
GET /api/v1/metrics/baselines

Returns computed baseline statistics for a product.

Query parameters: product_id (required), metric_type (optional).

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "baselines": [
    {
      "metric_type": "response_time",
      "p50": 220.0,
      "p90": 450.0,
      "p99": 900.0,
      "mean": 235.0,
      "std_dev": 68.2,
      "sample_count": 1440,
      "computed_at": "2026-03-23T00:00:00.000000+00:00"
    }
  ]
}

Example

1
2
curl -s "http://localhost:8765/api/v1/metrics/baselines?product_id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Get detected anomalies

1
GET /api/v1/metrics/anomalies

Returns metrics anomalies detected by the APM agent.

Query parameters: product_id (required), hours (default: 24).

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "anomalies": [
    {
      "id": "anom-3c4d5e6f",
      "metric_type": "response_time",
      "endpoint_path": "/api/search",
      "detected_at": "2026-03-23T07:42:00.000000+00:00",
      "severity": "warning",
      "current_value": 1240.0,
      "baseline_p99": 900.0,
      "deviation_pct": 37.8,
      "description": "P95 response time 37.8% above baseline on /api/search"
    }
  ]
}

Example

1
2
curl -s "http://localhost:8765/api/v1/metrics/anomalies?product_id=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Quality API

Get quality score

1
GET /api/v1/quality/{product_id}

Returns the current composite quality score with component breakdown.

Path parameters

Parameter Description
product_id Product UUID or slug

Query parameters

Parameter Type Description
environment string Scope to a specific environment. Returns aggregate when omitted

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "environment": "production",
  "score": 87.4,
  "components": {
    "test_health": {
      "score": 91.0,
      "weight": 0.35,
      "pass_rate": 0.94,
      "flakiness_rate": 0.02
    },
    "performance_health": {
      "score": 84.0,
      "weight": 0.30,
      "p95_ms": 420,
      "lcp_ms": 1800,
      "slo_compliance": 0.98
    },
    "security_posture": {
      "score": 88.0,
      "weight": 0.20,
      "open_findings": 2,
      "critical": 0,
      "high": 0
    },
    "accessibility": {
      "score": 82.0,
      "weight": 0.15,
      "violations": 4,
      "warnings": 11,
      "wcag_level": "AA"
    }
  },
  "trend": "improving",
  "recommendations": [
    "Fix 4 accessibility violations on /checkout to gain +3 points.",
    "Reduce P95 response time below 400 ms to meet SLO."
  ],
  "computed_at": "2026-03-23T09:00:00.000000+00:00"
}

Example

1
2
curl -s "http://localhost:8765/api/v1/quality/checkout-service?environment=production" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Quality score history

1
GET /api/v1/quality/{product_id}/history

Returns historical quality scores for trend analysis.

Query parameters

Parameter Type Description
days integer Lookback window in days. Default: 30
environment string Scope to a specific environment

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "history": [
    {"date": "2026-02-22", "score": 82.1, "environment": "production"},
    {"date": "2026-03-01", "score": 84.5, "environment": "production"},
    {"date": "2026-03-15", "score": 86.0, "environment": "production"},
    {"date": "2026-03-23", "score": 87.4, "environment": "production"}
  ],
  "trend_7d": 1.4,
  "trend_30d": 5.3
}

Example

1
2
curl -s "http://localhost:8765/api/v1/quality/checkout-service/history?days=30" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Full quality report

1
GET /api/v1/quality/{product_id}/report

Generates a comprehensive quality report aggregating all subsystems.

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "environment": "all",
  "generated_at": "2026-03-23T09:00:00.000000+00:00",
  "quality_score": 87.4,
  "trend_7d": 1.4,
  "trend_30d": 5.3,
  "test_summary": {
    "total_runs": 124,
    "pass_rate": 0.94,
    "flaky_playbooks": 1,
    "avg_duration_ms": 4200
  },
  "performance_summary": {
    "p50_ms": 210,
    "p95_ms": 420,
    "p99_ms": 890,
    "lcp_ms": 1800,
    "cls": 0.08,
    "slo_compliance": 0.98
  },
  "security_summary": {
    "open_findings": 2,
    "critical": 0,
    "high": 0,
    "medium": 2,
    "last_scan_at": "2026-03-23T06:00:00.000000+00:00"
  },
  "accessibility_summary": {
    "violations": 4,
    "warnings": 11,
    "wcag_level": "AA",
    "score": 82
  },
  "top_issues": [
    {
      "severity": "medium",
      "type": "accessibility",
      "description": "Missing alt text on 3 images in /checkout"
    },
    {
      "severity": "medium",
      "type": "performance",
      "description": "P95 response time exceeds 400 ms SLO on /api/search"
    }
  ],
  "recommendations": [
    "Add alt text to images on /checkout to fix 3 accessibility violations.",
    "Optimise /api/search query to bring P95 below 400 ms.",
    "Schedule nightly full suite run to catch regressions earlier."
  ]
}

Example

1
2
curl -s http://localhost:8765/api/v1/quality/checkout-service/report \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Alerts API

List alerts

1
GET /api/v1/alerts

Returns active and historical alert events.

Query parameters

Parameter Type Description
severity string Filter by severity: critical, warning, or info
status string Filter by status: open, acknowledged, resolved
product_id UUID Filter by product
limit integer Max results to return (default: 50)

Response 200 OK

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[
  {
    "id": "alert-1a2b3c4d",
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "rule_id": "rule-5e6f7a8b",
    "condition_type": "performance_regression",
    "severity": "warning",
    "status": "open",
    "title": "P95 response time spike on /api/search",
    "description": "Response time 37.8% above baseline — P95: 1240 ms vs baseline: 900 ms",
    "triggered_at": "2026-03-23T07:42:00.000000+00:00",
    "acknowledged_at": null,
    "resolved_at": null
  }
]

Example

1
2
curl -s "http://localhost:8765/api/v1/alerts?severity=critical&status=open" \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Create alert rule

1
POST /api/v1/alerts/rules

Creates a new alert rule for automated monitoring.

Request body

1
2
3
4
5
6
7
8
9
{
  "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "Quality drop alert",
  "condition_type": "quality_score_drop",
  "severity": "warning",
  "threshold": {"value": 10},
  "channels": ["slack:#engineering-alerts", "email:team@example.com"],
  "enabled": true
}
Field Type Required Description
product_id UUID yes Product to monitor
name string yes Human-readable rule name
condition_type string yes quality_score_drop, test_failure, performance_regression, endpoint_down, or security_issue
severity string yes critical, warning, or info
threshold object yes Condition-specific threshold values
channels array no Notification channels
enabled boolean no Whether the rule is active (default: true)

Response 201 Created — created rule object.

Example

1
2
3
4
5
6
7
8
9
10
curl -s -X POST http://localhost:8765/api/v1/alerts/rules \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $TINAA_API_KEY" \
  -d '{
    "product_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "Quality drop alert",
    "condition_type": "quality_score_drop",
    "severity": "warning",
    "threshold": {"value": 10}
  }' | jq .

Acknowledge alert

1
PUT /api/v1/alerts/{id}/acknowledge

Marks an alert as acknowledged, suppressing repeat notifications.

Response 200 OK

1
2
3
4
5
{
  "id": "alert-1a2b3c4d",
  "status": "acknowledged",
  "acknowledged_at": "2026-03-23T09:15:00.000000+00:00"
}

Example

1
2
curl -s -X PUT http://localhost:8765/api/v1/alerts/alert-1a2b3c4d/acknowledge \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Resolve alert

1
PUT /api/v1/alerts/{id}/resolve

Marks an alert as resolved.

Response 200 OK

1
2
3
4
5
{
  "id": "alert-1a2b3c4d",
  "status": "resolved",
  "resolved_at": "2026-03-23T09:30:00.000000+00:00"
}

Example

1
2
curl -s -X PUT http://localhost:8765/api/v1/alerts/alert-1a2b3c4d/resolve \
  -H "X-API-Key: $TINAA_API_KEY" | jq .

Webhooks API

GitHub webhook receiver

1
POST /api/v1/webhooks/github

Receives GitHub webhook events and triggers automated test runs on deployment events and PR updates.

TINAA processes the following GitHub event types:

GitHub event Action TINAA behaviour
deployment_status success Triggers regression test run against deployment URL
pull_request opened, synchronize Triggers smoke test run on PR environment
push main branch Triggers scheduled suite on production environment

Headers required by GitHub

1
2
3
X-GitHub-Event: deployment_status
X-Hub-Signature-256: sha256=<hmac-sha256>
Content-Type: application/json

The webhook secret is configured via GITHUB_WEBHOOK_SECRET. TINAA validates the HMAC-SHA256 signature on every request.

Response 200 OK

1
2
3
4
5
{
  "status": "accepted",
  "event": "deployment_status",
  "run_id": "run-9d4e5f6a"
}

Example (simulating a GitHub delivery)

1
2
3
4
5
curl -s -X POST http://localhost:8765/api/v1/webhooks/github \
  -H "Content-Type: application/json" \
  -H "X-GitHub-Event: deployment_status" \
  -H "X-Hub-Signature-256: sha256=<computed-hmac>" \
  -d @github_event_payload.json | jq .

Health Endpoints

Health check

1
GET /health

Returns service health status. Used as a liveness probe by Docker and Kubernetes.

Response 200 OK

1
2
3
4
5
{
  "status": "healthy",
  "version": "2.0.0",
  "timestamp": "2026-03-23T09:00:00.000000+00:00"
}

Example

1
curl -s http://localhost:8765/health | jq .

Readiness probe

1
GET /health/ready

Returns readiness status — checks database and Redis connectivity. Used as a readiness probe by Kubernetes.

Response 200 OK

1
2
3
4
5
6
7
8
{
  "status": "ready",
  "checks": {
    "database": "ok",
    "redis": "ok"
  },
  "timestamp": "2026-03-23T09:00:00.000000+00:00"
}

Returns 503 Service Unavailable when any dependency is not reachable.

Example

1
curl -s http://localhost:8765/health/ready | jq .

Error Responses

All error responses follow a consistent shape:

1
2
3
{
  "detail": "Product 'unknown-slug' not found"
}
Status Meaning
400 Bad Request Invalid request body or business logic violation
401 Unauthorized Missing or invalid API key
404 Not Found Resource does not exist
422 Unprocessable Entity Request body failed validation
503 Service Unavailable Upstream dependency (database, Redis) unreachable

MCP Tools

TINAA exposes 14 tools over the FastMCP 2.0 protocol. Connect to the MCP server at port 8765 (same process, same port, different transport).

Tool index

# Tool name Description
1 register_product Register a new product for quality management
2 list_products List all products, optionally filtered by status
3 get_product Get detailed product info, environments, and recent runs
4 get_quality_score Get current quality score with component breakdown
5 run_playbook Execute a specific playbook against an environment
6 run_suite Run all playbooks for a product/environment
7 get_metrics Query APM metrics with baseline comparison
8 get_test_results Get recent test run results
9 suggest_tests Get test suggestions based on changed files
10 create_playbook Create a new test playbook
11 get_quality_report Generate a comprehensive quality report
12 configure_alerts Configure alert rules for a product
13 get_deployments Get recent deployments with quality impact
14 explore_codebase Trigger codebase exploration to discover routes and journeys

register_product

Registers a new product and associates it with deployment environments.

Parameters

Name Type Required Description
name string yes Human-readable product name
repo_url string yes Git repository URL
environments object yes Map of env name to base URL
description string no Product description

Returns dictproduct_id, slug, name, repo_url, environments, description, status, quality_score, created_at


list_products

Parameters

Name Type Required Description
status string no Filter by active, paused, or archived

Returns list[dict] — each item contains product_id, slug, name, status, quality_score, environment_count, last_run_at


get_product

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug

Returns dictproduct_id, slug, name, repo_url, environments, endpoints, quality_score, recent_test_runs, created_at, updated_at


get_quality_score

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
environment string no Environment scope

Returns dictscore, test_health, performance_health, security_posture, accessibility, trend, recommendations


run_playbook

Parameters

Name Type Required Description
playbook_id_or_name string yes Playbook UUID or name
environment string no Target environment name
target_url string no Override base URL for this run

Returns dictrun_id, playbook_name, environment, status, results_summary, duration_ms, quality_score_impact, started_at


run_suite

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
environment string no Target environment (default: staging)
suite_type string no regression, smoke, full, security, accessibility (default: regression)

Returns dictrun_id, playbooks_executed, passed, failed, quality_score


get_metrics

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
endpoint_path string no Filter to specific endpoint
metric_type string no response_time, lcp, cls, availability, error_rate
hours integer no Lookback window in hours (default: 24)

Returns dictmetrics (list of {timestamp, value}), baseline, current_avg, trend


get_test_results

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
limit integer no Max results (default: 10)
status string no Filter by passed, failed, error, running

Returns list[dict] — each item: run_id, playbook_name, status, duration_ms, passed, failed, timestamp


suggest_tests

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
changed_files list[string] no Changed file paths from the current diff

Returns list[dict] — each item: playbook_name, reason, priority (high/medium/low), affected_journeys


create_playbook

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
name string yes Playbook name
steps list[dict] yes Ordered list of action dicts
assertions dict no Assertion rules
performance_gates dict no Performance thresholds (e.g. {"lcp_ms": 2500})

Returns dictplaybook_id, name, step_count, validation_errors, status, created_at


get_quality_report

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
environment string no Environment scope

Returns dictquality_score, trend_7d, trend_30d, test_summary, performance_summary, security_summary, accessibility_summary, top_issues, recommendations


configure_alerts

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
rules list[dict] yes Alert rule objects

Returns dictstatus, rules_configured, errors


get_deployments

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug
environment string no Filter by environment
limit integer no Max results (default: 10)

Returns list[dict] — each item: deployment_id, environment, commit_sha, url, quality_score_delta, test_results_summary, deployed_at


explore_codebase

Parameters

Name Type Required Description
product_id_or_slug string yes Product UUID or slug

Returns dictroutes, apis, forms, user_journeys


WebSocket

Real-time test execution streaming

1
WS /ws/{client_id}

Establishes a persistent WebSocket connection for real-time updates. The {client_id} can be any identifier you choose — it is used to route server-push messages back to the correct connection.

Connection example (JavaScript)

1
2
3
4
5
6
7
8
9
10
11
12
const ws = new WebSocket('ws://localhost:8765/ws/my-client-001');

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  console.log('Received:', msg);
};

// Subscribe to a product's events
ws.send(JSON.stringify({
  type: 'subscribe',
  product_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6'
}));

Client message types (sent from browser to server)

type Additional fields Description
ping Keepalive check; server replies with {"type": "pong"}
subscribe product_id Subscribe to events for a product

Server push message types (sent from server to browser)

type Additional fields Description
pong Response to ping
subscribed product_id Confirms subscription
test_progress run_id, progress Live test step progress during a run
quality_update product_id, score, delta Quality score changed
alert alert_id, severity, title Alert triggered
deployment deployment_id, commit_sha, environment Deployment event received

Test progress payload example

1
2
3
4
5
6
7
8
9
10
11
12
{
  "type": "test_progress",
  "run_id": "run-8f3a2b1c",
  "progress": {
    "step_index": 7,
    "step_name": "click #checkout-btn",
    "status": "passed",
    "duration_ms": 450,
    "total_steps": 14,
    "steps_completed": 7
  }
}