Skip to content

Campaign Books Service

Manage books within a campaign, including their notes and assets.

Campaign books organize your campaign content into chapters. Each book can contain multiple chapters, notes, and assets. Books are numbered sequentially and can be reordered using the renumber() method.

Usage

from vclient import books_service

books = books_service(campaign_id="CAMPAIGN_ID", on_behalf_of="USER_ID", company_id="COMPANY_ID")

Methods

CRUD Operations

Method Returns Description
get(book_id, *, include=None) CampaignBookDetail Get a book by ID, optionally embedding chapters, notes, or assets
create(BookCreate, **kwargs) CampaignBook Create a new book
update(book_id, BookUpdate, **kwargs) CampaignBook Update a book
delete(book_id) None Delete a book
renumber(book_id, number) CampaignBook Change a book's position

Embedding Child Resources

The get() method accepts an optional include parameter that embeds child resources directly in the response, eliminating the need for follow-up requests.

Valid values (BookInclude type alias): "chapters", "notes", "assets"

When a value is not included in the request, the corresponding field on CampaignBookDetail is None. When requested, the field contains a list of fully populated objects — the same DTOs returned by the dedicated child endpoints.

from vclient import books_service

books = books_service(campaign_id="...", on_behalf_of="...", company_id="...")

# Embed chapters and notes in a single request
book = await books.get("book_id", include=["chapters", "notes"])
assert book.chapters is not None  # list[CampaignChapter]
assert book.notes is not None     # list[Note]
assert book.assets is None        # not requested

Pagination

Method Returns Description
get_page(limit?, offset?) PaginatedResponse[CampaignBook] Get a page of books
list_all() list[CampaignBook] Get all books
iter_all(limit?) AsyncIterator[CampaignBook] Iterate through all books

Assets

Method Returns Description
get_assets_page(book_id, limit?, offset?) PaginatedResponse[Asset] Get a page of assets
list_all_assets(book_id) list[Asset] Get all assets
iter_all_assets(book_id, limit?) AsyncIterator[Asset] Iterate through assets
get_asset(book_id, asset_id) Asset Get an asset
upload_asset(book_id, filename, content) Asset Upload an asset
delete_asset(book_id, asset_id) None Delete an asset

Notes

Method Returns Description
get_notes_page(book_id, limit?, offset?) PaginatedResponse[Note] Get a page of notes
list_all_notes(book_id) list[Note] Get all notes
iter_all_notes(book_id, limit?) AsyncIterator[Note] Iterate through notes
get_note(book_id, note_id) Note Get a note
create_note(book_id, NoteCreate, **kwargs) Note Create a note
update_note(book_id, note_id, NoteUpdate, **kwargs) Note Update a note
delete_note(book_id, note_id) None Delete a note

Examples

Create and Manage Books

from vclient.models import BookCreate, BookUpdate

# Create a book (preferred: use model object)
request = BookCreate(
    name="Act One",
    description="The beginning of the story"
)
book = await books.create(request)
print(f"Created book #{book.number}: {book.name}")

# Alternative: pass fields as kwargs
book = await books.create(
    name="Act One",
    description="The beginning of the story"
)

# Update a book
update = BookUpdate(name="Act One: Origins")
updated = await books.update(book.id, update)

# Reorder the book
await books.renumber(book.id, number=2)

Manage Book Notes

from vclient.models import NoteCreate

# Create a note
note_request = NoteCreate(title="Chapter Summary", content="...")
note = await books.create_note(book.id, note_request)

# List all notes for a book
notes = await books.list_all_notes(book.id)

# Iterate through notes (memory-efficient)
async for note in books.iter_all_notes(book.id):
    print(f"{note.title}: {note.content[:50]}...")

Manage Book Assets

# Upload a book cover image
with open("cover.jpg", "rb") as f:
    asset = await books.upload_asset(
        book.id,
        filename="book_cover.jpg",
        content=f.read(),
    )

# List all assets
all_assets = await books.list_all_assets(book.id)
for asset in all_assets:
    print(f"{asset.original_filename}: {asset.public_url}")

See Response Models for CampaignBook, Asset, Note, and related types.