---
title: "Update a book"
method: PATCH
path: "/api/v1/books/{bookId}"
tags: ["Books"]
---

# Update a book

`PATCH /api/v1/books/{bookId}`

## Request

- Base URL: `https://beyourcover.com`
- URL: `https://beyourcover.com/api/v1/books/{bookId}`
- Auth: HTTP bearer

Edits a book's details, as the app's edit form does, or hides it from the shelf. Free. Send only the fields to change. Covers generated later use the new details; existing covers do not change. Text fields pass the same moderation as `POST /api/v1/books`.

## Path parameters

- `bookId` string, uuid, required

## Request body

- BookUpdate: Send only the fields to change. `null` clears an optional field. The app's edit-form rules apply: a title is required, and an author is required except for Planner & Journal books.
  - `title` string
  - `author` string, nullable
  - `subtitle` string, nullable
  - `summary` string, nullable
  - `genre` string: A genre slug or canonical value, as in `POST /api/v1/books`. A new genre keeps the stored subgenre only when it belongs to that genre; otherwise the subgenre is cleared.
  - `subgenre` string, nullable: One of the genre's subgenres (see `GET /api/v1/templates`).
  - `target_audience` string, nullable
  - `planner_year` string, nullable
  - `visibility` 'default' | 'hidden': `hidden` takes the book off the shelf; nothing is deleted.

## Response `200`

The updated book.

- BookSummary
  - `bookId` string, uuid, required
  - `title` string, required
  - `author` string, nullable
  - `subtitle` string, nullable
  - `genre` string, required: Canonical genre value (e.g. `Science Fiction`).
  - `subgenre` string, nullable
  - `summary` string, nullable
  - `target_audience` string, nullable
  - `planner_year` string, nullable: Planner & Journal books only: the year on the cover.
  - `visibility` 'default' | 'hidden', required: `hidden` books are off the dashboard shelf and out of `GET /api/v1/books` unless `include_hidden=true`.
  - `source_type` 'generated' | 'external_wrap' | 'premade', required: `generated` = made in the generator or the API; `external_wrap` = an uploaded cover (External Cover Studio); `premade` = a bought premade cover.
  - `thumbnail_cover_id` string, uuid, nullable, required: The coverId that represents the book on the shelf: the newest cover marked `favorite`, else the newest cover. Null when the book has no covers.
  - `covers_count` integer, required: Every cover of the book, hidden ones included (the dashboard's "N covers").
  - `created_at` string, date-time, required

## Other responses

- `400`: `code` is one of: `invalid_body`, `unknown_fields`, `no_changes`, `missing_required_fields`, `invalid_field_type`, `field_too_long`, `unsupported_characters`, `invalid_field_value`, `invalid_genre`, `invalid_subgenre`, `content_policy_violation`.
- `401`: Missing/malformed API key, unknown or inactive key, or inactive subscription detected during credit checks. `code`: `unauthorized`.
- `403`: The API key is valid but its owner has no active enterprise subscription. `code`: `forbidden`.
- `404`: `code` is `book_not_found`.
- `500`: Server error. `code` is `book_update_failed` or `internal_error`.

---

[API](https://skmtc.dev/beyourcover/apis/beyourcover-partner-api.md) · [All operations](https://skmtc.dev/beyourcover/apis/beyourcover-partner-api/llms.txt) · [OpenAPI document](https://skmtc.dev/beyourcover/apis/beyourcover-partner-api/revisions/82ad2c7c8ede?raw)
