# agent-versions

The organization's agent version policy per DTAP environment: follow the newest release, or hold a pinned version that moves by promotion.

**Amfelt REST API** · v1.13.0 · `https://api.amfelt.com`

---
### GET `/v1/orgs/{slug}/agent-version-policies` {#listagentversionpolicies}

**List the organization's agent version policies.**

Returns one agent version policy per DTAP environment of the organization. A policy is set once per environment for the whole organization: every project's environment of that type follows it. An agent serving several environments follows the strictest of their policies — the lowest pinned version wins — and the target each agent derives from them is computed at read time, never stored.

#### Parameters

| Name | In  | Required | Type | Description |
| ---- | --- | -------- | ---- | ----------- |
| `slug` | path | Yes | string | Slug of the organization. |

#### Responses

**200** — The organization's agent version policies.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `data` | [AgentVersionPolicy](#agent-version-policy)[] | Yes |  |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**404** — The specified resource was not found.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

### GET `/v1/orgs/{slug}/agent-version-policies/{environment_id}/evidence` {#getagentversionevidence}

**Read the evidence for promoting one environment's pin.**

Returns the evidence a promotion of this environment's pin to `version` would carry: the recorded runs of that version in lower environments. The promotion dialog reads it before its first submit; changeAgentVersionPolicy attaches the same evidence to its answer. Zero runs is valid evidence, shown as such.

#### Parameters

| Name | In  | Required | Type | Description |
| ---- | --- | -------- | ---- | ----------- |
| `slug` | path | Yes | string | Slug of the organization. |
| `environment_id` | path | Yes | string | The DTAP environment slug whose pin would move. |
| `version` | query | Yes | string | The version a promotion would pin. |

#### Responses

**200** — The recorded runs of the version in lower environments.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `environments` | [EnvironmentSlug](#environment-slug)[] | Yes | The DTAP environment slugs that ran the version, in promotion order. Examples: `["test","acceptance"]`. |
| `first_at` | [string null] | Yes | When the first of those runs started; null when there are none. |
| `last_at` | [string null] | Yes | When the last of those runs started; null when there are none. |
| `runs` | integer | Yes | Successful runs the version executed in lower environments. Examples: `12`. |


**400** — The request was malformed or failed validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**404** — The specified resource was not found.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

### POST `/v1/orgs/{slug}/agent-version-policies/{environment_id}/changes` {#changeagentversionpolicy}

**Change one environment's agent version policy.**

Requests a change to one environment's agent version policy: a pin move (a promotion to a newer version, or a rollback to an earlier one with `rollback: true`), a switch between `follow_latest` and `pinned`, or a new `settle_delay_minutes`.
A change to Production needs approval, whatever it changes, the settle delay included: the response is 202 with an approval request of kind `agent_version_policy_change`, and the policy changes only when that request is approved. A change to any other environment needs no approval: it is applied at once and the response is 200 with the applied policy. An environment has at most one pending request: a change while one is pending is refused with `approval_already_pending`.
A promotion (a change that moves `pinned_version` up) carries the evidence of the runs that version executed in lower environments: on a 200 in the policy's `evidence`, on a 202 in the approval request's `payload.evidence`. Evidence is shown, not required: a promotion with no recorded runs is refused with `evidence_unconfirmed` until it is resent with `confirm_without_evidence: true`. A rollback needs no evidence.

#### Parameters

| Name | In  | Required | Type | Description |
| ---- | --- | -------- | ---- | ----------- |
| `slug` | path | Yes | string | Slug of the organization. |
| `environment_id` | path | Yes | string | The DTAP environment slug whose policy changes. |

#### Request body _(required)_

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `confirm_without_evidence` | boolean | No | Confirms a promotion to a version with no recorded runs in lower environments. Without it such a promotion is refused with `evidence_unconfirmed`. |
| `mode` | [AgentVersionPolicyMode](#agent-version-policy-mode) | Yes |  |
| `pinned_version` | string | No | The version to pin. Required when `mode` is `pinned`, and must be absent when it is `follow_latest`. Examples: `5.2.0`. |
| `reason` | string | No | Why the change is made. When the change needs approval, it is carried on the approval request's `payload` and shown to the approver. It is not stored for a change that applies at once. Examples: `Ran clean in Acceptance for two weeks.`. |
| `rollback` | boolean | No | True when the change is a rollback: it pins a `pinned_version` lower than the environment's current target, which is its pin when `mode` is `pinned` and otherwise the newest release past its settle delay. The flag must match the change: `rollback: true` on a change that pins no lower version is refused with `rollback_not_lower`, and a lower `pinned_version` without it is refused with `rollback_unconfirmed`. A rollback needs no evidence, because the environment ran that version before. |
| `settle_delay_minutes` | integer | No | Minutes after a release is published before this environment's `follow_latest` agents act on it. Absent keeps the current delay. A change to it follows the same approval rule as any other change to this environment's policy. Examples: `60`. |


#### Responses

**200** — The change needed no approval and was applied.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `environment_id` | [EnvironmentSlug](#environment-slug) | Yes |  |
| `evidence` | [AgentVersionEvidence](#agent-version-evidence) | No |  |
| `mode` | [AgentVersionPolicyMode](#agent-version-policy-mode) | Yes |  |
| `pinned_version` | [string null] | Yes | The version agents of this environment hold. Set when `mode` is `pinned`, null when it is `follow_latest`. Examples: `5.1.3`. |
| `settle_delay_minutes` | integer | Yes | Minutes after a release is published before `follow_latest` agents act on it. Examples: `60`. |
| `updated_at` | string | Yes | When the policy last changed. |
| `updated_by` | string | Yes | Identifier of the account that last changed the policy, or `system` when the platform set it. Examples: `system`. |


**202** — The change needs approval. The body is the pending approval request; the policy is unchanged until it is approved.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `decided_at` | [string null] | No | When the request was approved or declined; null otherwise. |
| `decided_by` | [string null] | No | Identifier of the account that approved or declined the request; null while it is pending or once it expired. |
| `expires_at` | string | Yes | When a still-pending request becomes `expired`. |
| `id` | string | Yes | Approval request identifier. |
| `kind` | string | Yes | What is being approved. An open vocabulary, so a new kind needs no contract change. Examples: `agent_version_policy_change`. |
| `payload` | object | Yes | The kind-specific details of the request. |
| `requested_at` | string | Yes | When the request was made. |
| `requested_by` | string | Yes | Identifier of the account that made the request. |
| `self_approved` | boolean | Yes | True when the requester approved their own request, which is allowed only in an organization with exactly one owner or admin. |
| `state` | [ApprovalRequestState](#approval-request-state) | Yes |  |


**400** — The request was malformed or failed validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**401** — The request lacks valid credentials.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**403** — The caller is authenticated but not permitted to perform the request.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**404** — The specified resource was not found.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


**409** — The change was refused; the policy is unchanged.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `evidence` | [AgentVersionEvidence](#agent-version-evidence) | No |  |
| `message` | string | Yes | Human-readable explanation, safe to show an operator. Examples: `Pin 5.0.2 is below the version floor 5.1.0 that &lt;feature&gt; needs; pin 5.1.0 or later.`. |
| `reason` | string | Yes | Machine-readable refusal reason. `pin_below_floor` — `pinned_version` is below a version floor the api requires; `message` names the floor and the feature it gates. `evidence_unconfirmed` — the promotion's version has no recorded runs in lower environments; resend with `confirm_without_evidence: true` to proceed. `approval_already_pending` — this environment's policy already has a pending approval request; it must be approved, declined or expire before another change is requested. `rollback_not_lower` — the change says `rollback: true` but pins no version lower than the environment's current target. The flag and the change disagree, so nothing is applied: resend without `rollback`, or with a lower `pinned_version`. `rollback_unconfirmed` — the change pins a version lower than the environment's current target without `rollback: true`; resend with `rollback: true` to roll back. Valid values are: `pin_below_floor`, `evidence_unconfirmed`, `approval_already_pending`, `rollback_not_lower`, `rollback_unconfirmed`. Examples: `pin_below_floor`. |


**422** — The request was well-formed but failed semantic validation.

`application/json`

| Property | Type | Required | Description |
|---|---|---|---|
| `code` | string | Yes | Stable, snake_case token identifying the error condition. See ErrorCode for the api's canonical named vocabulary — this field is deliberately not restricted to it, since handlers may emit other ad-hoc codes not listed there (e.g. not_implemented). Examples: `invalid_argument`. |
| `field` | string | No | Optional hint identifying the request field the error refers to, in snake_case (e.g. "slug", "display_name", "token"). Set by handlers that validate multiple fields and want to enable field-targeted UX in clients. Absent when the error does not map to a single field. Examples: `slug`. |
| `message` | string | Yes | Human-readable description of the error. Examples: `limit must be between 1 and 100`. |


#### Security

bearer_jwt

---

