---
title: "Record that a version went into an environment"
method: POST
path: "/api/projects/{projectId}/specs/{specId}/versions/{versionId}/promote"
tags: ["API Specs"]
---

# Record that a version went into an environment

`POST /api/projects/{projectId}/specs/{specId}/versions/{versionId}/promote`

## Request

- Base URL: `https://api.routebase.dev`
- URL: `https://api.routebase.dev/api/projects/{projectId}/specs/{specId}/versions/{versionId}/promote`
- Auth: API key in header `X-API-Key`

Tells Routebase which version an environment now serves. The intended order is
that your pipeline deploys first and then makes this call, so the pin reflects
what is actually running rather than what someone intended.

A call authenticated with an API key is recorded with source `cli`, which is how
a pipeline assertion is told apart from someone clicking in the UI. If the target
environment freezes versions, the promoted version becomes immutable here.

## Path parameters

- `ProjectId` string, uuid, required
- `SpecId` string, uuid, required
- `VersionId` string, uuid, required

## Headers

- `X-RB-Region` string

## Request body

- PromoteVersionRequest: Which environment a version was deployed to, and what that should make it visible to.
  - `environmentId` string, uuid, required: Environment the version was deployed to.
  - `publishTarget` 'internal' | 'public' | 'exportOnly': Who a published version is visible to.
  - `impactAcknowledged` boolean, nullable: Confirms you have seen the effect on dependent services. Send true to clear a promotion that was refused with 409 for that reason.

## Response `200`

The promotion was recorded.

- PromotionResult: What the promotion changed: the new pin, whether it froze the version, and where the pin came from.
  - `promotionId` string, uuid, required: Public id of this promotion record, which the audit trail refers to.
  - `environmentId` string, uuid, required: Public id of the environment the version went into.
  - `environmentName` string, required: Display name of that environment.
  - `versionId` string, uuid, required: Public id of the promoted version.
  - `versionNumber` string, required: Version label of the promoted version.
  - `frozeVersion` boolean, required: Whether this promotion made the version immutable.
  - `previousVersionNumber` string, nullable: What the environment pinned before, or null if this is the first promotion.
  - `source` 'manual' | 'cli' | 'gatewayDeployment', required: Where a version pin came from. A call authenticated with an API key is recorded as `cli`, which marks it as a pipeline assertion rather than a manual entry.
  - `isRollback` boolean, required: Whether the pin moved back to a version the environment served earlier.

## Other responses

- `400`: The request was malformed or failed validation.
- `401`: The API key is missing, invalid, expired or revoked. A US organization calling without `X-RB-Region: us` also lands here, because the request reached the wrong region.
- `403`: The key is valid but lacks the permission or the project scope for this call. A scoped key is also refused on organization level operations by design.
- `404`: The resource does not exist, or it belongs to another organization or project. Both cases answer the same way on purpose, so the API cannot be used to probe for foreign identifiers.
- `409`: The promotion is blocked. The most common reason is an unacknowledged impact on dependent services, which you clear by sending `impactAcknowledged`.
- `429`: The rate limit was exceeded. The `Retry-After` header gives the seconds to wait.

---

[API](https://skmtc.dev/routebase/apis/routebase-public-api.md) · [All operations](https://skmtc.dev/routebase/apis/routebase-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/routebase/apis/routebase-public-api/revisions/7187df489f27?raw)
