---
title: "Update Actions"
method: POST
path: "/actions/update"
tags: ["Actions"]
---

# Update Actions

`POST /actions/update`

## Request

- Base URL: `https://api.peec.ai/customer/v1`
- URL: `https://api.peec.ai/customer/v1/actions/update`
- Auth: one of:
  - API key in header `X-API-Key`
  - API key in query parameter `api_key`
  - HTTP bearer

Rewrite the fields a customer owns, on actions they wrote or ones Peec generated. An edit is stored beside the generated wording rather than in it, so a regeneration cannot discard it. Only a customer's own action can change shape: the type and group of a generated one say what Peec found, and an item trying to move them lands in `rejected`. A field the item leaves out keeps what it held; `null` clears the ones that can be cleared, and an item naming no field at all is rejected rather than recorded as an edit. Ids the project publishes no action under are returned in `skipped` — the batch never fails as a whole. A content optimisation is reachable only on a project with content optimisation enabled; elsewhere its id is returned in `skipped`. A product page action is reachable only on a project with product page actions enabled, the same way.

## Request body

- object
  - `project_id` string: Required if using a company api key
  - `actions` object[], required
    - `action_id` string, uuid, required: The action to rewrite, from list_actions.
    - `description` object: What the action is for. `html` is the formatting the app's editor renders; `text` is what everything else reads.
      - `text` string, required
      - `html` string
    - `notes` object, nullable: Working notes kept beside the action. Null clears them.
      - `text` string, required
      - `html` string
    - `topic_id` string, nullable: Topic the action is scoped to, from the topics endpoint. Null clears it.
    - `prompt_ids` string[]: Prompts this action is meant to move, from the prompts endpoint. Replaces the whole list.
    - `steps` object[]: The work to do, replacing the whole step list.
      - `title` string, required: What to do, as one line.
      - `description` string: Detail below the step's own line.
      - `completed` boolean
      - `section` string: Heading this step sits under. Steps naming the same one are grouped together, in the order they first appear; steps naming none sit in the default list above every group.
    - `priority` 'none' | 'low' | 'medium' | 'high': How much the action matters. It fills the same impact bars a generated action fills from its predicted lift, which is what lets the two sort together.
    - `country_codes` string[], nullable: ISO 3166-1 alpha-2 markets the action is scoped to. Null means every market the project tracks.
    - `language_codes` string[], nullable
    - `tag_ids` string[]
    - `category` string, nullable
    - `assignee_user_id` string, nullable: The project member who owns the work. Null unassigns it.
    - `due_on` string, date, nullable: Calendar day in the project's timezone. Null clears it.
    - `repeat` object, nullable: How often the work comes round again. Completing an action you wrote opens its next round as a new `PENDING` action, due one interval after this one (or after the day it was completed, when no `due_on` is set), and this one stops repeating. Null makes it one-off.
      - `every` integer, required
      - `unit` 'day' | 'week' | 'month' | 'year', required
    - `time_range` '7d' | '28d' | '90d' | 'all', nullable: The window the action's own measurements are read over.
    - `title` string
    - `kind` 'CONTENT_OPTIMIZATION' | 'CONTENT_CREATION' | 'MENTION' | 'TECHNICAL' | 'PRODUCT_PAGE' | 'OTHER': What the work is. Only an action the customer wrote can change shape — a generated one keeps the type and group Peec found it under. One of: `CONTENT_OPTIMIZATION` (Content optimization), `CONTENT_CREATION` (Create content), `MENTION` (Improve a mention), `TECHNICAL` (Fix a technical issue), `PRODUCT_PAGE` (Improve a product page), `OTHER` (Something else).
    - `page_url` string: The page the action lands on. Empty means it names no page. On an owned-page kind this is also the page the action is measured against.

## Response `200`

Per-item results

- object: Per-item results
  - `updated` object[], required
    - `action_id` string, required
  - `skipped` object[], required
    - `action_id` string, required
    - `reason` 'not_found', required
  - `rejected` object[], required
    - `action_id` string, required
    - `reason` 'duplicate_id' | 'no_change' | 'invalid', required
    - `message` string, required

## Changes

- **2026-11-03** `9fdffdff48a5`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/peec/apis/peec-ai-customer-api/changes/actions/update/post.md)

---

[API](https://skmtc.dev/peec/apis/peec-ai-customer-api.md) - [All operations](https://skmtc.dev/peec/apis/peec-ai-customer-api/llms.txt) - [OpenAPI document](https://skmtc.dev/peec/apis/peec-ai-customer-api/revisions/9d774600c8eb?raw)
