---
title: "Upsert one test-case result with scores"
method: POST
path: "/api/v1/public/evaluation-runs/{run_id}/results"
tags: ["Offline Eval"]
---

# Upsert one test-case result with scores

`POST /api/v1/public/evaluation-runs/{run_id}/results`

## Request

- Base URL: `https://app.traceroot.ai`
- URL: `https://app.traceroot.ai/api/v1/public/evaluation-runs/{run_id}/results`
- Auth: HTTP bearer

Upsert one test-case result (and its scores). Idempotent on (run, test case).

## Path parameters

- `run_id` string, required

## Request body

- UpsertResultRequest: Upsert one test-case result. Idempotent on (``run_id``, ``test_case_id``). ``trace_id`` may be null now and set on a later call (out-of-order arrival). ``scores`` is genuinely optional and carries three distinct meanings, so the out-of-order flow (POST the result with its scores, then re-POST later just to attach the OTel ``trace_id``) cannot destroy them: absent → leave the existing scores untouched, ``[]`` → clear them, non-empty → replace them. Do not give this a ``default_factory=list``, which would collapse the first two cases. Every optional field is a *partial* update: a key the caller omits keeps its stored value, while an explicit null clears it. Sending ``scores`` replaces the result's scores (``[]`` clears them); omitting it leaves them alone.
  - `baseline_output` string, nullable
  - `candidate_output` string, nullable
  - `change` 'improved' | 'regressed' | 'unchanged', nullable
  - `cost` number, nullable
  - `duration_ms` integer, nullable
  - `expected_output` string, nullable
  - `input` string, required
  - `scores` ScoreInput[]
    - `bool_value` boolean, nullable
    - `error` string, nullable
    - `explanation` string, nullable
    - `numeric_value` number, nullable
    - `passed` boolean, nullable
    - `scorer_name` string, required
    - `scorer_version` string, required
    - `string_value` string, nullable
  - `status` 'passed' | 'failed' | 'errored' | 'not_scored', required
  - `task_error` string, nullable
  - `test_case_id` string, required
  - `trace_id` string, nullable

## Response `200`

Successful Response

- UpsertResultResponse
  - `evaluation_result_id` string, required

## Other responses

- `400`: Invalid request
- `401`: Authentication failed
- `404`: Not found
- `413`: Request body too large
- `422`: Validation error
- `503`: Authentication service unavailable

---

[API](https://skmtc.dev/traceroot/apis/traceroot-public-api.md) - [All operations](https://skmtc.dev/traceroot/apis/traceroot-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/traceroot/apis/traceroot-public-api/revisions/ce6aef96c0d6?raw)
