> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/developer/rest-api/train-and-manage-training-jobs.md).

# Train and Manage Training Jobs

You can start, cancel, and stop training jobs through the REST API. You can also star NAS (Neural Architecture Search) child models to mark your preferred architectures.

## Start a Training Job

{% tabs %}
{% tab title="REST API" %}
Kick off a training run on a dataset version:

```url
POST https://api.roboflow.com/:workspace/:project/:version/train
```

```bash
curl "https://api.roboflow.com/my-workspace/my-detector/3/train?api_key=$ROBOFLOW_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"model_type": "rfdetr-base"}'
```

Training runs asynchronously. The response confirms that the job was queued, not that it has finished.

The calling API key must have the `trainingJob:create` scope.
{% endtab %}
{% endtabs %}

### Why a Training Job Did Not Start

When a version cannot be trained, the request returns `400` (or `409` for a legacy single-model version) with a structured `error` object. The `code` is stable and the `message` states whether waiting will help, so a client polling the endpoint knows whether to retry or stop.

```json
{
  "error": {
    "type": "BadRequest",
    "code": "insufficient_split_images",
    "message": "Training has not started: ...",
    "splits": { "train": { "current": 1, "required": 2 } }
  }
}
```

| Category                                                   | Codes                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Transient (wait, then retry)                               | `version_generation_in_progress`, `dataset_rebalance_in_progress`                                                                                                                                                                                                                                                                                           |
| Terminal (fix the data, generate a new version)            | `version_generation_incomplete`, `version_generation_failed`, `version_has_no_images`, `version_missing_annotations`, `splits_missing_annotations`, `insufficient_split_images`, `insufficient_validation_images_for_nas`, `classification_train_set_degenerate`, `version_has_uploaded_model`, `invalid_model_type`, `LEGACY_VERSION_SINGLE_MODEL` (`409`) |
| Plan or credit gate (resolve on the workspace, then retry) | `train_not_enabled`, `insufficient_train_credits`, `train_quota_exhausted`, `accurate_train_not_available`, `sam3_not_available_for_plan`, `nas_not_available_for_plan`                                                                                                                                                                                     |

## Cancel a Training Job

{% tabs %}
{% tab title="REST API" %}
Cancel an in-progress training job. The job must be in a running or queued state.

```url
POST https://api.roboflow.com/:workspace/:project/:version/train/cancel
```

```bash
curl "https://api.roboflow.com/my-workspace/my-detector/3/train/cancel?api_key=$ROBOFLOW_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{}'
```

The request records the cancellation and reports what happened in the `outcome` field. `success` and `refund` are retained for backwards compatibility.

```json
{
  "outcome": "cancelled",
  "success": true,
  "refund": true
}
```

| `outcome`               | Meaning                                                                                                                             |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `cancelled`             | The job was cancelled. `refund` reports whether training credits were returned.                                                     |
| `pending`               | The cancellation was recorded and is being finalized. Poll the training status to confirm the terminal state. Safe to retry.        |
| `superseded`            | The run finished before the cancellation took effect, so the completed model stands. `status` carries the terminal state.           |
| `requires_confirmation` | The job is past the refund window, so nothing was cancelled. Resend with `{"continueIfNoRefund": true}` to cancel without a refund. |

Credits are refunded only within 30 minutes of the job starting. After that window a cancel needs `continueIfNoRefund: true` to proceed, and no refund is issued.

If there is no running job to cancel (it already finished or was cancelled), the endpoint returns `409 Conflict`:

```json
{
  "error": {
    "type": "Conflict",
    "message": "Cannot cancel non-running train job.",
    "code": "CANNOT_CANCEL"
  }
}
```

The calling API key must have the `trainingJob:create` scope.
{% endtab %}
{% endtabs %}

## Stop a Training Job (Early Stop)

{% tabs %}
{% tab title="REST API" %}
Request an early stop for a running training job. Unlike cancel, stop is idempotent and will return success even if the job has already stopped.

```url
POST https://api.roboflow.com/:workspace/:project/:version/train/stop
```

```bash
curl "https://api.roboflow.com/my-workspace/my-detector/3/train/stop?api_key=$ROBOFLOW_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{}'
```

Example success response:

```json
{
  "success": true
}
```

The calling API key must have the `trainingJob:create` scope.
{% endtab %}
{% endtabs %}
