﻿# Sim Job Results

Once a SimC job reaches a terminal status, fetch its full result to get summary metrics, runtime info, and downloadable artifacts. Skip to the [examples](#examples) for code samples.

## Response

`GET /v1/simc/jobs/{jobId}/result`

Available once the job reaches a terminal status (`completed`, `failed`, `cancelled`, or `timed_out`). Requests before a terminal status will return `409` with code `result_not_ready`.

If the job is terminal but produced no result payload (for example, an early failure), the response is `422` with code `result_unavailable`.

View in full in [API Reference](/docs/api-reference#tag/simc/GET/v1/simc/jobs/{id}/result).

### Job Fields

Top-level fields describe the job itself, such as its status, runtime, and the build that ran it.

**`id`** _(string)_

Job ID.

**`status`** _(enum)_

Terminal status of the job.

`completed` | `failed` | `cancelled` | `timed_out`

**`priority`** _(enum)_

Effective priority the job ran at.

`background` | `standard` | `high`

**`createdAt`** _(string | null)_

When the job was submitted.

**`startedAt`** _(string | null)_

When the job began executing. Null when the job never started.

**`completedAt`** _(string | null)_

When the job reached a terminal status.

**`cancelRequestedAt`** _(string | null)_

When a cancel was requested. Null when no cancel has been requested.

**`errorCode`** _(enum | null)_

Machine-readable error code for the terminal state. Null when the job completed successfully.

`execution_interrupted` | `execution_timeout` | `execution_failed` | `build_unavailable` | `simulation_error` | `queue_timeout` | `input_invalid` | `insufficient_credits` | `user_cancelled` | `internal`

**`statusReason`** _(string | null)_

Human-readable explanation paired with `errorCode`.

**`simcExitCode`** _(string | null)_

SimC process exit code.

**`retentionDays`** _(number | null)_

Number of days artifacts are retained after `completedAt`. After this window, artifact endpoints return `410`.

**`metadata`** _(object | null)_

Opaque metadata echoed back exactly as submitted.

**`runtime.simDurationMs`** _(number | null)_

SimC process wall-clock time in milliseconds. Excludes setup and teardown time. Null if the sim did not start.

**`runtime.totalDurationMs`** _(number | null)_

Total wall-clock time from job start to completion (milliseconds). Includes sim execution, artifact generation, and post-processing.

**`runtime.creditsConsumed`** _(number | null)_

Credits charged for this job, including any priority fee. `0` for terminal jobs with no billable work.

**`runtime.priorityFeeCredits`** _(number)_

Priority surcharge included in `creditsConsumed`. `0` for jobs submitted at `standard` or `background`; otherwise the `high`-priority fee in effect at submission time.

**`runtime.vcpus`** _(number | null)_

vCPUs used for this job.

**`runtime.ceiling.runtimeSeconds`** _(number | null)_

The runtime ceiling that applied to this run, in seconds.

**`runtime.ceiling.queueSeconds`** _(number | null)_

The queue timeout ceiling that applied to this run, in seconds.

**`retried`** _(boolean)_

True if this job was retried automatically because of a platform error. The response reflects the latest retry attempt.

**`build.id`** _(string)_

Build ID. `GET /v1/simc/builds/{id}` returns the full build record.

**`build.channel`** _(enum)_

SimC build channel this job ran on.

`nightly` | `weekly` | `latest`

**`build.commit`** _(string)_

Git commit hash of the SimC source used for this build.

**`build.ci`** _(object | null)_

Compact upstream CI summary (status and failure count) for this commit. Null when CI data is unavailable.

**`links.share`** _(string)_

URL to a hosted page for this job. Once the job is terminal, renders the full HTML summary. The page does not auto-refresh today. Returns `404` after retention expires.

**`links.manifest`** _(string)_

URL to the manifest JSON. Returns `404` after retention expires.

### Result

The `result` block carries the sim's actual output, such as the summary metrics for the main actor, multistage details, and references to downloadable artifacts.

**`result.summary`** _(object | null)_

Summary metrics for the run. Null when no summary was produced (for example, a failed job).

**`result.summary.metric`** _(enum)_

Primary metric used for ranking.

`dps`

**`result.summary.mainActor`** _(object | null)_

Result for the headline actor (selected by SimC's `profileset_main_actor_index` directive, default `0`). When profileset results are available, this object also carries a `profilesets` block for the sweep over this actor. For multi-player sims using `copy=` or `set=`, per-player results for the remaining actors are in the JSON artifact.

**`result.summary.mainActor.name`** _(string)_

Actor name as defined in the profile.

**`result.summary.mainActor.mean`** _(number)_

Mean DPS across all iterations.

**`result.summary.mainActor.mean_error`** _(number)_

Standard error of the mean.

**`result.summary.mainActor.mean_stddev`** _(number)_

Standard deviation of per-iteration DPS.

**`result.summary.mainActor.profilesets`** _(object)_

Profileset sweep results scoped to this actor. Omitted when no profileset results are available, either because the input declared no profilesets or because none were produced.

**`result.summary.mainActor.profilesets.count`** _(number)_

Total number of profilesets in the sim result. When this exceeds the length of `results`, the array was truncated to the top 200 entries by DPS. The full set is available in the JSON artifact.

**`result.summary.mainActor.profilesets.results`** _(array)_

Profileset sweep entries, ranked by DPS (highest first). Truncated to the top 200 entries.

**`result.summary.multiStage`** _(object)_

Multistage execution metadata.

**`result.summary.multiStage.enabled`** _(boolean)_

Whether multistage execution ran.

**`result.summary.multiStage.reason`** _(enum)_

Why multistage execution did or did not run.

`disabled_by_option` | `unsupported_stage_sensitive_directive` | `unsupported_copy_set_only` | `unsupported_mixed_profileset_copy_set` | `no_variants_in_input` | `unsupported_multi_actor` | `no_profileset_candidates` | `below_min_candidates` | `eligible_profileset_only`

**`result.summary.multiStage.stages`** _(array)_

Per-stage funnel for multistage execution, in execution order. Empty for single-pass runs. Each entry includes the stage number, label (`initial`, `intermediate`, `final`), number of profilesets executed, and number culled at the end of the stage.

**`result.artifacts`** _(array)_

Downloadable artifacts produced by this job. Includes the HTML report, JSON report, raw logs, and so on.

**`result.artifacts[].id`** _(string)_

Artifact ID.

**`result.artifacts[].url`** _(string)_

Stable public URL for downloading this artifact. Valid for the full retention window of the job.

**`result.artifacts[].kind`** _(string)_

Type of artifact (for example `html_report`, `json_report`, `stdout_log`).

**`result.artifacts[].mimeType`** _(string)_

MIME type of the artifact content.

**`result.artifacts[].stage`** _(number | null)_

Stage number for multistage execution artifacts (1-indexed). Null for single-run jobs or artifacts not associated with a specific multistage stage.

## Fetching artifacts

Each entry in `result.artifacts` carries a stable `url` you can download directly. To resolve a single artifact's URL by ID without refetching the full result, call `GET /v1/simc/artifacts/{artifactId}/url`; it returns `{ url }`.

## Retention

Artifacts and results stay available for `retentionDays` after `completedAt`. After that window:

- `GET /v1/simc/jobs/{jobId}/result` continues to return the job record, but `result.artifacts` is empty: expired entries are dropped from the array rather than returned with broken URLs.
- `GET /v1/simc/artifacts/{artifactId}/url` returns `410` with code `artifact_expired`.
- `links.share` and `links.manifest` return `404`.

If you need long-term storage, download the artifacts before retention expires.

## Examples

### Get DPS result

This example function uses the `summary` to print the player's DPS in the sim.

```javascript
const secretKey = process.env.SIMMIT_SECRET_KEY

async function printMainActorDps(jobId) {
  // Send GET request to result endpoint
  const response = await fetch(
    `https://api.simmit.com/v1/simc/jobs/${jobId}/result`,
    { headers: { Authorization: `Bearer ${secretKey}` } }
  )

  if (!response.ok) {
    throw new Error(`Result failed: ${response.statusText}`)
  }

  // Extract fields you need, see Response below
  const { result } = await response.json()
  const mainActor = result.summary?.mainActor

  if (!mainActor) {
    console.log('No actor result available')
    return
  }

  console.log('Player DPS:', mainActor.mean)
}

// Use a real job ID
await printMainActorDps('123')
```

### Get SimC JSON file

This example function finds the JSON report in `artifacts`, downloads it, and parses it into a variable you can build a report from.

```javascript
const secretKey = process.env.SIMMIT_SECRET_KEY

async function fetchSimcJson(jobId) {
  // Get the result payload, which lists downloadable artifacts
  const response = await fetch(
    `https://api.simmit.com/v1/simc/jobs/${jobId}/result`,
    { headers: { Authorization: `Bearer ${secretKey}` } }
  )

  if (!response.ok) {
    throw new Error(`Result failed: ${response.statusText}`)
  }

  const { result } = await response.json()

  // Find the JSON report artifact
  const jsonArtifact = result.artifacts.find(a => a.kind === 'json_report')

  if (!jsonArtifact) {
    throw new Error('No JSON report artifact found')
  }

  // The artifact URL is a public, stable download link, no auth header needed
  const reportResponse = await fetch(jsonArtifact.url)

  if (!reportResponse.ok) {
    throw new Error(`Download failed: ${reportResponse.statusText}`)
  }

  // Parse into a variable you can build a report from
  const report = await reportResponse.json()
  return report
}

// Use a real job ID
const report = await fetchSimcJson('123')
```

### Get SimC HTML report

This example function finds the HTML report in `artifacts` and prints its download link. The HTML report exists only if the job was submitted with `artifacts.html: true`.

```javascript
const secretKey = process.env.SIMMIT_SECRET_KEY

async function printHtmlReportLink(jobId) {
  // Get the result payload, which lists downloadable artifacts
  const response = await fetch(
    `https://api.simmit.com/v1/simc/jobs/${jobId}/result`,
    { headers: { Authorization: `Bearer ${secretKey}` } }
  )

  if (!response.ok) {
    throw new Error(`Result failed: ${response.statusText}`)
  }

  const { result } = await response.json()

  // Find the HTML report artifact
  const htmlArtifact = result.artifacts.find(a => a.kind === 'html_report')

  if (!htmlArtifact) {
    console.log(
      'No HTML report. Submit with `artifacts.html: true` to generate one'
    )
    return
  }

  console.log('HTML report:', htmlArtifact.url)
}

// Use a real job ID
await printHtmlReportLink('123')
```

### Get shareable link

This example function pretty-prints `links.share` (hosted HTML summary) and `links.manifest` (manifest JSON) for browser-friendly viewing. `links.share` renders the full summary once the job is terminal; `links.manifest` is populated then as well.

```javascript
const secretKey = process.env.SIMMIT_SECRET_KEY

async function printShareLinks(jobId) {
  // Send GET request to the job record endpoint
  const response = await fetch(`https://api.simmit.com/v1/simc/jobs/${jobId}`, {
    headers: { Authorization: `Bearer ${secretKey}` }
  })

  if (!response.ok) {
    throw new Error(`Job fetch failed: ${response.statusText}`)
  }

  const { links } = await response.json()

  console.log('Share page:', links.share)

  if (links.manifest) {
    console.log('Manifest:  ', links.manifest)
  }
}

// Use a real job ID
await printShareLinks('123')
```

### Get job details

This example function pretty-prints a job's total sim duration, credits consumed, vCPUs used, build commit, and metadata.

```javascript
const secretKey = process.env.SIMMIT_SECRET_KEY

async function printJobDetails(jobId) {
  // Send GET request to the job record endpoint
  const response = await fetch(`https://api.simmit.com/v1/simc/jobs/${jobId}`, {
    headers: { Authorization: `Bearer ${secretKey}` }
  })

  if (!response.ok) {
    throw new Error(`Job fetch failed: ${response.statusText}`)
  }

  const { status, runtime, build, metadata } = await response.json()

  console.log(`Status:           ${status}`)
  console.log(`Total duration:   ${runtime.totalDurationMs ?? '—'} ms`)
  console.log(`Sim duration:     ${runtime.simDurationMs ?? '—'} ms`)
  console.log(`Credits consumed: ${runtime.creditsConsumed ?? '—'}`)
  console.log(`vCPUs:            ${runtime.vcpus ?? '—'}`)
  console.log(`Build commit:     ${build?.commit ?? '—'}`)
  console.log(`Metadata:         ${JSON.stringify(metadata ?? {}, null, 2)}`)
}

// Use a real job ID
await printJobDetails('123')
```

---

_HTML version: https://simmit.com/docs/learning/simc-job-results · Full docs index: https://simmit.com/llms.txt_
