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

# Evaluation results

> Retrieve operator-completed evaluations and download PDF or XLSX reports.

After you submit documents, an operator runs the evaluation in the TruEnroll UI. You can
retrieve the results and download reports through the Partner API. These endpoints do not
start an evaluation. Do not add `evaluation` to an upload's `features` array.

The JSON response includes candidate, institution, and qualification details alongside the
evaluated results. You do not need to call `/extraction` first.

## Integration flow

1. Submit documents with `POST /cases` and retain the returned `caseId` and `uploadId`. For a case
   an operator created in TruEnroll, use its case ID or case number from `GET /cases`.
2. Arrange for an operator to evaluate the case in TruEnroll.
3. Poll `GET /cases/{id}/evaluation`, or use `case.evaluation.completed` as a prompt to fetch
   the current results. Keep polling as a fallback because this event is best-effort.
4. Download a credential report once its evaluation row has `status: "completed"`.
5. Poll `GET /cases/{id}/evaluation/combined` for the combined equivalency. Combined readiness
   is separate from the JSON evaluation status, so `/evaluation` can read `completed` while the
   combined equivalency is still `processing`.
6. Download a combined report once that endpoint reports `completed`.

All paths below are relative to `https://api.truenroll.com/partner/v1`.

## Get evaluation results

```text theme={null}
GET /cases/{id}/evaluation
```

<ParamField path="id" type="string" required>
  TruEnroll case ID, or the case number. See [Addressing a case](/partner-api/cases#addressing-a-case).
</ParamField>

<ParamField query="uploadId" type="string">
  Limit the response to credentials produced by this upload. Available immediately after upload.
</ParamField>

<ParamField query="credentialId" type="string">
  Limit the response to one credential in this case. Discover credential IDs from the case
  summary or evaluation response after classification.
</ParamField>

Omit both query parameters for the whole case. Send at most one; sending both returns `400`.
Both identifiers must be 24-character hexadecimal strings; hex digits are accepted in either
case. A missing upload or credential, including a deleted credential, returns `404`.

```bash theme={null}
curl "https://api.truenroll.com/partner/v1/cases/$CASE_ID/evaluation?uploadId=$UPLOAD_ID" \
  -H "x-api-key: $TRUENROLL_API_KEY"
```

### Status and targets

| Status | Meaning |
| - | - |
| `queued` | Evaluation has not been initiated |
| `processing` | Evaluation is a draft or requires further operator work |
| `completed` | Evaluated output is available |
| `not_applicable` | Envelope only. The selection has nothing to evaluate: no credentials, or only uncategorized ones |

`data.status` aggregates the credentials that can be evaluated: those past extraction and not
uncategorized. This is the same rule `case.evaluation.completed` uses, so the webhook never
arrives while this endpoint still reads `processing`. Every credential is still listed.

* `queued` when none of them has been evaluated yet. A credential still being extracted, or an
  upload still being classified, keeps the case `queued`, because evaluation work is still coming.
* `completed` when every one of them has a completed evaluation.
* `processing` otherwise. A credential with `evaluations: []` counts as still waiting and holds
  the aggregate at `processing`.

Inspect the credentials and rows you need before downloading. The case summary's processing
status is separate from evaluation status.
Each credential owns its `evaluations` array. An unfinished row contains only
`evaluationId`, `status`, `completedAt: null`, and `targetInstitute`. Completed rows also
contain `equivalency`, `courses`, and `note`. Reopening an evaluation returns it to
`processing` and hides the completed output until it is completed again.

`targetInstitute` is always present. `null` identifies the general evaluation. When target
institutes are configured, additional rows contain `{ "id": "...", "name": "..." }`.
Find the general row by `targetInstitute === null`; do not rely on array order. Before an
operator initiates evaluation, the array can be empty.

A credential can have more than one evaluation for the same target. Every endpoint returns the
same one: a completed evaluation if there is one, otherwise the first.

### Completed response

```json theme={null}
{
  "success": true,
  "message": "Evaluation retrieved",
  "meta": {},
  "data": {
    "id": "6712abcdef123456abcdef01",
    "externalId": "applicant-9876",
    "status": "completed",
    "caseNumber": 10482,
    "credentials": [
      {
        "credentialId": "6712abcdef123456abcdef02",
        "uploadId": "6712abcdef123456abcdef03",
        "candidate": { "fullName": "Asha Rao", "dateOfBirth": "05/14/1998" },
        "institution": { "name": "Anna University", "country": "India" },
        "qualification": {
          "name": "Bachelor of Technology",
          "educationLevel": "BACHELORS",
          "program": "Computer Science and Engineering",
          "programDurationYears": 4,
          "yearOfAdmission": 2016,
          "yearsOfAttendance": [2016, 2017, 2018, 2019, 2020],
          "dateOfAward": "06/30/2020"
        },
        "evaluations": [
          {
            "evaluationId": "6712abcdef123456abcdef04",
            "status": "completed",
            "completedAt": "2026-09-14T11:22:05.000Z",
            "targetInstitute": null,
            "equivalency": {
              "usEquivalency": "Bachelor of Science",
              "statement": "Equivalent to a Bachelor of Science in the United States.",
              "fieldOfStudy": "Computer Science",
              "evaluatedAs": "Bachelor of Technology",
              "gpa": { "weighted": "3.42", "unweighted": "3.50" },
              "totalCredits": 120,
              "creditUnit": "Semester Credits",
              "disclaimer": null
            },
            "courses": [
              {
                "courseId": "c1",
                "courseName": "Data Structures",
                "grade": "A",
                "point": 4,
                "credit": 3,
                "isRetaken": false,
                "isNonGradable": false,
                "isExcluded": false
              }
            ],
            "note": "Evaluator note"
          }
        ]
      }
    ]
  }
}
```

### Response fields

| Field | Meaning |
| - | - |
| `data.id`, `data.externalId` | TruEnroll case ID and your reference. `externalId` is `null` for a case created in the TruEnroll UI |
| `data.caseNumber` | The case number shown in TruEnroll and printed on reports. Carried by every case response and accepted as `{id}` on any case route |
| `credentialId`, `uploadId` | Credential ID and originating upload ID; `uploadId` can be `null` |
| `candidate` | Full name and date of birth (`MM/DD/YYYY`), with unavailable values returned as `null` |
| `institution` | Institution name and country name, with unavailable values returned as `null` |
| `qualification` | Qualification name, education level, program, duration, admission year, attendance years, and award date |
| `qualification.programDurationYears`, `qualification.yearOfAdmission` | Number when numeric, otherwise the source string, or `null` |
| `qualification.yearsOfAttendance` | Sorted, distinct year numbers; an empty array when unavailable |
| `qualification.dateOfAward` | `MM/DD/YYYY`, or `null`; the same source is named `dateOfIssue` in extraction results |
| `evaluationId` | ID used to select this evaluation's report |
| `completedAt` | Latest completion timestamp in ISO 8601, or `null` if unfinished or no completion timestamp is recorded |
| `equivalency.usEquivalency`, `equivalency.statement` | Evaluator-editable US equivalency and explanatory statement |
| `equivalency.fieldOfStudy` | Normalized field of study; it can differ from the transcript's specialization in extraction results |
| `equivalency.evaluatedAs` | Qualification description used for evaluation |
| `equivalency.gpa` | Weighted and unweighted GPA strings, each nullable |
| `equivalency.totalCredits` | Computed equivalent credits, or `null` |
| `equivalency.creditUnit` | `Carnegie Units` for secondary and higher-secondary credentials; `Semester Credits` otherwise |
| `equivalency.disclaimer` | Organization-specific disclaimer prefixed with `**`, or `null` |
| `courses` | Course ID and name, evaluated grade, grade point, and equivalent credit; unavailable values are `null` |
| `courses[].isRetaken` | Whether the source course is identified as retaken |
| `courses[].isNonGradable` | Whether the report treats the course as ungradable |
| `courses[].isExcluded` | Whether the evaluated course is excluded |
| `note` | Evaluator report note, or `null` |

Course grades, points, and credits are evaluated output. Use [extraction results](/partner-api/extraction)
if you also need the transcript's original values. This response does not include accreditation
findings, grade scales, or course codes. Combined equivalency has
[its own endpoint](#get-combined-equivalency-as-json).

## Download a credential report

```text theme={null}
GET /cases/{id}/evaluation/report/pdf
GET /cases/{id}/evaluation/report/xlsx
```

Send exactly one of these query parameters:

| Parameter | Selects |
| - | - |
| `evaluationId` | A specific evaluation, including a target-specific evaluation |
| `credentialId` | The credential's general evaluation (`targetInstitute: null`) |

Both IDs are 24-character hexadecimal strings and hex digits are accepted in either case.
Sending neither or both returns `400`. An evaluation not in the case returns `404`. An
existing unfinished evaluation returns `409`.

```bash theme={null}
curl "https://api.truenroll.com/partner/v1/cases/$CASE_ID/evaluation/report/pdf?evaluationId=$EVALUATION_ID" \
  -H "x-api-key: $TRUENROLL_API_KEY" \
  --output evaluation-report.pdf
```

The response is a binary attachment, not a JSON success envelope. PDF responses use
`application/pdf`; XLSX responses use
`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`.

TruEnroll names the file in the `Content-Disposition` header
(`attachment; filename="..."`, with spaces replaced by underscores). Read the filename from
that header rather than deriving one from the request.

## Get combined equivalency as JSON

```text theme={null}
GET /cases/{id}/evaluation/combined
```

Combined equivalency is the case's credentials evaluated together against one target, rather
than each on its own. This returns that result with the credentials it was built from.

<ParamField query="targetInstituteId" type="string">
  Select a target institute from an evaluation row's `targetInstitute.id`. Omit for the general
  combined equivalency. This is an institute ID, not an evaluation ID.
</ParamField>

Courses are omitted here; they are the bulk of the payload and `/evaluation` already carries
them. An unknown target institute returns `404`.

```bash theme={null}
curl "https://api.truenroll.com/partner/v1/cases/$CASE_ID/evaluation/combined" \
  -H "x-api-key: $TRUENROLL_API_KEY"
```

```json theme={null}
{
  "success": true,
  "message": "Combined evaluation retrieved",
  "meta": {},
  "data": {
    "id": "6712abcdef123456abcdef01",
    "externalId": "applicant-9876",
    "status": "completed",
    "pendingCredentialIds": [],
    "caseNumber": 10482,
    "targetInstitute": { "id": "6712abcdef123456abcdef09", "name": "State University" },
    "candidate": { "fullName": "Asha Rao", "dateOfBirth": "05/14/1998" },
    "combinedEquivalencies": [
      {
        "equivalency": "Equivalent to a Bachelor of Science in the United States.",
        "credentialIds": ["6712abcdef123456abcdef02", "6712abcdef123456abcdef05"]
      }
    ],
    "credentials": [
      {
        "credentialId": "6712abcdef123456abcdef02",
        "uploadId": "6712abcdef123456abcdef03",
        "institution": { "name": "Anna University", "country": "India" },
        "qualification": {
          "name": "Bachelor of Technology",
          "educationLevel": "BACHELORS",
          "program": "Computer Science and Engineering",
          "programDurationYears": 4,
          "yearOfAdmission": 2016,
          "yearsOfAttendance": [2016, 2017, 2018, 2019, 2020],
          "dateOfAward": "06/30/2020"
        },
        "evaluations": [
          {
            "evaluationId": "6712abcdef123456abcdef04",
            "status": "completed",
            "completedAt": "2026-09-14T11:22:05.000Z",
            "targetInstitute": { "id": "6712abcdef123456abcdef09", "name": "State University" },
            "equivalency": {
              "usEquivalency": "Bachelor of Science",
              "statement": "Equivalent to a Bachelor of Science in the United States.",
              "fieldOfStudy": "Computer Science",
              "evaluatedAs": "Bachelor of Technology",
              "gpa": { "weighted": "3.42", "unweighted": "3.50" },
              "totalCredits": 120,
              "creditUnit": "Semester Credits",
              "disclaimer": null
            },
            "note": "Evaluator note"
          }
        ]
      }
    ]
  }
}
```

### How this differs from `/evaluation`

| | `/evaluation` | `/evaluation/combined` |
| - | - | - |
| Scope | Every evaluation on the case | One target institute |
| Rows per credential | One per target | At most one, for the selected target |
| `courses` | Included | Omitted |
| `candidate` | Per credential | Once, on the envelope |
| Combined equivalency | Not included | `combinedEquivalencies` |

`combinedEquivalencies[].credentialIds` names the credentials a statement was derived from. It
is **empty when an operator wrote the statement by hand**, because a manual edit does not record
its sources. The combined report has the same gap, so treat a populated array as a bonus rather
than a guarantee.

### Poll this, not the report

| `status` | Meaning |
| - | - |
| `queued` | No credential on the case has a completed evaluation for this target yet |
| `processing` | Some credentials are still being evaluated for this target, or every one is and the combined equivalency is being produced |
| `failed` | Every credential is evaluated, but producing the combined equivalency failed. Download the combined report to retry |
| `completed` | `combinedEquivalencies` can be read |

A target is `completed` only when **every** credential that can be evaluated has a completed
evaluation for it and its combined equivalency has been produced. While it is `queued` or
`processing`, `pendingCredentialIds` lists the credentials still waiting on an evaluation. It is
`[]` once they are all evaluated.

This endpoint returns `200` with a status rather than the `409` the report routes return, which
gives you something to poll. Reading it never triggers combined equivalency generation, so
polling it has no side effects.

`/evaluation` and `/evaluation/combined` can disagree, and both are right: every credential can
be `completed` while the combined equivalency for a target is still `processing`. Check this
endpoint before downloading a combined report.

## Download a combined report

```text theme={null}
GET /cases/{id}/evaluation/combined-report/pdf
GET /cases/{id}/evaluation/combined-report/xlsx
```

<ParamField query="targetInstituteId" type="string">
  Select a target institute from an evaluation row's `targetInstitute.id`. Omit this
  parameter for the general combined report. This is an institute ID, not an evaluation ID.
</ParamField>

These routes serve a report only when [the combined equivalency JSON](#get-combined-equivalency-as-json)
would read `completed`:

| Combined `status` | Report route |
| - | - |
| `queued`, `processing` | `409` `Combined evaluation is not completed yet` |
| `failed` | Retries producing the combined equivalency, then serves the report if it succeeds. If it fails again: `409` `Combined evaluation failed; retry the download` |
| `completed` | The report |

There is no webhook for a failed combined equivalency, so watch for `failed` on the JSON
endpoint. An unknown target institute returns `404`. The response is a binary PDF or XLSX
attachment, named in the `Content-Disposition` header as above.

Poll [the combined equivalency JSON](#get-combined-equivalency-as-json) rather than retrying
these routes to find out when a target is ready.

```bash theme={null}
curl "https://api.truenroll.com/partner/v1/cases/$CASE_ID/evaluation/combined-report/xlsx" \
  -H "x-api-key: $TRUENROLL_API_KEY" \
  --output combined-evaluation-report.xlsx
```

<Note>
  Poll the JSON endpoint for progress. Each PDF request generates a fresh report with a new
  report ID and QR verification link. Repeated downloads can produce separately verifiable
  documents. Request reports when you need a download.
</Note>

## Errors

| HTTP status | Meaning |
| - | - |
| `400` | Invalid case or lookup ID, conflicting JSON filters, or missing/conflicting credential report selectors |
| `401` | Missing or invalid API key |
| `403` | API key is inactive or is not a partner key |
| `404` | Case is missing, deleted, or outside your organization; upload, credential, evaluation, or target is not in the case |
| `409` | Requested credential report is not ready (`Evaluation is not completed yet`), or the combined report is not ready or failed again on retry |

Both JSON endpoints return `200` with a current status rather than refusing an unfinished
result; only the report downloads return `409`. An evaluation has no `failed` status and there is
no `case.evaluation.failed` event. If operator work cannot be completed, the evaluation remains
`processing`. Only the combined equivalency can be `failed`.


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