---
title: "Update an intern"
method: PATCH
path: "/interns/{internId}"
tags: ["Interns"]
---

# Update an intern

`PATCH /interns/{internId}`

Changes the intern name, description, instructions or model. Omitted fields stay unchanged. The request body is capped at 1048576 bytes and a larger body is refused with 413. A non-empty body must declare `Content-Type: application/json` or it is refused with 415. The API key selects the caller, workspace and visible interns. There is no default workspace fallback. Requests on regional hostnames such as `eu.openrouter.ai` are refused. [API key](/docs/api-reference/authentication) required.

## Path parameters

- `internId` string, required — ID of an intern visible to the authenticated API key.

## Request body

- UpdateInternRequest — Lifecycle settings to change. Omitted fields stay unchanged and null clears a field.
  - `description` string, nullable — New free-form description. Null clears it.
  - `instructions` string, nullable — New standing instructions. Null clears them.
  - `model` string, nullable — New OpenRouter model slug in `author/slug` form (an optional `:variant` suffix is accepted). Other shapes are refused with 400. Null restores the workspace default. Takes effect on the next provision: until then `GET` shows this configured model while chat chunks show the model the running intern reports.
  - `name` string — New intern name, unique per creator within the workspace.

## Response `200`

Updated intern.

- Intern — Public lifecycle state and settings for one intern.
  - `attached_vault_id` string, nullable, required — Vault the intern borrows from another intern, or null when it borrows none.
  - `created_at` string, required — ISO 8601 creation time.
  - `description` string, nullable, required — Free-form description.
  - `hostname` string, nullable, required — Public hostname the intern is reachable at, or null until provisioning has assigned one.
  - `id` string, required — Intern id.
  - `instructions` string, nullable, required — Standing instructions the intern boots with.
  - `last_failure_message` string, nullable, required — Why the last provisioning attempt failed, when status is failed.
  - `model` string, nullable, required — OpenRouter model slug the intern runs, or null for the workspace default.
  - `name` string, required — Intern name, unique per creator within a workspace.
  - `progress` object, nullable, required — Active provisioning step, or null once provisioning has settled.
    - `step_label` string, required — Human-readable label of the active provisioning step.
    - `step_number` integer, required — One-based index of the active step.
    - `total_steps` integer, required — Number of provisioning steps.
  - `status` 'awaiting_slack_install' | 'queued' | 'provisioning' | 'running' | 'failed' | 'stopped' | 'destroying' | 'destroy_failed', required — Lifecycle status.
  - `updated_at` string, required — ISO 8601 last update time.
  - `vault_id` string, nullable, required — Vault the intern owns, or null before it has been created.
  - `workspace_id` string, required — Workspace that owns the intern and scopes its secrets.

## Other responses

- `400` — The request body is invalid.
- `401` — Missing, unknown or provisioning API key.
- `403` — The key owner no longer has access, or the request used a regional hostname.
- `404` — The caller is outside the Intern API programme, the intern is hidden, or lifecycle writes are disabled.
- `408` — The request exceeded its route deadline. The deadline quoted in the message is the route's own, so it differs between operations.
- `409` — The new name is already taken by an intern in this workspace.
- `413` — The request body is larger than 1048576 bytes.
- `415` — The request body is non-empty and its Content-Type is not application/json.
- `500` — The request could not be completed. `metadata.reason` says whether to try again: `internal_error` is a transient failure and carries `metadata.retryable: true`, so the same request may be sent again, while `configuration_error` carries `retryable: false` because the next attempt reads the same missing binding or unusable stored credential.

## Changes

- **2026-09-21** `0ca3cbfb629d` — 1 info
  - added the non-success response with the status `415`
- **2026-09-21** `50d23050da7a` — 8 info
  - added the non-success response with the status `409`
  - added the optional property `error/metadata` to the response with the `400` status
  - added the optional property `error/metadata` to the response with the `401` status
  - added the optional property `error/metadata` to the response with the `403` status
  - …4 more
- **2026-09-19** `1212b12392a8` — 2 breaking
  - the `model` request property's minLength was increased from `0` to `1`
  - added the pattern `^[A-Za-z0-9~._:@+-]+\/[A-Za-z0-9~._:@+-]+$` to the request property `model`
- **2026-09-18** `c4cafb1919d1` — 7 breaking, 7 info
  - removed the required property `createdAt` from the response with the `200` status
  - removed the required property `lastFailureMessage` from the response with the `200` status
  - removed the required property `progress/stepLabel` from the response with the `200` status
  - removed the required property `progress/stepNumber` from the response with the `200` status
  - …10 more
- **2026-09-17** `c3b9702bd9d7` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/openrouterteam/apis/openrouter-api/changes/interns/:internId/patch.md)

---

[API](https://skmtc.dev/openrouterteam/apis/openrouter-api.md) · [All operations](https://skmtc.dev/openrouterteam/apis/openrouter-api/llms.txt) · [OpenAPI document](https://skmtc.dev/openrouterteam/apis/openrouter-api/revisions/0ca3cbfb629d?raw)
