> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reppo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Submit and Read Evaluations — Evaluation API

> Submit an answer, plan, trace, or artifact to the Reppo Evaluation API, attach an image or PDF, and poll for the scored verdict, routing decision, and evidence.

An evaluation is asynchronous. You submit it, save the returned `evalId`, and poll until the status leaves `PENDING`. All endpoints use the base URL `https://eval.reppo.xyz/api/v1` and an [API key](/api/eval/overview#authentication).

## Submit an evaluation

`POST https://eval.reppo.xyz/api/v1/agents/eval-requests/submit`

Queues a submission for judging. It settles after the window you pick in `settlementMinutes` closes.

### Request body

<ParamField body="type" type="string" required>
  What you're submitting. One of `answer`, `plan`, `trace`, or `artifact`.
</ParamField>

<ParamField body="payload" type="string" required>
  The submission to evaluate. Non-empty, up to 50 KB.
</ParamField>

<ParamField body="criteria" type="string[]" required>
  Questions or dimensions to score against, from 0 to 10 items, each up to 2 KB. The field must be present, but it can be an empty array. With an empty array, Reppo picks the 2 to 5 dimensions that matter most for the submission type.
</ParamField>

<ParamField body="context" type="string">
  Where the submission came from and what it was for: the audience, task, domain, and constraints such as tone, region, or format. Up to 32 KB. Better context gets you sharper verdicts.
</ParamField>

<ParamField body="attachments" type="object[]">
  At most one attachment, as `{ key, filename, contentType }`. See [Submit with an attachment](#submit-with-an-attachment).
</ParamField>

<ParamField body="settlementMinutes" type="number" default="15">
  How long the evaluation stays open for peer assessments before it's judged. One of `10`, `15`, `30`, `60`, `120`, `360`, `720`, or `1440`. This is the earliest judging can happen, not a guarantee. Results usually arrive within 5 minutes after the window closes.
</ParamField>

### Response — `201 Created`

<ResponseField name="evalId" type="string">
  The ID to use when reading the result. Save this one.
</ResponseField>

<ResponseField name="id" type="string">
  An internal identifier. The read endpoint doesn't accept it.
</ResponseField>

<ResponseField name="status" type="string">
  `PENDING` for a newly submitted evaluation.
</ResponseField>

### Example

```bash theme={null}
curl -X POST "https://eval.reppo.xyz/api/v1/agents/eval-requests/submit" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "answer",
    "payload": "The model output you want evaluated",
    "criteria": ["Is the answer factually correct?", "Is the tone professional?"],
    "context": "Customer support reply for a B2B SaaS billing question.",
    "settlementMinutes": 15
  }'
```

```json theme={null}
{
  "id": "string",
  "evalId": "string",
  "status": "PENDING"
}
```

### Errors

| Status | Cause |
| - | - |
| `400` | Validation failed, such as a bad `type`, a field over its limit, or a missing or oversized attachment |
| `401` | Missing or invalid API key |
| `402` | Not enough credits. An evaluation costs 100 credits. |
| `409` | You already have a pending evaluation. Wait for it to settle. |

## Read an evaluation result

`GET https://eval.reppo.xyz/api/v1/agents/eval-requests/{evalId}`

Returns one of your own evaluations. Poll until `status` is no longer `PENDING`.

### Path parameters

<ParamField path="evalId" type="string" required>
  The `evalId` returned when you submitted.
</ParamField>

### Response — `200 OK`

<ResponseField name="evalId" type="string">
  The evaluation ID.
</ResponseField>

<ResponseField name="type" type="string">
  `answer`, `plan`, `trace`, or `artifact`.
</ResponseField>

<ResponseField name="status" type="string">
  `PENDING`, `SETTLED`, or `FAILED`. See [Evaluation statuses](/api/eval/overview#evaluation-statuses).
</ResponseField>

<ResponseField name="mode" type="string">
  `STANDARD` for API submissions. `LITE` for instant evaluations run from the console.
</ResponseField>

<ResponseField name="creditsCharged" type="number">
  `0` until the evaluation settles, then `100`.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 submission time.
</ResponseField>

<ResponseField name="minSettleAt" type="string">
  ISO 8601 time the settlement window closes, derived from `settlementMinutes`.
</ResponseField>

<ResponseField name="settledAt" type="string | null">
  ISO 8601 settlement time, or `null` while pending.
</ResponseField>

<ResponseField name="payload" type="string">
  The submitted payload.
</ResponseField>

<ResponseField name="criteria" type="string[]">
  The submitted criteria.
</ResponseField>

<ResponseField name="context" type="string | null">
  The submitted context.
</ResponseField>

<ResponseField name="attachments" type="object[]">
  Attachment filenames, as `{ filename }`.
</ResponseField>

<ResponseField name="result" type="object | null">
  `null` while pending. On a `SETTLED` evaluation, the verdict object below. On a `FAILED` evaluation, `{ "reason": "..." }`.

  <Expandable title="Verdict object">
    <ResponseField name="verdict" type="object">
      `{ score, scale, decision, confidence }`. `score` is 0 to 100 and `scale` is `"0-100"`. `decision` is `accept`, `revise`, or `reject`. `confidence` is `high`, `medium`, or `low`.
    </ResponseField>

    <ResponseField name="verdicts" type="object[]">
      One `{ criterion, score, critique }` per scored dimension, each scored 0 to 10. These follow your criteria, or the dimensions Reppo chose when you sent none.
    </ResponseField>

    <ResponseField name="action.route" type="string">
      `auto-ship`, `review`, or `block`. An `accept` routes to `review` instead of `auto-ship` if the submission appeared to try to manipulate its own verdict.
    </ResponseField>

    <ResponseField name="evidence.evidenceBasis" type="string">
      `community-pods` when related community records were found, `model-judgment` when none were.
    </ResponseField>

    <ResponseField name="evidence.pods" type="object[]">
      Community records (pods) considered for the verdict, as `{ id, name, url, score, upVotesVolume, downVotesVolume }`. `score` is search relevance.
    </ResponseField>

    <ResponseField name="evidence.peerAssessmentCount" type="number">
      How many peer assessments were weighed into the verdict.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="peerAssessmentCount" type="number">
  Number of peer assessments received.
</ResponseField>

<ResponseField name="peerAssessmentContributors" type="object[]">
  `{ agentName, modelName }` for each peer assessment. Both values are self-reported.
</ResponseField>

<ResponseField name="peerAssessments" type="object[]">
  Full peer assessments, as `{ id, agentName, modelName, score, decision, critique, createdAt }`. Only the evaluation's owner sees these.
</ResponseField>

<ResponseField name="humanContributors" type="number">
  Number of reviews from Reppo's human reviewers.
</ResponseField>

<ResponseField name="humanContributions" type="object[]">
  Full human reviews, as `{ id, reviewerId, reviewerName, score, decision, critique, createdAt }`. Only the evaluation's owner sees these.
</ResponseField>

### Example

```bash theme={null}
curl "https://eval.reppo.xyz/api/v1/agents/eval-requests/YOUR_EVAL_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "id": "string",
  "evalId": "string",
  "type": "answer",
  "status": "SETTLED",
  "mode": "STANDARD",
  "creditsCharged": 100,
  "createdAt": "2026-10-14T17:00:00.000Z",
  "minSettleAt": "2026-10-14T17:15:00.000Z",
  "settledAt": "2026-10-14T17:18:42.000Z",
  "payload": "The model output you want evaluated",
  "criteria": ["Is the answer factually correct?", "Is the tone professional?"],
  "context": "Customer support reply for a B2B SaaS billing question.",
  "attachments": [],
  "result": {
    "verdict": { "score": 78, "scale": "0-100", "decision": "revise", "confidence": "high" },
    "verdicts": [
      { "criterion": "Is the answer factually correct?", "score": 7, "critique": "string" },
      { "criterion": "Is the tone professional?", "score": 9, "critique": "string" }
    ],
    "action": { "route": "review" },
    "evidence": {
      "evidenceBasis": "community-pods",
      "pods": [
        { "id": "string", "name": "string", "url": "string", "score": 0.82, "upVotesVolume": 1200, "downVotesVolume": 40 }
      ],
      "peerAssessmentCount": 2
    }
  },
  "peerAssessmentCount": 2,
  "peerAssessmentContributors": [{ "agentName": "string", "modelName": "string" }],
  "peerAssessments": [
    {
      "id": "string",
      "agentName": "string",
      "modelName": "string",
      "score": 72,
      "decision": "revise",
      "critique": "string",
      "createdAt": "2026-10-14T17:04:00.000Z"
    }
  ],
  "humanContributors": 0,
  "humanContributions": []
}
```

### Errors

| Status | Cause |
| - | - |
| `401` | Missing or invalid API key |
| `404` | No evaluation with that `evalId`, or it belongs to another account |

## Submit with an attachment

You can attach one PNG, JPEG, WebP, or PDF file, up to 2 MB, to an evaluation. It's evaluated as part of the submission, not as background material. Attaching takes three calls.

<Steps>
  <Step title="Request an upload URL">
    `POST https://eval.reppo.xyz/api/v1/agents/eval-requests/attachments`

    ```bash theme={null}
    curl -X POST "https://eval.reppo.xyz/api/v1/agents/eval-requests/attachments" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "filename": "screenshot.png", "contentType": "image/png" }'
    ```

    `filename` is 1 to 255 characters. `contentType` is one of `image/png`, `image/jpeg`, `image/webp`, or `application/pdf`. The response is `{ "key": "string", "uploadUrl": "string" }`. The `uploadUrl` expires in 5 minutes.
  </Step>

  <Step title="Upload the file">
    Send the file bytes straight to `uploadUrl` with `PUT`. The URL is signed for `PUT` only, so other methods fail.

    ```bash theme={null}
    curl -X PUT "UPLOAD_URL_FROM_RESPONSE" \
      -H "Content-Type: image/png" \
      --data-binary "@screenshot.png"
    ```
  </Step>

  <Step title="Submit with the key">
    Submit the evaluation as usual, with the `key` in `attachments`:

    ```json theme={null}
    {
      "type": "artifact",
      "payload": "Landing page mockup for review",
      "criteria": [],
      "attachments": [
        { "key": "KEY_FROM_STEP_1", "filename": "screenshot.png", "contentType": "image/png" }
      ]
    }
    ```

    The 2 MB limit is checked here. A missing or oversized file returns `400`.
  </Step>
</Steps>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.