Live

Test Results API

Live accepts test execution evidence from CI pipelines and test runners. Results are stored in the graph, rolled up per requirement, and written back to the workbook's RTMify Verification column.

Using this path for production test?

ATE stations and ATP workflows use this same JSON contract. For the manufacturing and as-built framing, including serial-number and product-anchor guidance, see ATE / ATP Results.

Two ingestion paths

HTTP POST

Send a JSON payload to the local API endpoint. Best for CI pipelines, test runners, and scripts that run on the same machine as Live.

POST http://127.0.0.1:8000/api/v1/test-results

File-drop inbox

Drop JSON files into the inbox directory. Live polls every 5 seconds and ingests automatically. Best for tools that can write files but not make HTTP requests.

~/.rtmify/inbox/

Authentication

HTTP ingestion requires a bearer token. The token is stored at:

~/.rtmify/api-token

Include it in the Authorization header:

Authorization: Bearer <your-token>

The dashboard's Guide → MCP & AI tab shows your current token and lets you regenerate it. You can also regenerate it via the API:

POST /api/v1/test-results/token/regenerate

File-drop ingestion does not require a bearer token — it uses filesystem access control instead.

Payload structure

The payload is a JSON object describing a test execution. Both the HTTP and file-drop paths accept the same format.

{
  "execution_id": "ci-run-20260313-001",
  "executed_at": "2026-03-13T14:00:00Z",
  "serial_number": "UNIT-042",       // optional
  "executor": "pytest",              // optional
  "source": "ci/github-actions",    // optional
  "test_cases": [
    {
      "result_id": "result-001",
      "test_case_ref": "TG-007/TC-001",
      "status": "passed",
      "duration_ms": 142,
      "notes": "All assertions passed",
      "measurements": [],            // optional structured data
      "attachments": []              // optional file references
    },
    {
      "result_id": "result-002",
      "test_case_ref": "TG-007/TC-002",
      "status": "failed",
      "duration_ms": 89,
      "notes": "Expected 200, got 422"
    }
  ]
}
Field Required Description
execution_id Required Unique identifier for this test run. Used for idempotent replacement.
executed_at Required ISO 8601 timestamp of when the execution occurred.
serial_number Optional Physical unit or device identifier, for hardware/embedded test evidence.
executor Optional Name of the test framework or runner.
source Optional CI system or execution context label.
test_cases[].result_id Required Unique identifier for this individual test case result.
test_cases[].test_case_ref Required Reference to a test case in your Tests tab. Dangling refs are accepted as warnings.
test_cases[].status Required One of: passed, failed, error, blocked, skipped.
test_cases[].duration_ms Optional Execution time in milliseconds.
test_cases[].notes Optional Free-text notes or failure message.
test_cases[].measurements Optional Array of structured measurement objects for quantitative evidence.
test_cases[].attachments Optional Array of file references (logs, screenshots, etc.).

What happens on ingestion

  1. Validates the JSON payload structure
  2. Computes an execution-level rollup status from the individual test case statuses
  3. Creates or updates TestExecution and TestResult graph nodes
  4. Creates HAS_RESULT and EXECUTION_OF edges linking results to test cases
  5. Accepts dangling test_case_ref values as warnings rather than rejecting the request
  6. On the next workbook sync, computes requirement verification rollups and writes the RTMify Verification column

Execution rollup statuses

Rollup Meaning
passed All test cases in the execution passed.
failed At least one test case failed, errored, or was blocked.
partial Mixed results — some passed, some did not reach a concrete outcome.

Idempotency

Submissions are idempotent by execution_id. Re-sending the same execution ID replaces the previous results, unless a newer execution has already superseded it (returns 409).

File-drop inbox

Drop JSON files into ~/.rtmify/inbox/. Live polls every 5 seconds and processes them automatically.

~/.rtmify/inbox/
  processed/ # successfully ingested files moved here
  rejected/ # invalid or unprocessable files moved here

The inbox directory can be changed with --inbox-dir <path> at startup. The current inbox path is shown in the dashboard Guide → MCP & AI tab.

API error codes

Code Meaning
200 Ingestion successful.
401 Missing or invalid bearer token.
400 Invalid payload structure. Response body contains structured error detail.
409 Execution ID conflict — a newer execution has already superseded this ID.
413 Payload too large.