> ## Documentation Index
> Fetch the complete documentation index at: https://rankspot.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update an action

> Edits an action's content — `title`, `slug`, `shortDescription`, `description`, `additionalInstructions`, `categoryId`, `keywordIds` — or its bookkeeping: `status` and `archived`. Passing `keywordIds` replaces the full set of linked keywords.

Content can only be edited while `status` is `new`; once an executor has started the action is locked and a content edit returns `action-locked`. Bookkeeping stays open: `archived` at any point, and `status` on anything that is not currently `in_progress` — a running generator is reading the row, so reopening or closing it returns `action-in-progress`.

`status: "processed"` stamps `completedAt` and marks the citation or backlink behind the action handled; `status: "new"` clears `completedAt`, puts that evidence back on the worklist and undoes a dismissal.



## OpenAPI

````yaml https://api.rankspot.ai/docs-json patch /v1/actions/{id}
openapi: 3.0.0
info:
  title: RankSpot Public API
  description: >-
    The RankSpot Public API gives you programmatic access to your workspace data
    — keywords, backlinks, competitors, planned actions, articles, and more.


    ## Authentication


    All endpoints require a Bearer API key in the `Authorization` header:


    ```

    Authorization: Bearer <your-api-key>

    ```


    Generate API keys from **Settings → API Keys** in the RankSpot dashboard.
    Each key is scoped to a single workspace.


    ## Pagination


    List endpoints return a consistent envelope:


    ```json

    {
      "data": {
        "total": 120,
        "offset": 0,
        "limit": 20,
        "count": 20,
        "items": [...]
      }
    }

    ```


    Use `offset` and `limit` query parameters to paginate. Default limit is
    **20**, maximum is **100**.


    ## Status codes


    | Code | Meaning |

    |------|---------|

    | 200  | Success |

    | 201  | Created |

    | 204  | No content (delete / unarchive) |

    | 400  | Validation error or business rule violation |

    | 401  | Missing or invalid API key |

    | 404  | Resource not found or belongs to another workspace |
  version: '1.0'
  contact: {}
servers:
  - url: https://api.rankspot.ai
    description: Production
security: []
tags:
  - name: AI Visibility
    description: >-
      How AI answer engines see your brand. Track prompts, read the answers
      ChatGPT, Perplexity and Google gave, and work through the pages they
      cited. Prompts are run on a daily schedule by RankSpot, so answers appear
      after the next run rather than on demand.
  - name: Articles
    description: >-
      AI-generated blog articles. Articles are created automatically when a
      `write_article` action is sent to generation — they cannot be created
      directly via the API.
  - name: Backlinks
    description: >-
      Backlinks discovered for your domain and your competitors' domains.
      Backlinks are auto-synced on a background interval and cannot be created
      via the API.
  - name: Categories
    description: Categories for organising actions and articles within your workspace.
  - name: Competitors
    description: >-
      Competitor domains tracked in your workspace. Once added, keywords and
      backlinks for each competitor are fetched asynchronously on a background
      sync interval.
  - name: Forum Opportunities
    description: >-
      Forum threads and community posts surfaced as potential link-building or
      engagement opportunities.
  - name: Keywords
    description: >-
      SEO keywords tracked in your workspace, enriched with search volume,
      competition, and AI-generated relevance scores.
  - name: People Also Ask
    description: >-
      "People also ask" questions discovered from search results for your
      tracked keywords.
  - name: Actions
    description: >-
      The SEO work planned for your workspace. Each action carries a `type`
      saying what kind of work it is and which target it points at — see `POST
      /v1/actions` for the full list. Only `write_article` can be turned into an
      article; the rest are a person's job. Create actions yourself or let
      RankSpot generate them.
  - name: Research
    description: >-
      Live lookups against the open web: a Google search and a page fetch. The
      only endpoints here that spend credits per call. Neither response reports
      what it cost — the charge is real, and your remaining balance is visible
      in the RankSpot dashboard. Returns 402 when the workspace is out of
      credits.
  - name: Search Console
    description: >-
      Google Search Console performance data — clicks, impressions, CTR, and
      average position for your connected property. Requires GSC to be connected
      from the RankSpot dashboard.
  - name: Workspace
    description: >-
      Who the workspace is: brand, domain, what the business does and who it
      sells to. Read this first — the rest of the API returns opportunities that
      only mean something in the context of a particular business.
paths:
  /v1/actions/{id}:
    patch:
      tags:
        - Actions
      summary: Update an action
      description: >-
        Edits an action's content — `title`, `slug`, `shortDescription`,
        `description`, `additionalInstructions`, `categoryId`, `keywordIds` — or
        its bookkeeping: `status` and `archived`. Passing `keywordIds` replaces
        the full set of linked keywords.


        Content can only be edited while `status` is `new`; once an executor has
        started the action is locked and a content edit returns `action-locked`.
        Bookkeeping stays open: `archived` at any point, and `status` on
        anything that is not currently `in_progress` — a running generator is
        reading the row, so reopening or closing it returns
        `action-in-progress`.


        `status: "processed"` stamps `completedAt` and marks the citation or
        backlink behind the action handled; `status: "new"` clears
        `completedAt`, puts that evidence back on the worklist and undoes a
        dismissal.
      operationId: ActionsController_update
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateActionDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionDto'
        '400':
          description: >-
            `action-locked` — content can only be edited while the action is
            `new`. `action-in-progress` — `status` cannot be changed while an
            executor is running. `action-title-already-exists`,
            `action-slug-already-exists` and `action-reference-not-found` apply
            here as they do on create.
        '404':
          description: Action not found or belongs to another workspace.
      security:
        - bearer: []
components:
  schemas:
    UpdateActionDto:
      type: object
      properties:
        title:
          type: string
          example: How to Start a Blog in 2024
        slug:
          type: object
          example: how-to-start-a-blog
          description: >-
            Optional slug for the article generated from this action. Pass null
            to clear it and fall back to deriving the slug from the title at
            generation time. Must already be a valid slug (lowercase letters,
            numbers and single hyphens) — it is validated, not rewritten. Must
            be unique across actions and articles.
        shortDescription:
          type: string
          example: Cited in 6 ChatGPT answers — you are in none.
          description: The one line shown under the title in a list.
        description:
          type: string
          example: A comprehensive guide for beginners.
        additionalInstructions:
          type: string
          example: Focus on WordPress.
        categoryId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        keywordIds:
          example:
            - 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          type: array
          items:
            type: string
        status:
          type: string
          enum:
            - new
            - processed
          example: processed
          description: >-
            Where the action stands. `processed` closes it and marks the page or
            link behind it handled; `new` reopens it and puts that page or link
            back on the worklist, undoing a dismissal too. `in_progress` is set
            by the executor, not here, and while an action is in it neither
            value is accepted: the generator is reading the row.
        archived:
          type: boolean
          example: true
          description: >-
            Take the action off the board without deciding it, which also hides
            the page or link behind it from the worklist. `false` puts both
            back. The row and its evidence are kept either way; nothing is
            deleted.
    ActionDto:
      type: object
      properties:
        id:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        type:
          example: write_article
          description: What kind of work this is.
          allOf:
            - $ref: '#/components/schemas/ActionType'
        title:
          type: string
          example: How to Start a Blog in 2024
        slug:
          type: string
          example: how-to-start-a-blog
          nullable: true
        shortDescription:
          type: string
          example: Cited in 6 ChatGPT answers — you are in none.
          nullable: true
          description: >-
            The one line shown under the title in a list. Null on actions
            created before this field existed.
        description:
          type: string
          example: A comprehensive guide for beginners.
          nullable: true
          description: >-
            The fuller explanation, shown when the action is opened. On
            `write_article` this is the brief handed to the generator instead.
        additionalInstructions:
          type: string
          example: Focus on WordPress.
          nullable: true
        status:
          example: new
          description: >-
            new: not started · in_progress: an executor is running · processed:
            finished. Same vocabulary as backlinks, citations and
            people-also-ask, with the extra middle state only actions can have.
          allOf:
            - $ref: '#/components/schemas/ActionStatus'
        completedAt:
          type: string
          nullable: true
          description: When the work finished.
        categoryId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          nullable: true
        articleId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          nullable: true
          description: >-
            The article this action produced (write_article) or edits
            (update_article).
        citationId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          nullable: true
          description: >-
            The cited page or thread, on get_cited and reply_thread. Null once
            the citation itself is gone, which does not remove the action.
        backlinkId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          nullable: true
          description: The referring domain to go after, on earn_link.
        competitorId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          nullable: true
          description: The brand to start tracking, on track_competitor.
        citation:
          nullable: true
          description: >-
            The cited page itself, on get_cited and reply_thread. Carries the
            `url` to open and the citation count the reason is built from.
          type: object
          allOf:
            - $ref: '#/components/schemas/ActionCitationDto'
        backlink:
          nullable: true
          description: >-
            The referring domain itself, on earn_link. `urlFrom` is the page
            carrying the competitor link.
          type: object
          allOf:
            - $ref: '#/components/schemas/ActionBacklinkDto'
        competitor:
          nullable: true
          description: The brand itself, on track_competitor.
          type: object
          allOf:
            - $ref: '#/components/schemas/ActionCompetitorDto'
        fanoutQueries:
          description: >-
            The fanout searches themselves, on the article types. Provenance
            rather than a target: they are what justified the work, not where it
            happens. A set, because engines phrase one intent many ways.
          type: array
          items:
            $ref: '#/components/schemas/ActionFanoutQueryDto'
        keywords:
          type: array
          items:
            $ref: '#/components/schemas/ActionKeywordDto'
        createdAt:
          format: date-time
          type: string
        updatedAt:
          format: date-time
          type: string
      required:
        - id
        - type
        - title
        - status
        - fanoutQueries
        - keywords
        - createdAt
        - updatedAt
    ActionType:
      type: string
      enum:
        - write_article
        - update_article
        - earn_link
        - get_cited
        - reply_thread
        - record_video
        - track_competitor
        - add_prompt
        - publish_article
        - request_indexing
        - other
      description: >-
        What kind of work an action is, and what else the body needs:


        - `write_article` — plan a piece of content, then call POST
        /v1/actions/:id/generate to write it. Requires no target.

        - `update_article` — any edit to an existing article, with the
        instruction in additionalInstructions. Requires `articleId`.

        - `earn_link` — go after a referring domain your competitors have.
        Requires `backlinkId`.

        - `get_cited` — get onto a page AI engines already cite. Requires
        `citationId`.

        - `reply_thread` — reply on a cited Reddit or Quora thread. Requires
        `citationId`.

        - `record_video` — make a video of your own, since you cannot be added
        to someone else's. Requires `citationId`.

        - `track_competitor` — start tracking a brand RankSpot discovered in AI
        answers. Requires `competitorId`.

        - `add_prompt` — track a question buyers ask that no existing prompt
        covers. Requires no target.

        - `publish_article` — push a finished article to the workspace
        integrations. Requires `articleId`.

        - `request_indexing` — ask Google to index a published page it has
        missed. Requires `articleId`.

        - `other` — anything you just want written down. Requires no target.
    ActionStatus:
      type: string
      enum:
        - new
        - in_progress
        - processed
      description: >-
        new: not started · in_progress: an executor is running · processed:
        finished. Same vocabulary as backlinks, citations and people-also-ask,
        with the extra middle state only actions can have.
    ActionCitationDto:
      type: object
      properties:
        id:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        url:
          type: string
          example: https://zapier.com/blog/best-screen-recorders/
        domain:
          type: string
          example: zapier.com
        title:
          type: string
          example: The 12 best screen recorders
          nullable: true
        isOwnDomain:
          type: boolean
          example: false
          description: The page is on your own domain.
      required:
        - id
        - url
        - domain
        - isOwnDomain
    ActionBacklinkDto:
      type: object
      properties:
        id:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        domainFrom:
          type: string
          example: ahrefs.com
        urlFrom:
          type: string
          example: https://ahrefs.com/blog/seo-tools/
          description: The page carrying the competitor link.
        domainFromRank:
          type: number
          example: 91
          nullable: true
        dofollow:
          type: boolean
          example: true
      required:
        - id
        - domainFrom
        - urlFrom
        - dofollow
    ActionCompetitorDto:
      type: object
      properties:
        id:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        name:
          type: string
          example: Ahrefs
        domain:
          type: string
          example: ahrefs.com
      required:
        - id
        - name
        - domain
    ActionFanoutQueryDto:
      type: object
      properties:
        id:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        query:
          type: string
          example: best screen recording software for mac 2026
      required:
        - id
        - query
    ActionKeywordDto:
      type: object
      properties:
        id:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
        keyword:
          type: string
          example: start a blog
      required:
        - id
        - keyword
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: JWT
      type: http

````