openapi: 3.2.0 info: title: Plainrouter Action Dry Run API version: 0.5.0 description: 'Operations tagged ActionDryRunApi across 2 of this provider''s published API definitions: dev-plainrouter-openapi.json, plainrouter-openapi.json. Each path carries the servers of the definition it was published in.' servers: - url: https://plainrouter.com/api/v1 description: Production security: - workspaceSecret: [] tags: - name: ActionDryRunApi paths: /agent/workspaces/{workspace}/actions/dry-run: post: operationId: actions.api.dry-run description: Preview policy decisions and execution diffs for the approved account without saving a proposal. A kill switch returns blocked policy decisions. summary: Preview actions tags: - ActionDryRunApi parameters: - name: workspace in: path required: true description: The workspace ID schema: type: integer requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ActionProposalInput' responses: '200': description: Evaluated dry-run preview. content: application/json: schema: $ref: '#/components/schemas/ActionDryRunRead' '401': description: Missing, invalid, revoked or expired credentials return error invalid_token and error_description. Missing principal permissions or an issuer whose current role no longer covers the key return error insufficient_scope and error_description. A management key returns message instead. content: application/json: schema: anyOf: - $ref: '#/components/schemas/AgentCredentialError' - $ref: '#/components/schemas/ErrorMessage' '403': description: A revoked or insufficient workspace grant returns error insufficient_scope and error_description. Missing creative.write permission returns message without a code. content: application/json: schema: anyOf: - $ref: '#/components/schemas/AgentCredentialError' - $ref: '#/components/schemas/ErrorMessage' '404': description: 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. content: application/json: schema: $ref: '#/components/schemas/ApiRouteNotFound' '422': description: Invalid input, account selection, evidence, parameters, targets, repeated management targets, missing staged assets or source ads, and invalid budget direction return message plus errors mapping field names to arrays of messages. Stable reason codes are prefixes of field messages, not an error.code property. content: application/json: schema: $ref: '#/components/schemas/ValidationError' '413': description: Oversized POST data returns message "The POST data is too large." before route authorization. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' '429': description: The shared API rate limit is exceeded; message is "Too Many Attempts." Retry-After gives seconds until a retry is allowed. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' headers: Retry-After: description: Seconds until the shared API rate limit allows another request. required: true schema: type: integer '500': description: An unexpected server or provider-read fault returns message "Server Error" when debug is disabled. content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' security: - workspaceActionKey: [] servers: - url: https://plainrouter.com/api/v1 description: Production components: schemas: ActionDryRunRead: type: object properties: dry_run: type: object properties: actions: type: array items: anyOf: - type: object properties: type: type: string enum: - 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 target_entity: type: object properties: type: type: string id: type: string name: type: string required: - type - id status: type: string enum: - evaluated policy_decision: type: string enum: - allow - require_approval - block policy_reasons: type: array items: type: string approval_required: type: boolean would_auto_execute: type: boolean diff: type: object properties: before: {} proposed: {} required: - before - proposed required: - type - target_entity - status - policy_decision - policy_reasons - approval_required - would_auto_execute - diff - type: object properties: type: type: string enum: - 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 target_entity: type: object properties: type: type: string id: type: string name: type: string required: - type - id status: type: string enum: - dry_run_unavailable reason: type: string required: - type - target_entity - status - reason required: - actions required: - dry_run title: ActionDryRunRead AgentCredentialError: type: object properties: error: type: string enum: - invalid_token - insufficient_scope error_description: type: string required: - error - error_description title: AgentCredentialError ActionProposalInput: properties: actions: minItems: 1 maxItems: 25 items: anyOf: - properties: type: enum: - increase_budget type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: new_daily_budget_minor: minimum: 1 type: integer type: object required: - new_daily_budget_minor rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - decrease_budget type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: new_daily_budget_minor: minimum: 1 type: integer type: object required: - new_daily_budget_minor rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - pause type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - resume type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - replace_creative type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - shift_spend type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - rollback type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - create_campaign type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - create_ad_set type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - create_ad type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - upload_asset type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: properties: staged_asset_id: maxLength: 255 pattern: ^stage_[a-f0-9]{40}$ type: string asset_type: enum: - image type: string filename: maxLength: 255 type: string content_sha256: pattern: ^[a-f0-9]{64}$ type: string mime_type: maxLength: 255 type: - string - 'null' size_bytes: minimum: 1 type: - integer - 'null' type: object required: - staged_asset_id - asset_type - filename - content_sha256 rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - adjust_budget type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: properties: new_daily_budget_minor: minimum: 1 type: integer type: object required: - new_daily_budget_minor rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - set_status type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: properties: status: enum: - active - paused type: string type: object required: - status rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - duplicate_ad_with_creative type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: properties: asset_id: maxLength: 255 pattern: ^(image|video):.+$ type: string status: enum: - paused type: string name_suffix: maxLength: 100 type: - string - 'null' type: object required: - asset_id - status rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale type: array rationale: maxLength: 4000 type: string idempotency_key: maxLength: 64 type: string evidence: minItems: 1 maxItems: 3 items: additionalProperties: false properties: source_tool: enum: - get_account_state - get_signal_health - get_performance - get-creative-library - staged-asset-manifest type: string fields_used: minItems: 1 maxItems: 50 items: maxLength: 255 type: string type: array action_index: minimum: 0 type: integer type: object required: - source_tool - fields_used type: array target_source: enum: - human_supplied type: string account_id: minimum: 1 type: integer workspace_id: minimum: 1 type: integer type: object required: - actions - rationale - idempotency_key - evidence - target_source title: ActionProposalInput ApiRouteNotFound: type: object properties: error: type: object properties: code: type: string enum: - api_route_not_found message: type: string resolution: type: string required: - code - message - resolution request: type: object properties: method: type: string path: type: string required: - method - path resources: type: object properties: documentation: type: string openapi: type: string required: - documentation - openapi required: - error - request - resources title: ApiRouteNotFound ValidationError: type: object properties: message: type: string errors: type: object additionalProperties: type: array items: type: string required: - message - errors title: ValidationError ErrorMessage: type: object properties: message: type: string required: - message title: ErrorMessage ActionDryRunRead_2: type: object properties: dry_run: type: object description: Complete projection rows are paged within 80,000 JSON bytes, accounting for both MCP representations. Defaults are bounded. Follow next_cursor with the same scope and filters. One oversized row is explicitly refused; fields are never silently clipped. properties: actions: type: array items: anyOf: - type: object properties: type: type: string enum: - 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 target_entity: type: object properties: type: type: string id: type: string name: type: string required: - type - id status: type: string enum: - evaluated policy_decision: type: string enum: - allow - require_approval - block policy_reasons: type: array items: type: string approval_required: type: boolean would_auto_execute: type: boolean diff: type: object properties: before: {} proposed: {} required: - before - proposed required: - type - target_entity - status - policy_decision - policy_reasons - approval_required - would_auto_execute - diff - type: object properties: type: type: string enum: - 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 target_entity: type: object properties: type: type: string id: type: string name: type: string required: - type - id status: type: string enum: - dry_run_unavailable reason: type: string required: - type - target_entity - status - reason next_cursor: type: - integer - 'null' truncated: type: boolean continuation: type: string total: type: integer required: - actions required: - dry_run title: ActionDryRunRead ActionProposalInput_2: properties: limit: description: Maximum complete result actions; the shared JSON byte budget can return fewer. default: 25 minimum: 1 maximum: 100 type: integer cursor: description: Continue using next_cursor. Read saved proposal actions with get_action_batch to avoid another write; dry runs repeat the same inputs. minimum: 0 type: integer actions: minItems: 1 maxItems: 25 items: anyOf: - properties: type: enum: - increase_budget type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: new_daily_budget_minor: minimum: 1 type: integer type: object required: - new_daily_budget_minor rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - decrease_budget type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: new_daily_budget_minor: minimum: 1 type: integer type: object required: - new_daily_budget_minor rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - pause type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - resume type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 pattern: ^[0-9]+$ type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - replace_creative type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - shift_spend type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - rollback type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - create_campaign type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - create_ad_set type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - create_ad type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false type: object rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - upload_asset type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: staged_asset_id: maxLength: 255 pattern: ^stage_[a-f0-9]{40}$ type: string asset_type: enum: - image type: string filename: maxLength: 255 type: string content_sha256: pattern: ^[a-f0-9]{64}$ type: string mime_type: maxLength: 255 type: - string - 'null' size_bytes: minimum: 1 type: - integer - 'null' type: object required: - staged_asset_id - asset_type - filename - content_sha256 rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - adjust_budget type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: new_daily_budget_minor: minimum: 1 type: integer type: object required: - new_daily_budget_minor rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - set_status type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: status: enum: - active - paused type: string type: object required: - status rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale - properties: type: enum: - duplicate_ad_with_creative type: string target_entity: additionalProperties: false properties: type: enum: - ad_account - campaign - ad_set - ad maxLength: 64 type: string id: maxLength: 128 type: string name: maxLength: 255 type: - string - 'null' type: object required: - type - id params: additionalProperties: false properties: asset_id: maxLength: 255 pattern: ^(image|video):.+$ type: string status: enum: - paused type: string name_suffix: maxLength: 100 type: - string - 'null' type: object required: - asset_id - status rationale: maxLength: 2000 type: string idempotency_key: maxLength: 255 type: string type: object required: - type - target_entity - params - rationale type: array rationale: maxLength: 4000 type: string idempotency_key: maxLength: 64 type: string evidence: minItems: 1 maxItems: 3 items: additionalProperties: false properties: source_tool: enum: - get_account_state - get_signal_health - get_performance - get_inventory_metrics - get-creative-library - staged-asset-manifest type: string fields_used: minItems: 1 maxItems: 50 items: maxLength: 255 type: string type: array action_index: minimum: 0 type: integer type: object required: - source_tool - fields_used type: array target_source: enum: - human_supplied type: string account_id: minimum: 1 type: integer workspace_id: minimum: 1 type: integer type: object required: - actions - rationale - idempotency_key - evidence - target_source title: ActionProposalInput securitySchemes: workspaceSecret: type: http description: Per-workspace Server secret. It authenticates only the Signals workspace represented by the credential. scheme: bearer sandboxCredential: type: http description: Short-lived Sandbox key issued by POST /sandbox/keys. scheme: bearer workspaceActionKey: type: http description: Workspace key with read-actions for reads or propose-actions for writes. Unbound keys select an available advertising account with account_id. scheme: bearer planWriter: type: http description: An OAuth agent or account-bound Workspace Key with write access and the plan-create grant. scheme: bearer workspaceInventoryKey: type: http description: Workspace read key with the get_inventory_metrics grant. Account-bound keys can read only their bound account. scheme: bearer planReader: type: http description: An OAuth agent or account-bound Workspace Key with read access to the approved ad account. scheme: bearer creativeWriter: type: http description: Workspace-bound write credential with a grant authorizing creative intake. scheme: bearer testReader: type: http description: A workspace principal with read tier and the launch.plans.index and launch.plans.show grants for this account. scheme: bearer testWriter: type: http description: A workspace principal with write tier and the launch.plans.store grant for this account. scheme: bearer ruleReader: type: http description: 'A workspace-scoped key with read ability and actions.rules.index or actions.rules.show access to the bound account. Send Accept: application/json.' scheme: bearer ruleWriter: type: http description: 'A workspace-scoped key with write ability and the actions.rules.store or actions.rules.update grant. Send Accept: application/json.' scheme: bearer agentContextKey: type: http description: Workspace key with read ability, ad-account.read permission and the agent.context grant. scheme: bearer agentContextOAuth: type: oauth2 description: OAuth access token for an active approved agent principal with mcp:use, ad-account.read and agent.context authorization. Authorization code with PKCE and device authorization tokens are accepted. This scheme applies only to agent context. flows: authorizationCode: authorizationUrl: https://plainrouter.com/oauth2/authorize tokenUrl: https://plainrouter.com/oauth2/token refreshUrl: https://plainrouter.com/oauth2/token scopes: mcp:use: Use the approved agent principal. x-refined-from: - dev-plainrouter-openapi.json - plainrouter-openapi.json x-action-types: - increase_budget - decrease_budget - pause - resume - replace_creative - shift_spend - rollback - create_campaign - create_ad_set - create_ad - upload_asset x-signed: true