> ## 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.

# Create an action

> `type` is required and has no default, and it decides which other fields apply:

- `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.

`slug`, `categoryId` and `keywordIds` apply to `write_article` only; `fanoutQueryIds` to `write_article`, `update_article` and `add_prompt`. They are dropped rather than rejected on the other types. A missing or out-of-workspace target is a `400`. Actions are appended to the end of the internal ordering.

`shortDescription` is the line shown under the title in a list and is usually the only text anyone reads — lead with the evidence rather than restating the title. `description` is the fuller explanation shown when the action is opened, except on `write_article` where it is the generation brief.



## OpenAPI

````yaml https://api.rankspot.ai/docs-json post /v1/actions
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:
    post:
      tags:
        - Actions
      summary: Create an action
      description: >-
        `type` is required and has no default, and it decides which other fields
        apply:


        - `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.


        `slug`, `categoryId` and `keywordIds` apply to `write_article` only;
        `fanoutQueryIds` to `write_article`, `update_article` and `add_prompt`.
        They are dropped rather than rejected on the other types. A missing or
        out-of-workspace target is a `400`. Actions are appended to the end of
        the internal ordering.


        `shortDescription` is the line shown under the title in a list and is
        usually the only text anyone reads — lead with the evidence rather than
        restating the title. `description` is the fuller explanation shown when
        the action is opened, except on `write_article` where it is the
        generation brief.
      operationId: ActionsController_create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateActionDto'
      responses:
        '201':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionDto'
        '400':
          description: >-
            `action-title-already-exists` — the title is taken by another
            action. `action-slug-already-exists` — the slug is taken by an
            action or an article. `action-reference-not-found` — a target,
            category, keyword or fanout query id is not in this workspace.
            `action-target-occupied` — this type already has an open action for
            that target.
      security:
        - bearer: []
components:
  schemas:
    CreateActionDto:
      type: object
      properties:
        type:
          example: write_article
          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.
          allOf:
            - $ref: '#/components/schemas/ActionType'
        title:
          type: string
          example: How to Start a Blog in 2024
          description: What to do. Shown as the card title. Required for every type.
        shortDescription:
          type: string
          example: Cited in 6 ChatGPT answers — you are in none.
          description: >-
            The one line shown under the title in a list, and for most actions
            the only text anyone reads. Lead with the evidence and the numbers
            behind it, do not restate the title. Keep it to a single short
            sentence.
        description:
          type: string
          example: A comprehensive guide for beginners.
          description: >-
            For write_article this is the brief handed to the generator. For
            every other type it is the fuller explanation shown when the action
            is opened, so it can run to a short paragraph.
        additionalInstructions:
          type: string
          example: Focus on WordPress.
          description: >-
            Extra guidance. For update_article this carries the actual
            instruction, which is why every kind of article edit is one type
            rather than several.
        slug:
          type: object
          example: how-to-start-a-blog
          description: >-
            write_article only; dropped on other types. Slug for the article
            generated from this action. If omitted or null the slug is derived
            from the title at generation time. Validated, not rewritten, and
            must be unique across actions and articles.
        categoryId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            write_article only; dropped on other types. Category to file the
            article under.
        keywordIds:
          example:
            - 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            write_article only; dropped on other types. Tracked keywords to
            link, which broadens the article's semantic coverage.
          type: array
          items:
            type: string
        articleId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            update_article, publish_article and request_indexing only, and
            required for them. The article this is about, from GET /v1/articles.
            This is the same `articleId` the response returns.
        citationId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            get_cited, reply_thread and record_video only, and required for
            them. The cited page or thread this is about.
        backlinkId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            earn_link only, and required for it. The referring domain to go
            after.
        competitorId:
          type: string
          example: 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            track_competitor only, and required for it. The brand to start
            tracking.
        fanoutQueryIds:
          example:
            - 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
            - 6b3c1f2e-9d4a-4a7e-b2c1-5f0e8a7d3c94
          description: >-
            Optional. write_article, update_article and add_prompt only; dropped
            on other types. The fanout searches that justified this, from
            rankspot_list_ai_fanout_queries. Send the whole cluster, not one
            phrasing of it: engines ask the same thing a dozen ways and one
            article answers all of them. Unlike the fields above this is not a
            target and not exclusive with them, so send `keywordIds` too.
          type: array
          items:
            type: string
      required:
        - type
        - title
    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

````