---
title: "Update topics"
method: PATCH
path: "/api/businesses/{business_id}/topics"
tags: ["topics"]
---

# Update topics

`PATCH /api/businesses/{business_id}/topics`

## Request

- Base URL: `https://api.mymarky.ai`
- URL: `https://api.mymarky.ai/api/businesses/{business_id}/topics`
- Auth: HTTP bearer

Change many topics in one call: titles, on/off, and which category each is in.

Apply a whole topic table at once instead of one update_topic per row. Name
categories with `category_name`; list any that do not exist yet in
`new_categories` and they are created first. Each change succeeds or fails
on its own; read `results`.

Errors:
    401 authentication_required: API key or token is missing, invalid, or revoked.
    403 permission_denied: Your plan does not include API access, or this business is not in your org.
    404 resource_not_found: No business with that ID exists.
    422 validation_error: No changes, more than 100, or a change sends both category_id and category_name.
    429 rate_limit_exceeded: You sent too many requests this minute.

## Path parameters

- `business_id` string, required: A UUID identifier.

## Headers

- `Marky-Version` '2026-04-08' | '2026-07-17' | '2026-08-02' | '2026-08-04' | '2026-08-06'

## Request body

- UpdateTopicsRequest
  - `changes` TopicChange[], required: One entry per topic to change. Only the fields you send change.
    - `topic_id` string, uuid, required: The topic to change.
    - `title` string, nullable: New title.
    - `body` string, nullable: New description.
    - `enabled` boolean, nullable: Turn the topic on or off for generation.
    - `category_id` string, nullable: Move it to this category, by id.
    - `category_name` string, nullable: Move it to this category, by name (case-insensitive). Use instead of category_id.
  - `new_categories` NewCategoryRequest[], nullable: Categories to create first, so changes can name them.
    - `name` string, required: Category name. Reused if it already exists.
    - `color` string: Hex color shown in the app.
    - `description` string: Optional notes.

## Response `200`

Successful Response

- UpdateTopicsResponse
  - `categories_created` CategoryResponse[], required: Categories this call created (names that already existed are reused, not listed).
    - `id` string, required: Category ID
    - `business_id` string, required: Business this category belongs to
    - `name` string, required: Category name
    - `description` string, nullable: Category description or notes
    - `color` string, nullable: Hex color used to tag this category in the app (e.g. '#6366F1').
    - `created_at` string, required: When the category was created
    - `updated_at` string, nullable: Last update time
  - `results` TopicChangeResult[], required: One entry per change, in order.
    - `index` integer, required: Position of the change in your request.
    - `topic_id` string, required
    - `ok` boolean, required
    - `revision_id` string, nullable: Pass to revert_revisions to undo.
    - `topic` TopicResponse
      - `id` string, required: Topic ID
      - `business_id` string, required: Business this topic belongs to
      - `title` string, required: Topic title
      - `body` string, nullable: Topic description or notes
      - `enabled` boolean: Whether the topic is active for generation
      - `category_id` string, nullable: Category ID
      - `created_at` string, required: When the topic was created
      - `updated_at` string, nullable: Last update time
      - `revision_id` string, nullable: Id of the undo record this write created. Pass it to revert_revisions to put the record back exactly as it was before this call. Set only on the response to a write; null when you read the record.
    - `error` TopicChangeError
      - `status_code` integer, required
      - `message` string, required

## Other responses

- `400`: Bad request — the input was malformed or otherwise invalid.
- `401`: Authentication failed — the API key is missing or invalid.
- `403`: Forbidden — the key is valid but may not access this resource.
- `404`: Not found — no resource matches the id in the path.
- `422`: Validation error — one or more fields failed validation.
- `429`: Rate limited — retry after the window resets (see Retry-After).
- `500`: Server error — something failed on our side; retry or quote X-Request-Id.

---

[API](https://skmtc.dev/mymarky/apis/marky-public-api.md) · [All operations](https://skmtc.dev/mymarky/apis/marky-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mymarky/apis/marky-public-api/revisions/25aeacae455c?raw)
