---
title: "Execute a deployment plan"
method: POST
path: "/workspaces/{workspace}/admin/plans/{deployment_plan}/execute"
tags: ["DeploymentPlan"]
---

# Execute a deployment plan

`POST /workspaces/{workspace}/admin/plans/{deployment_plan}/execute`

## Request

- Base URL: `https://plainrouter.com/api/v1`
- URL: `https://plainrouter.com/api/v1/workspaces/{workspace}/admin/plans/{deployment_plan}/execute`
- Auth: HTTP bearer

Create or replay a governed Launch intent using the reviewed plan's review_version. Changed versions are refused before intent creation or staging.

## Path parameters

- `workspace` integer, required
- `deployment_plan` string, required

## Request body

- ExecuteDeploymentPlanRequest
  - `review_version` string, required
  - `intent_key` string, nullable

## Response `200`

Created or replayed Launch intent, including a blocked intent under the kill switch.

- LaunchIntentRead
  - `intent` object, required
    - `id` string, required
    - `status` 'approval_required' | 'approved' | 'executing' | 'verified' | 'failed' | 'drifted' | 'partial' | 'blocked', required
    - `action_batch_id` string, nullable, required
    - `policy_reasons` string[], required
    - `provider_object_ids` unknown, required
    - `campaign_id` string, nullable, required
    - `ad_set_id` string, nullable, required
    - `currency` string, nullable, required
    - `actions` object[], required
      - `id` string, required
      - `type` 'increase_budget' | 'decrease_budget' | 'pause' | 'resume' | 'replace_creative' | 'shift_spend' | 'rollback' | 'create_campaign' | 'create_ad_set' | 'create_ad' | 'upload_asset' | 'adjust_budget' | 'set_status' | 'duplicate_ad_with_creative' | 'duplicate_adset' | 'duplicate_ad_with_creative_v2', required
      - `verification_result` string, nullable, required
      - `external_ids` unknown, required

## Other responses

- `401`: Missing, invalid, revoked or expired credentials, a missing active principal, missing read scope or lost issuer authority return message. No error code is returned.
- `403`: Missing workspace, account, write access, execution scope or workspace grant returns message without a code.
- `404`: A missing or inaccessible workspace or plan, or a disabled Plan surface, returns error.code api_route_not_found with error.message, error.resolution, request and resources.
- `409`: An intent key bound to another plan returns error.code launch_submission_key_plan_mismatch and error.message.
- `413`: Oversized POST data returns message "The POST data is too large." before route authorization.
- `422`: Request validation returns message plus errors (including intent_key and review_version). Domain refusals return error.code and error.message: plan_changed_since_review ("This plan changed since you reviewed it. Reload and review the latest plan before submitting."), deployment_plan_not_executable, creative_not_ready, creative_bytes_unavailable, launch_video_upload_unavailable, ad_set_daily_budget_invalid, ad_set_bid_amount_invalid, currency_mismatch, currency_unsupported, budget_invalid, deployment_plan_has_no_actions. Proposal input or evidence validation returns message plus field errors.
- `429`: The shared API rate limit is exceeded; message is "Too Many Attempts." Retry-After gives seconds until a retry is allowed.
- `500`: An unexpected server or provider-read fault returns message "Server Error" when debug is disabled.
- `503`: The proposal could not be recorded: error.code proposal_not_recorded and error.message "The proposal could not be recorded. Retry." No proposal is committed. The bounded workspace transaction timed out: error.code workspace_lock_timeout and error.message "The workspace is busy. Retry the operation shortly." Retry-After is 1 second.

---

[API](https://skmtc.dev/plainrouter/apis/plainrouter-conversion-api.md) · [All operations](https://skmtc.dev/plainrouter/apis/plainrouter-conversion-api/llms.txt) · [OpenAPI document](https://skmtc.dev/plainrouter/apis/plainrouter-conversion-api/revisions/d071d4f4f05c?raw)
