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.