bookstack

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2026 License: MIT Imports: 9 Imported by: 0

README

bookstack-api

A Go client library for the BookStack REST API.

Full API reference: https://demo.bookstackapp.com/api/docs

Installation

go get github.com/dimahum/bookstack-api

Requires Go 1.21 or later.

Authentication

BookStack uses token-based authentication. Generate a token in your BookStack instance under Profile → API Tokens, then pass the token ID and secret to NewClient.

Quick start

import bookstack "github.com/dimahum/bookstack-api"

client := bookstack.NewClient(
    "https://your-bookstack.example.com",
    "your-token-id",
    "your-token-secret",
)

Usage

Books
// List books (first 10, newest first)
resp, err := client.ListBooks(&bookstack.ListOptions{
    Count: 10,
    Sort:  "-created_at",
})

// Create a book
book, err := client.CreateBook(&bookstack.CreateBookRequest{
    Name:        "My Book",
    Description: "A great book",
    Tags: []bookstack.Tag{{Name: "team", Value: "engineering"}},
})

// Get a book by ID
book, err := client.GetBook(42)

// Update a book
book, err := client.UpdateBook(42, &bookstack.UpdateBookRequest{
    Name: "My Book (revised)",
})

// Delete a book
err := client.DeleteBook(42)
Chapters
chapter, err := client.CreateChapter(&bookstack.CreateChapterRequest{
    BookID: 42,
    Name:   "Introduction",
})

chapter, err := client.GetChapter(chapter.ID)

_, err = client.UpdateChapter(chapter.ID, &bookstack.UpdateChapterRequest{
    Name: "Getting Started",
})

err = client.DeleteChapter(chapter.ID)
Pages
// Create a page with HTML content (inside a chapter)
page, err := client.CreatePage(&bookstack.CreatePageRequest{
    ChapterID: 10,
    Name:      "Hello World",
    HTML:      "<h1>Hello</h1><p>World</p>",
})

// Or create a page with Markdown content directly in a book
page, err := client.CreatePage(&bookstack.CreatePageRequest{
    BookID:   42,
    Name:     "Hello Markdown",
    Markdown: "# Hello\n\nWorld",
})

page, err := client.GetPage(page.ID)

_, err = client.UpdatePage(page.ID, &bookstack.UpdatePageRequest{
    Name: "Hello World (v2)",
})

err = client.DeletePage(page.ID)
Bookshelves
shelf, err := client.CreateShelf(&bookstack.CreateShelfRequest{
    Name:  "Engineering",
    Books: []int{42, 43}, // book IDs to include
})

shelf, err := client.GetShelf(shelf.ID)

_, err = client.UpdateShelf(shelf.ID, &bookstack.UpdateShelfRequest{
    Name: "Engineering (archived)",
})

err = client.DeleteShelf(shelf.ID)
results, err := client.Search(&bookstack.SearchOptions{
    Query: "kubernetes deployment",
    Page:  1,
    Count: 20,
})

for _, item := range results.Data {
    fmt.Printf("[%s] %s – %s\n", item.Type, item.Name, item.URL)
}

BookStack's advanced search syntax is supported in the Query field, for example:

Syntax Meaning
[is:page] Only return pages
[created_by:me] Content created by the current user
{exact phrase} Exact phrase match
tag:version=2 Items with a specific tag value
Attachments
// Create a link attachment on a page
att, err := client.CreateAttachment(&bookstack.CreateAttachmentRequest{
    Name:       "Official Docs",
    UploadedTo: page.ID,
    Link:       "https://demo.bookstackapp.com/api/docs",
})

att, err := client.GetAttachment(att.ID)

_, err = client.UpdateAttachment(att.ID, &bookstack.UpdateAttachmentRequest{
    Name: "API Docs",
})

err = client.DeleteAttachment(att.ID)
Users
users, err := client.ListUsers(nil)

user, err := client.CreateUser(&bookstack.CreateUserRequest{
    Name:     "Jane Doe",
    Email:    "jane@example.com",
    Password: "s3cur3p@ss",
    Roles:    []int{2}, // role IDs
})

user, err := client.GetUser(user.ID)

_, err = client.UpdateUser(user.ID, &bookstack.UpdateUserRequest{
    Name: "Jane Smith",
})

// Delete user and migrate their content ownership to user ID 1
err = client.DeleteUser(user.ID, 1)
Pagination & filtering

Every list method accepts a *ListOptions parameter:

opts := &bookstack.ListOptions{
    Count:  50,            // items per page (max 500)
    Offset: 50,            // skip first 50 results
    Sort:   "-updated_at", // sort field; prefix "-" for descending
    Filter: map[string]string{
        "name:like": "%go%",          // name contains "go"
        "created_by": "5",            // created by user 5
    },
}
resp, err := client.ListBooks(opts)
fmt.Printf("%d / %d books\n", len(resp.Data), resp.Total)

Running the example program

export BOOKSTACK_URL=https://your-bookstack.example.com
export BOOKSTACK_TOKEN_ID=your-token-id
export BOOKSTACK_TOKEN_SECRET=your-token-secret
go run ./examples/bookstack/

Running the tests

go test ./...

License

MIT

Documentation

Overview

Package bookstack provides a Go client for the BookStack REST API. BookStack API documentation: https://demo.bookstackapp.com/api/docs

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Attachment

type Attachment struct {
	ID         int      `json:"id"`
	Name       string   `json:"name"`
	Extension  string   `json:"extension"`
	UploadedTo int      `json:"uploaded_to"`
	External   bool     `json:"external"`
	Order      int      `json:"order"`
	CreatedAt  string   `json:"created_at"`
	UpdatedAt  string   `json:"updated_at"`
	CreatedBy  *UserRef `json:"created_by,omitempty"`
	UpdatedBy  *UserRef `json:"updated_by,omitempty"`
}

Attachment is a summary of a BookStack attachment as returned by list endpoints.

type AttachmentDetail

type AttachmentDetail struct {
	Attachment
	Content string `json:"content,omitempty"`
}

AttachmentDetail is the full attachment resource returned by create/read/update. For file attachments, Content contains the base64-encoded file data. For link attachments, Content contains the URL.

type Book

type Book struct {
	ID          int      `json:"id"`
	Name        string   `json:"name"`
	Slug        string   `json:"slug"`
	Description string   `json:"description"`
	CreatedAt   string   `json:"created_at"`
	UpdatedAt   string   `json:"updated_at"`
	CreatedBy   *UserRef `json:"created_by,omitempty"`
	UpdatedBy   *UserRef `json:"updated_by,omitempty"`
	OwnedBy     *UserRef `json:"owned_by,omitempty"`
	Cover       *Image   `json:"cover,omitempty"`
}

Book is a summary of a BookStack book as returned by list endpoints.

type BookContentsEntry

type BookContentsEntry struct {
	ID   int    `json:"id"`
	Type string `json:"type"` // "chapter" or "page"
	Name string `json:"name"`
	Slug string `json:"slug"`
}

BookContentsEntry is a chapter or page inside a book's contents list.

type BookDetail

type BookDetail struct {
	Book
	Contents []BookContentsEntry `json:"contents,omitempty"`
	Tags     []Tag               `json:"tags,omitempty"`
}

BookDetail is the full book resource returned by create/read/update endpoints.

type Chapter

type Chapter struct {
	ID          int      `json:"id"`
	BookID      int      `json:"book_id"`
	Name        string   `json:"name"`
	Slug        string   `json:"slug"`
	Description string   `json:"description"`
	Priority    int      `json:"priority"`
	CreatedAt   string   `json:"created_at"`
	UpdatedAt   string   `json:"updated_at"`
	CreatedBy   *UserRef `json:"created_by,omitempty"`
	UpdatedBy   *UserRef `json:"updated_by,omitempty"`
	OwnedBy     *UserRef `json:"owned_by,omitempty"`
}

Chapter is a summary of a BookStack chapter as returned by list endpoints.

type ChapterDetail

type ChapterDetail struct {
	Chapter
	Pages []ChapterPage `json:"pages,omitempty"`
	Tags  []Tag         `json:"tags,omitempty"`
}

ChapterDetail is the full chapter resource returned by create/read/update.

type ChapterPage

type ChapterPage struct {
	ID        int    `json:"id"`
	BookID    int    `json:"book_id"`
	ChapterID int    `json:"chapter_id"`
	Name      string `json:"name"`
	Slug      string `json:"slug"`
	Draft     bool   `json:"draft"`
	Template  bool   `json:"template"`
}

ChapterPage is a summary of a page inside a chapter.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the BookStack API client.

func NewClient

func NewClient(baseURL, tokenID, tokenSecret string) *Client

NewClient creates a new BookStack API client.

baseURL is the base URL of your BookStack instance (e.g. "https://bookstack.example.com"). tokenID and tokenSecret are your API credentials generated in BookStack (Profile → API Tokens).

func (*Client) CreateAttachment

func (c *Client) CreateAttachment(req *CreateAttachmentRequest) (*AttachmentDetail, error)

CreateAttachment creates a new link attachment on a page.

func (*Client) CreateBook

func (c *Client) CreateBook(req *CreateBookRequest) (*BookDetail, error)

CreateBook creates a new book.

func (*Client) CreateChapter

func (c *Client) CreateChapter(req *CreateChapterRequest) (*ChapterDetail, error)

CreateChapter creates a new chapter.

func (*Client) CreatePage

func (c *Client) CreatePage(req *CreatePageRequest) (*PageDetail, error)

CreatePage creates a new page.

func (*Client) CreateShelf

func (c *Client) CreateShelf(req *CreateShelfRequest) (*ShelfDetail, error)

CreateShelf creates a new bookshelf.

func (*Client) CreateUser

func (c *Client) CreateUser(req *CreateUserRequest) (*UserDetail, error)

CreateUser creates a new user.

func (*Client) DeleteAttachment

func (c *Client) DeleteAttachment(id int) error

DeleteAttachment deletes an attachment by ID.

func (*Client) DeleteBook

func (c *Client) DeleteBook(id int) error

DeleteBook deletes a book by ID.

func (*Client) DeleteChapter

func (c *Client) DeleteChapter(id int) error

DeleteChapter deletes a chapter by ID.

func (*Client) DeletePage

func (c *Client) DeletePage(id int) error

DeletePage deletes a page by ID.

func (*Client) DeleteShelf

func (c *Client) DeleteShelf(id int) error

DeleteShelf deletes a bookshelf by ID.

func (*Client) DeleteUser

func (c *Client) DeleteUser(id, migrateOwnershipTo int) error

DeleteUser deletes a user by ID. If migrateOwnershipTo is > 0, content owned by the deleted user will be transferred to that user ID.

func (*Client) GetAttachment

func (c *Client) GetAttachment(id int) (*AttachmentDetail, error)

GetAttachment returns a single attachment by ID.

func (*Client) GetBook

func (c *Client) GetBook(id int) (*BookDetail, error)

GetBook returns a single book by ID.

func (*Client) GetChapter

func (c *Client) GetChapter(id int) (*ChapterDetail, error)

GetChapter returns a single chapter by ID.

func (*Client) GetPage

func (c *Client) GetPage(id int) (*PageDetail, error)

GetPage returns a single page by ID.

func (*Client) GetShelf

func (c *Client) GetShelf(id int) (*ShelfDetail, error)

GetShelf returns a single bookshelf by ID.

func (*Client) GetUser

func (c *Client) GetUser(id int) (*UserDetail, error)

GetUser returns a single user by ID.

func (*Client) ListAttachments

func (c *Client) ListAttachments(opts *ListOptions) (*ListResponse[Attachment], error)

ListAttachments returns a paginated list of attachments.

func (*Client) ListBooks

func (c *Client) ListBooks(opts *ListOptions) (*ListResponse[Book], error)

ListBooks returns a paginated list of books.

func (*Client) ListChapters

func (c *Client) ListChapters(opts *ListOptions) (*ListResponse[Chapter], error)

ListChapters returns a paginated list of chapters.

func (*Client) ListPages

func (c *Client) ListPages(opts *ListOptions) (*ListResponse[Page], error)

ListPages returns a paginated list of pages.

func (*Client) ListShelves

func (c *Client) ListShelves(opts *ListOptions) (*ListResponse[Shelf], error)

ListShelves returns a paginated list of bookshelves.

func (*Client) ListUsers

func (c *Client) ListUsers(opts *ListOptions) (*ListResponse[User], error)

ListUsers returns a paginated list of users.

func (*Client) Search

func (c *Client) Search(opts *SearchOptions) (*SearchResponse, error)

Search performs a full-text search across all content.

func (*Client) UpdateAttachment

func (c *Client) UpdateAttachment(id int, req *UpdateAttachmentRequest) (*AttachmentDetail, error)

UpdateAttachment updates an existing attachment.

func (*Client) UpdateBook

func (c *Client) UpdateBook(id int, req *UpdateBookRequest) (*BookDetail, error)

UpdateBook updates an existing book.

func (*Client) UpdateChapter

func (c *Client) UpdateChapter(id int, req *UpdateChapterRequest) (*ChapterDetail, error)

UpdateChapter updates an existing chapter.

func (*Client) UpdatePage

func (c *Client) UpdatePage(id int, req *UpdatePageRequest) (*PageDetail, error)

UpdatePage updates an existing page.

func (*Client) UpdateShelf

func (c *Client) UpdateShelf(id int, req *UpdateShelfRequest) (*ShelfDetail, error)

UpdateShelf updates an existing bookshelf.

func (*Client) UpdateUser

func (c *Client) UpdateUser(id int, req *UpdateUserRequest) (*UserDetail, error)

UpdateUser updates an existing user.

func (*Client) WithHTTPClient

func (c *Client) WithHTTPClient(hc *http.Client) *Client

WithHTTPClient replaces the default HTTP client, useful for testing or custom transports.

type CreateAttachmentRequest

type CreateAttachmentRequest struct {
	Name       string `json:"name"`
	UploadedTo int    `json:"uploaded_to"` // page ID
	// Link is the URL for external/link attachments.
	Link string `json:"link,omitempty"`
}

CreateAttachmentRequest is the payload for creating a link attachment. To upload a file attachment use CreateFileAttachment instead.

type CreateBookRequest

type CreateBookRequest struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Tags        []Tag  `json:"tags,omitempty"`
}

CreateBookRequest is the payload for creating a book.

type CreateChapterRequest

type CreateChapterRequest struct {
	BookID      int    `json:"book_id"`
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Tags        []Tag  `json:"tags,omitempty"`
}

CreateChapterRequest is the payload for creating a chapter.

type CreatePageRequest

type CreatePageRequest struct {
	BookID    int    `json:"book_id,omitempty"`
	ChapterID int    `json:"chapter_id,omitempty"`
	Name      string `json:"name"`
	HTML      string `json:"html,omitempty"`
	Markdown  string `json:"markdown,omitempty"`
	Tags      []Tag  `json:"tags,omitempty"`
}

CreatePageRequest is the payload for creating a page. Exactly one of BookID or ChapterID must be set.

type CreateShelfRequest

type CreateShelfRequest struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Books       []int  `json:"books,omitempty"`
	Tags        []Tag  `json:"tags,omitempty"`
}

CreateShelfRequest is the payload for creating a bookshelf.

type CreateUserRequest

type CreateUserRequest struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	Password string `json:"password,omitempty"`
	Language string `json:"language,omitempty"`
	Roles    []int  `json:"roles,omitempty"`
	// SendInvite when true sends a welcome/invite e-mail to the user.
	SendInvite bool `json:"send_invite,omitempty"`
}

CreateUserRequest is the payload for creating a user.

type Error

type Error struct {
	StatusCode int
	Message    string `json:"message"`
}

Error represents a BookStack API error response.

func (*Error) Error

func (e *Error) Error() string

type Image

type Image struct {
	ID      int    `json:"id"`
	Name    string `json:"name"`
	URL     string `json:"url"`
	Created string `json:"created"`
	Updated string `json:"updated"`
}

Image is a cover image attached to a book or shelf.

type ListOptions

type ListOptions struct {
	// Count is the number of items to return (default 20, max 500).
	Count int
	// Offset is the number of items to skip (for pagination).
	Offset int
	// Sort is the field name to sort by. Prefix with "-" for descending order
	// (e.g. "-updated_at").
	Sort string
	// Filter maps field names (and optional operators separated by ":") to
	// filter values, e.g. {"name:like": "%go%"}.
	Filter map[string]string
}

ListOptions are the common query parameters accepted by every list endpoint.

type ListResponse

type ListResponse[T any] struct {
	Data  []T `json:"data"`
	Total int `json:"total"`
}

ListResponse is the envelope returned by all list endpoints.

type Page

type Page struct {
	ID        int      `json:"id"`
	BookID    int      `json:"book_id"`
	ChapterID int      `json:"chapter_id"`
	Name      string   `json:"name"`
	Slug      string   `json:"slug"`
	Priority  int      `json:"priority"`
	Draft     bool     `json:"draft"`
	Template  bool     `json:"template"`
	CreatedAt string   `json:"created_at"`
	UpdatedAt string   `json:"updated_at"`
	CreatedBy *UserRef `json:"created_by,omitempty"`
	UpdatedBy *UserRef `json:"updated_by,omitempty"`
	OwnedBy   *UserRef `json:"owned_by,omitempty"`
}

Page is a summary of a BookStack page as returned by list endpoints.

type PageDetail

type PageDetail struct {
	Page
	HTML     string `json:"html,omitempty"`
	Markdown string `json:"markdown,omitempty"`
	RawHTML  string `json:"raw_html,omitempty"`
	Tags     []Tag  `json:"tags,omitempty"`
}

PageDetail is the full page resource returned by create/read/update endpoints.

type Role

type Role struct {
	ID          int    `json:"id"`
	DisplayName string `json:"display_name"`
}

Role is a lightweight role reference embedded in user details.

type SearchOptions

type SearchOptions struct {
	// Query is the search string. Supports BookStack's advanced filter syntax,
	// e.g. `[created_by:me]`, `[is:page]`, `{exact phrase}`.
	Query string
	// Page is the 1-based page number (default 1).
	Page int
	// Count is the number of items per page (default 20, max 100).
	Count int
}

SearchOptions controls a search request.

type SearchResponse

type SearchResponse struct {
	Data  []SearchResultItem `json:"data"`
	Total int                `json:"total"`
}

SearchResponse is the envelope returned by the search endpoint.

type SearchResultItem

type SearchResultItem struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
	Slug string `json:"slug"`
	// Type is one of "book", "chapter", "page", or "bookshelf".
	Type      string `json:"type"`
	URL       string `json:"url"`
	Preview   string `json:"preview_html,omitempty"`
	CreatedAt string `json:"created_at"`
	UpdatedAt string `json:"updated_at"`
}

SearchResultItem is a single result from a search query.

type Shelf

type Shelf struct {
	ID          int      `json:"id"`
	Name        string   `json:"name"`
	Slug        string   `json:"slug"`
	Description string   `json:"description"`
	CreatedAt   string   `json:"created_at"`
	UpdatedAt   string   `json:"updated_at"`
	CreatedBy   *UserRef `json:"created_by,omitempty"`
	UpdatedBy   *UserRef `json:"updated_by,omitempty"`
	OwnedBy     *UserRef `json:"owned_by,omitempty"`
	Cover       *Image   `json:"cover,omitempty"`
}

Shelf is a summary of a BookStack bookshelf as returned by list endpoints.

type ShelfDetail

type ShelfDetail struct {
	Shelf
	Books []Book `json:"books,omitempty"`
	Tags  []Tag  `json:"tags,omitempty"`
}

ShelfDetail is the full shelf resource returned by create/read/update.

type Tag

type Tag struct {
	Name  string `json:"name"`
	Value string `json:"value,omitempty"`
	Order int    `json:"order,omitempty"`
}

Tag is a key/value tag that can be attached to books, chapters, and pages.

type UpdateAttachmentRequest

type UpdateAttachmentRequest struct {
	Name       string `json:"name,omitempty"`
	UploadedTo int    `json:"uploaded_to,omitempty"`
	Link       string `json:"link,omitempty"`
}

UpdateAttachmentRequest is the payload for updating an attachment.

type UpdateBookRequest

type UpdateBookRequest struct {
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Tags        []Tag  `json:"tags,omitempty"`
}

UpdateBookRequest is the payload for updating a book.

type UpdateChapterRequest

type UpdateChapterRequest struct {
	BookID      int    `json:"book_id,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Tags        []Tag  `json:"tags,omitempty"`
}

UpdateChapterRequest is the payload for updating a chapter.

type UpdatePageRequest

type UpdatePageRequest struct {
	BookID    int    `json:"book_id,omitempty"`
	ChapterID int    `json:"chapter_id,omitempty"`
	Name      string `json:"name,omitempty"`
	HTML      string `json:"html,omitempty"`
	Markdown  string `json:"markdown,omitempty"`
	Tags      []Tag  `json:"tags,omitempty"`
}

UpdatePageRequest is the payload for updating a page.

type UpdateShelfRequest

type UpdateShelfRequest struct {
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	Books       []int  `json:"books,omitempty"`
	Tags        []Tag  `json:"tags,omitempty"`
}

UpdateShelfRequest is the payload for updating a bookshelf.

type UpdateUserRequest

type UpdateUserRequest struct {
	Name     string `json:"name,omitempty"`
	Email    string `json:"email,omitempty"`
	Password string `json:"password,omitempty"`
	Language string `json:"language,omitempty"`
	Roles    []int  `json:"roles,omitempty"`
}

UpdateUserRequest is the payload for updating a user.

type User

type User struct {
	ID        int    `json:"id"`
	Name      string `json:"name"`
	Email     string `json:"email"`
	Slug      string `json:"slug"`
	AvatarURL string `json:"avatar_url"`
	CreatedAt string `json:"created_at"`
	UpdatedAt string `json:"updated_at"`
}

User is a BookStack user as returned by list endpoints.

type UserDetail

type UserDetail struct {
	User
	Roles []Role `json:"roles,omitempty"`
}

UserDetail is the full user resource returned by create/read/update endpoints.

type UserRef

type UserRef struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
	Slug string `json:"slug,omitempty"`
}

UserRef is a lightweight user reference embedded in most resources. Some BookStack versions return it as a plain integer (user ID); this type handles both forms during JSON decoding.

func (*UserRef) UnmarshalJSON

func (u *UserRef) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler so that UserRef can be decoded from either a JSON object {"id":1,"name":"..."} or a bare integer.

Directories

Path Synopsis
examples
bookstack command
Command examples demonstrates how to use the bookstack API client.
Command examples demonstrates how to use the bookstack API client.
tests
integration command
Command integration exercises the bookstack API client against a live BookStack instance: it creates one book and two pages, updates the first page, deletes the second page, and then verifies that the book contains exactly one page with the updated name.
Command integration exercises the bookstack API client against a live BookStack instance: it creates one book and two pages, updates the first page, deletes the second page, and then verifies that the book contains exactly one page with the updated name.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL