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

> ## Agent Instructions
> Evolve has two products behind one API key. Edith answers questions about an agent trajectory over HTTP: `POST https://api.evolvingmachines.ai/v1/decisions`. Evaluations run coding agents on tasks in cloud sandboxes, through the `evolve` CLI, the Python and TypeScript SDKs, or HTTP.
> A person creates the key at https://dashboard.evolvingmachines.ai/api-keys. Read it from `EVOLVE_API_KEY`; never ask for it in chat or write it to a file.
> Install the CLI with `npm install -g @evolvingmachines/evolve`, then confirm the connection with `evolve auth status`.
> The CLI carries the manual for its own version. `evolve skills get evals` prints the index and `evolve skills get evals <page>` prints one page, for example `evolve skills get evals cli-reference/run`. When the installed CLI is older than this site, follow the installed manual.
> Commands take `--help` for their options and `--json` for machine-readable output. Evaluations spend credits: start with one task and set `--max-trial-spend`.

# Jobs HTTP API

> Submit evaluations, follow and compare them, retry work, and manage sharing.

Create an Evolve job from dataset selectors and agent/model arms, then follow its trials until the job settles. The accepted job continues running after your HTTP connection closes.

## Create a job

Reuse [connection setup](https://docs.evolvingmachines.ai/api-reference/index.md#connect) and save this request as `job.json`:

```json job.json theme={"dark"}
{
  "datasets": [
    {
      "name": "deepswe",
      "version": "1.1",
      "task_names": ["anko-default-function-arguments"]
    }
  ],
  "agents": [
    {
      "name": "codex",
      "model_name": "gpt-6-luna"
    }
  ],
  "max_trial_spend_usd": 1,
  "retry": {
    "max_retries": 0
  }
}
```

```bash theme={"dark"}
curl -sS "$API/api/jobs" \
  -H "Authorization: Bearer $EVOLVE_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @job.json
```

Success returns `202 JobCreated`: a [Job](https://docs.evolvingmachines.ai/sdk-reference/types.md#job-fields) with `job_id` as an additional alias of `id`. Set `JOB_ID` to that id. For safe submission retries, use an [Idempotency-Key](https://docs.evolvingmachines.ai/api-reference/index.md#idempotent-job-submissions).

### Required inputs

| JSON field | Required fields and selection |
| - | - |
| `datasets` | Nonempty array; each entry requires `name`. Optional `version` pins a version; otherwise the active version is used |
| `datasets[].task_names` | Optional include globs |
| `datasets[].exclude_task_names` | Optional exclude globs, applied after inclusion |
| `datasets[].n_tasks` | Optional positive integer cap, applied after filtering |
| `agents` | Nonempty array; each entry requires `name` and `model_name` |
| `agents[].version` | Optional harness version; omitted resolves and records the latest version at job creation |
| `agents[].reasoning_effort` | Optional effort supported by the chosen model; omitted uses its default |
| `agents[].kwargs` | Optional object; supported inline harness settings go under `config` |
| `agents[].preset` | Optional `no-internet` or `pinned-context`, only when supported by the harness |
| `agents[].skills` | Optional skill reference array; see [skill inputs](https://docs.evolvingmachines.ai/sdk-reference/skills.md#pick-a-reference) |

Dataset names must be distinct. Built-in agent models must appear on that harness's `/api/meta` roster; registered agents accept their own model names. Unknown request fields are refused rather than ignored. See [full job input definitions](https://docs.evolvingmachines.ai/sdk-reference/methods/jobs.md#start) for nested schemas and supported harness settings.

### Run settings

| JSON field | Default and constraints |
| - | - |
| `job_name` | Optional label, at most 200 characters; omitted uses a UTC timestamp |
| `org` | Optional organization slug or id; defaults to your personal organization; membership required |
| `n_attempts` | Integer of at least 1; default 1 |
| `n_concurrent_trials` | Integer 1–150; default 4 |
| `max_trial_spend_usd` | Agent model-spend cap per attempt in USD, 0.000001–999999.999999, stored to six decimal places; default from `/api/meta` |
| `sandbox_provider` | Provider from `/api/meta` |
| `sandbox_credentials` | Optional stored or inline provider credentials; requires deployment support, otherwise `422 feature_unsupported`; see [your provider account](https://docs.evolvingmachines.ai/core-concepts/sandboxes.md#your-own-provider-account) |
| `retry` | Automatic retry policy below |
| `analyze` | Optional [analysis configuration](https://docs.evolvingmachines.ai/api-reference/analyses.md#analysis-configuration) to analyze trials as they settle; `trial_ids` is only accepted by the later manual analysis request |
| `system_log` | Boolean; default `false`; collect the sandbox's system log |
| `timeout_multiplier` | Positive number; default 1 |
| `agent_timeout_multiplier` | Positive number overriding the common multiplier for agent execution |
| `verifier_timeout_multiplier` | Positive number overriding it for verification |
| `agent_setup_timeout_multiplier` | Positive number overriding it for agent setup |
| `environment_build_timeout_multiplier` | Positive number overriding it for image preparation |
| `agent_env` | Nonempty objects are currently refused |
| `verifier_env` | String values for `REWARDKIT_JUDGE` and `REWARDKIT_MODEL` only |
| `secrets` | Optional stored references or inline values; see [secret attachment](https://docs.evolvingmachines.ai/api-reference/secrets.md#attach-and-delete) |

`max_trial_spend_usd` caps agent model spend for each attempt. `worst_case_spend_usd` multiplies that cap by the trial count and allowed attempts, including retries; it excludes separate judge and analysis spend. Those charges can add to the bill. There is no enforced job-wide cap. Read the [cost fields](https://docs.evolvingmachines.ai/sdk-reference/types.md#cost-and-statistics); an unmeasured cost is not evidence of free execution.

The optional `retry` object accepts:

| Field | Meaning |
| - | - |
| `max_retries` | Nonnegative integer; omitted uses the current default; `0` disables automatic retries |
| `include_exceptions` | String array; omitted, `null`, or `[]` adds no include restriction |
| `exclude_exceptions` | String array taking precedence over inclusion; omitted uses the default exclusions, while explicit `null` disables exclusions |
| `wait_multiplier` | Nonnegative number; default 1 |
| `min_wait_sec` | Nonnegative seconds; default 1 |
| `max_wait_sec` | Nonnegative seconds; default 60 |

See [run settings](https://docs.evolvingmachines.ai/sdk-reference/jobs.md#run-settings) for the default exclusions and retry behavior. This policy is separate from retrying a failed HTTP request.

## Read and compare

| Method and path | Input | Success |
| - | - | - |
| `GET /api/jobs` | Filters below | `200 JobPage` |
| `GET /api/jobs/{jobId}` | Job id | `200 Job` |
| `GET /api/jobs/{jobId}/trials` | Optional `status`, `task_name`, `dataset`, `failed_only`, `limit`, `cursor` | `200 TrialPage` |
| `GET /api/jobs/{jobId}/tasks` | Optional `limit`, `cursor` | `200 JobTaskRollupPage` |
| `GET /api/jobs/compare` | Required `ids`: 2–10 comma-separated job ids | `200 CompareResponse` |
| `GET /api/jobs/{jobId}/grep` | Required `q`; optional `type`, `limit`, `cursor` | `200 JobGrepPage` |
| `GET /api/jobs/{jobId}/download` | Terminal job id | `200`, `.tar.gz` archive |

```bash theme={"dark"}
curl -sS "$API/api/jobs/$JOB_ID/trials" \
  -H "Authorization: Bearer $EVOLVE_API_KEY"
```

The job list accepts `scope` (`my`, `shared`, `org`; default `my`) or `org` (slug/id), never both. Other optional filters are `kind` (`job`, `check`, `all`; default `job`), repeatable `status`, `agent`, `model`, and `sandbox_provider`, plus `dataset`, `is_regrade`, `uploaded`, and `search`. Sorting accepts `sortField=created` and `sortDirection=asc|desc` (default descending). Use [catalog pagination](https://docs.evolvingmachines.ai/api-reference/index.md#pagination).

Trial `status` filters accept repeated or comma-separated values from the [trial status vocabulary](https://docs.evolvingmachines.ai/sdk-reference/types.md#status-vocabulary). `failed_only` selects trials carrying exceptions, excluding cancelled trials, and combines with other filters. The list truncates exception messages to 2,000 characters; [trial detail](https://docs.evolvingmachines.ai/api-reference/trials.md) returns the full message.

Grep's `q` is a case-insensitive POSIX pattern of at most 512 characters; `type` is at most 100. Results group matches by trial, with the exact count and up to five sample events. Use a trial's trace endpoint to read all its matches.

## Follow progress

`GET /api/jobs/{jobId}/events` returns `200 text/event-stream`:

```bash theme={"dark"}
curl -N "$API/api/jobs/$JOB_ID/events" \
  -H "Authorization: Bearer $EVOLVE_API_KEY"
```

Each frame has `id` (sequence), `event` (type), and JSON `data`. Resume after the last sequence with `Last-Event-ID` or `?after=<seq>`. Heartbeat comments arrive every 15 seconds. `curl` does not reconnect automatically.

A `trial.settled` failure can be followed by `trial.retrying`; do not treat it alone as proof that automatic retries ended. `trial.retry_circuit_broken` explains why a retry was stopped. See [job event fields](https://docs.evolvingmachines.ai/sdk-reference/types.md#job-events).

## Change execution

| Method and path | Optional JSON body | Success |
| - | - | - |
| `POST /api/jobs/{jobId}/cancel` | No body | `200 Job` |
| `POST /api/jobs/{jobId}/resume` | `filter_error_types`: string array | `202 Job`; `200` on idempotent replay |
| `POST /api/jobs/{jobId}/retry` | `trial_ids`: nonempty string array, or `failed_only`: boolean | `202 Job`; `200` on idempotent replay |
| `POST /api/jobs/{jobId}/regrade` | `statuses`: trial-status array; `task_name`: string | `202 Job` |
| `POST /api/jobs/{jobId}/analyze` | [Analysis configuration](https://docs.evolvingmachines.ai/api-reference/analyses.md#analysis-configuration) | `202 Job` |

```bash theme={"dark"}
curl -sS -X POST "$API/api/jobs/$JOB_ID/cancel" \
  -H "Authorization: Bearer $EVOLVE_API_KEY"
```

Resume, retry, and regrade create new linked jobs; the original results remain unchanged. Uploaded jobs cannot be resumed, retried, or regraded.

Resume requires a terminal source. Its default selection includes `ScoringError`, `InfrastructureError`, `ApiUsageLimitError`, and `IncompleteTrialError`, plus stopped trials and still-queued trials of a cancelled job.

Retry with no body retries every trial of a terminal job. `failed_only: true` selects failed trials, excluding scored and cancelled trials. Explicit `trial_ids` can select settled trials while the source job is still running. Do not combine `trial_ids` and `failed_only`.

Regrade requires a terminal source with recorded verifier inputs and eligible trials. See [execution method details](https://docs.evolvingmachines.ai/sdk-reference/jobs.md#cancel-or-run-selected-work-again) for eligibility and linked-job result fields.

## Import recorded jobs

`POST /api/jobs/upload` accepts multipart data with exactly one `archive` (gzipped Harbor job directory) or public HTTPS `archive_url`. Optional `dataset` is `name` or `name@version` and links trial task names to that dataset.

```bash theme={"dark"}
curl -sS "$API/api/jobs/upload" \
  -H "Authorization: Bearer $EVOLVE_API_KEY" \
  -F 'archive=@job.tar.gz' \
  -F 'dataset=deepswe@1.1'
```

Success returns `202 JobImport`, not a job. Poll `GET /api/jobs/imports/{importId}` until `COMPLETED` or `FAILED`; completion provides `job_id`. `GET /api/jobs/imports` accepts `status`, `limit`, and `cursor`. Import statuses are `QUEUED`, `RUNNING`, `COMPLETED`, and `FAILED`.

The archive must contain `result.json` and `config.json` at its root. Imported rewards are retained. Reported cost stays separate from platform-metered cost. See [import fields](https://docs.evolvingmachines.ai/sdk-reference/types.md#job-imports) for skipped trials, task linkage, and failures.

Large uploads use the [resumable protocol](https://docs.evolvingmachines.ai/api-reference/datasets.md#resumable-uploads) with these job paths:

| Method and path | Input | Success |
| - | - | - |
| `POST /api/jobs/upload/uploads` | JSON: required `size`, `sha256`; optional `dataset` | `201 UploadSessionCreated` |
| `GET /api/jobs/upload/uploads/{uploadId}` | Upload id | `200 UploadSession` |
| `HEAD /api/jobs/upload/uploads/{uploadId}` | Upload id | `200`, offset headers |
| `PATCH /api/jobs/upload/uploads/{uploadId}` | Chunk bytes and required upload headers | `204`, new offset |
| `DELETE /api/jobs/upload/uploads/{uploadId}` | Upload id | `204`, no body |
| `POST /api/jobs/upload/uploads/{uploadId}/complete` | No body | `202 JobImport` |

## Share and delete

Share management and deletion require the creator. Team membership or an email share grants read access, not these operations.

| Method and path | Input | Success |
| - | - | - |
| `POST /api/jobs/{jobId}/share` | JSON: `link: true`, `emails: [...]`, or both | `200 JobShares` |
| `POST /api/jobs/{jobId}/unshare` | Same body selecting grants to revoke | `200 JobShares` |
| `GET /api/jobs/{jobId}/shares` | Job id | `200 JobShares` |
| `DELETE /api/jobs/{jobId}` | Terminal job id | `200 JobDeleteResult` |

```bash theme={"dark"}
curl -sS "$API/api/jobs/$JOB_ID/share" \
  -H "Authorization: Bearer $EVOLVE_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"link":true}'
```

Links are unlisted and read-only. Email sharing sends an invitation to each new address, with at most 50 email grants per job. Repeated sharing returns the existing grants. Revoking a link invalidates it; sharing again creates a new link.

Deletion permanently removes the job's trials and stored analysis results. Active analysis or derived regrade work can prevent deletion; regrade ids are not deleted through this route. See [sharing and deletion fields](https://docs.evolvingmachines.ai/sdk-reference/types.md#sharing-and-deletion).

## Errors

Creation can refuse an unready dataset (`409 version_not_ready`), an explicitly named failed task (`409 task_failed_to_build`), an unsupported task/provider combination (`422 provider_unsupported`), insufficient credits (402), or organization queue capacity (`429 quota_exceeded`). A bulk selection can exclude tasks whose builds failed; inspect `build_exclusions` on the accepted job.

Execution changes can return `job_not_terminal`, `trial_not_settled`, `job_uploaded`, or a code describing an empty eligible selection. Read the [job and trial error catalog](https://docs.evolvingmachines.ai/sdk-reference/error-codes.md#jobs-and-trials) before deciding whether to retry.


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