498 lines
13 KiB
Markdown
498 lines
13 KiB
Markdown
|
|
# Product Requirements Document: bookstack-api
|
|||
|
|
|
|||
|
|
## 1. Projektübersicht
|
|||
|
|
|
|||
|
|
- **Ziel und Vision:**
|
|||
|
|
Eine Go-Library für die Bookstack REST-API, die programmatischen Zugriff auf das Dokumentationssystem ermöglicht. Die Library wird in hqcli integriert und soll veröffentlichungsfähig sein.
|
|||
|
|
|
|||
|
|
- **Zielgruppe:**
|
|||
|
|
- Primär: AI-Agenten (via hqcli mit `--json` Flag)
|
|||
|
|
- Sekundär: Go-Entwickler, die Bookstack programmatisch nutzen wollen
|
|||
|
|
|
|||
|
|
- **Erfolgs-Metriken:**
|
|||
|
|
- Vollständige Abdeckung der Kern-API (Books, Pages, Search)
|
|||
|
|
- Nutzbar in hqcli für AI-gestützte Dokumentationssuche
|
|||
|
|
- Veröffentlichung als eigenständiges Go-Modul
|
|||
|
|
|
|||
|
|
- **Projektscope:**
|
|||
|
|
- **In Scope:** REST-API-Client für Bookstack, Iterator-basierte Pagination, Export-Funktionen
|
|||
|
|
- **Out of Scope:** Webhooks, Caching, Admin-Funktionen (Users, Roles)
|
|||
|
|
|
|||
|
|
## 2. Funktionale Anforderungen
|
|||
|
|
|
|||
|
|
### Kern-Features
|
|||
|
|
|
|||
|
|
| Feature | Priorität | Version |
|
|||
|
|
|---------|-----------|---------|
|
|||
|
|
| Books: List, Get | P0 | v0.1 |
|
|||
|
|
| Pages: List, Get | P0 | v0.1 |
|
|||
|
|
| Search: All | P0 | v0.1 |
|
|||
|
|
| Pages: Export (Markdown, PDF) | P1 | v0.2 |
|
|||
|
|
| Chapters: List, Get | P1 | v0.2 |
|
|||
|
|
| Shelves: List, Get | P1 | v0.2 |
|
|||
|
|
| Pages: Create, Update | P1 | v0.3 |
|
|||
|
|
| Pages: Delete | P2 | v0.4 |
|
|||
|
|
| Attachments: CRUD | P2 | v0.4 |
|
|||
|
|
| Comments: CRUD | P3 | v0.5 |
|
|||
|
|
|
|||
|
|
### User Stories
|
|||
|
|
|
|||
|
|
**US1: Dokumentation durchsuchen (AI-Agent)**
|
|||
|
|
> Als AI-Agent möchte ich die Bookstack-Dokumentation durchsuchen können, um relevante Seiten für Benutzeranfragen zu finden.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
hqcli docs search "deployment" --json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**US2: Seite abrufen**
|
|||
|
|
> Als Benutzer möchte ich eine Dokumentationsseite anzeigen können, um deren Inhalt zu lesen.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
hqcli docs page 123
|
|||
|
|
hqcli docs page deployment-guide # via Slug
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**US3: Bücher auflisten**
|
|||
|
|
> Als Benutzer möchte ich alle verfügbaren Bücher sehen, um die Dokumentationsstruktur zu verstehen.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
hqcli docs books --json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**US4: Seite exportieren**
|
|||
|
|
> Als Benutzer möchte ich eine Seite als Markdown oder PDF exportieren können.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
hqcli docs page 123 --export=md > page.md
|
|||
|
|
hqcli docs page 123 --export=pdf > page.pdf
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**US5: Seite im Browser öffnen**
|
|||
|
|
> Als Benutzer möchte ich eine Seite schnell im Browser öffnen können.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
hqcli docs open 123
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Detaillierte Workflows
|
|||
|
|
|
|||
|
|
**Workflow: Suche und Anzeige**
|
|||
|
|
```
|
|||
|
|
1. Benutzer/Agent führt Suche aus
|
|||
|
|
2. API gibt Liste von Treffern zurück (ID, Typ, Name, Preview)
|
|||
|
|
3. Benutzer/Agent wählt Treffer aus
|
|||
|
|
4. Seite wird abgerufen und angezeigt (Markdown oder JSON)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Workflow: Seite bearbeiten (v0.3)**
|
|||
|
|
```
|
|||
|
|
1. Seite abrufen (Get)
|
|||
|
|
2. Inhalt lokal bearbeiten
|
|||
|
|
3. Seite aktualisieren (Update)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Feature-Prioritäten
|
|||
|
|
|
|||
|
|
- **Must-have (v1):** List, Get, Search für Books/Pages
|
|||
|
|
- **Should-have (v1):** Export Markdown/PDF, Chapters, Shelves
|
|||
|
|
- **Nice-to-have (v2):** Create, Update, Delete
|
|||
|
|
- **Future:** Attachments, Comments, Image Gallery
|
|||
|
|
|
|||
|
|
## 3. Technische Anforderungen
|
|||
|
|
|
|||
|
|
- **Performance-Ziele:**
|
|||
|
|
- API-Calls < 500ms (abhängig von Netzwerk)
|
|||
|
|
- Iterator verarbeitet 10.000+ Einträge ohne Memory-Probleme
|
|||
|
|
|
|||
|
|
- **Concurrent User-Kapazität:**
|
|||
|
|
Nicht zutreffend (Library, kein Server)
|
|||
|
|
|
|||
|
|
- **Real-time Features:**
|
|||
|
|
Nicht zutreffend
|
|||
|
|
|
|||
|
|
- **Sicherheitsstandards:**
|
|||
|
|
- Token-basierte Authentifizierung (Token ID + Secret)
|
|||
|
|
- Keine Speicherung von Credentials (Aufrufer-Verantwortung)
|
|||
|
|
|
|||
|
|
- **Compliance-Vorgaben:**
|
|||
|
|
Keine speziellen
|
|||
|
|
|
|||
|
|
- **Plattform-Support:**
|
|||
|
|
- Go 1.21+
|
|||
|
|
- Linux, macOS, Windows
|
|||
|
|
|
|||
|
|
## 4. Datenarchitektur
|
|||
|
|
|
|||
|
|
*Nicht zutreffend – keine eigene Datenhaltung*
|
|||
|
|
|
|||
|
|
### Bookstack-Hierarchie (extern)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Shelf (Regal)
|
|||
|
|
└── Book (Buch)
|
|||
|
|
├── Chapter (Kapitel)
|
|||
|
|
│ └── Page (Seite)
|
|||
|
|
└── Page (Seite)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Datenstrukturen
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// Book repräsentiert ein Bookstack-Buch
|
|||
|
|
type Book struct {
|
|||
|
|
ID int `json:"id"`
|
|||
|
|
Name string `json:"name"`
|
|||
|
|
Slug string `json:"slug"`
|
|||
|
|
Description string `json:"description"`
|
|||
|
|
CreatedAt time.Time `json:"created_at"`
|
|||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|||
|
|
CreatedBy int `json:"created_by"`
|
|||
|
|
UpdatedBy int `json:"updated_by"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Page repräsentiert eine Bookstack-Seite
|
|||
|
|
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"`
|
|||
|
|
HTML string `json:"html"`
|
|||
|
|
RawHTML string `json:"raw_html"`
|
|||
|
|
Markdown string `json:"markdown"`
|
|||
|
|
CreatedAt time.Time `json:"created_at"`
|
|||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Chapter repräsentiert ein Bookstack-Kapitel
|
|||
|
|
type Chapter struct {
|
|||
|
|
ID int `json:"id"`
|
|||
|
|
BookID int `json:"book_id"`
|
|||
|
|
Name string `json:"name"`
|
|||
|
|
Slug string `json:"slug"`
|
|||
|
|
Description string `json:"description"`
|
|||
|
|
CreatedAt time.Time `json:"created_at"`
|
|||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Shelf repräsentiert ein Bookstack-Regal
|
|||
|
|
type Shelf struct {
|
|||
|
|
ID int `json:"id"`
|
|||
|
|
Name string `json:"name"`
|
|||
|
|
Slug string `json:"slug"`
|
|||
|
|
Description string `json:"description"`
|
|||
|
|
CreatedAt time.Time `json:"created_at"`
|
|||
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// SearchResult repräsentiert ein Suchergebnis
|
|||
|
|
type SearchResult struct {
|
|||
|
|
ID int `json:"id"`
|
|||
|
|
Name string `json:"name"`
|
|||
|
|
Slug string `json:"slug"`
|
|||
|
|
Type string `json:"type"` // page, chapter, book, bookshelf
|
|||
|
|
URL string `json:"url"`
|
|||
|
|
Preview string `json:"preview"`
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 5. API & Interface-Spezifikation
|
|||
|
|
|
|||
|
|
### Client-Initialisierung
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
type Config struct {
|
|||
|
|
BaseURL string // z.B. "https://docs.jakoubek.net"
|
|||
|
|
TokenID string // API Token ID
|
|||
|
|
TokenSecret string // API Token Secret
|
|||
|
|
HTTPClient *http.Client // optional, für Tests/Mocking
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func NewClient(cfg Config) *Client
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Beispiel:**
|
|||
|
|
```go
|
|||
|
|
client := bookstack.NewClient(bookstack.Config{
|
|||
|
|
BaseURL: "https://docs.jakoubek.net",
|
|||
|
|
TokenID: os.Getenv("BOOKSTACK_TOKEN_ID"),
|
|||
|
|
TokenSecret: os.Getenv("BOOKSTACK_TOKEN_SECRET"),
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Service-Struktur
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
type Client struct {
|
|||
|
|
Books *BooksService
|
|||
|
|
Pages *PagesService
|
|||
|
|
Chapters *ChaptersService
|
|||
|
|
Shelves *ShelvesService
|
|||
|
|
Search *SearchService
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### REST-Endpoints (Bookstack API)
|
|||
|
|
|
|||
|
|
| Service | Methode | Endpoint | Beschreibung |
|
|||
|
|
|---------|---------|----------|--------------|
|
|||
|
|
| Books | List | GET /api/books | Alle Bücher |
|
|||
|
|
| Books | Get | GET /api/books/{id} | Einzelnes Buch |
|
|||
|
|
| Pages | List | GET /api/pages | Alle Seiten |
|
|||
|
|
| Pages | Get | GET /api/pages/{id} | Einzelne Seite |
|
|||
|
|
| Pages | Create | POST /api/pages | Seite erstellen |
|
|||
|
|
| Pages | Update | PUT /api/pages/{id} | Seite aktualisieren |
|
|||
|
|
| Pages | Delete | DELETE /api/pages/{id} | Seite löschen |
|
|||
|
|
| Pages | ExportMD | GET /api/pages/{id}/export/markdown | Markdown-Export |
|
|||
|
|
| Pages | ExportPDF | GET /api/pages/{id}/export/pdf | PDF-Export |
|
|||
|
|
| Chapters | List | GET /api/chapters | Alle Kapitel |
|
|||
|
|
| Chapters | Get | GET /api/chapters/{id} | Einzelnes Kapitel |
|
|||
|
|
| Shelves | List | GET /api/shelves | Alle Regale |
|
|||
|
|
| Shelves | Get | GET /api/shelves/{id} | Einzelnes Regal |
|
|||
|
|
| Search | All | GET /api/search?query=... | Volltextsuche |
|
|||
|
|
|
|||
|
|
### Authentifizierung
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Authorization: Token <token_id>:<token_secret>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Pagination (Iterator-Pattern)
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// ListAll gibt einen Iterator über alle Einträge zurück
|
|||
|
|
// Nutzt Go 1.23+ iter.Seq oder eigene Implementation
|
|||
|
|
func (s *BooksService) ListAll(ctx context.Context) iter.Seq2[*Book, error]
|
|||
|
|
|
|||
|
|
// Nutzung:
|
|||
|
|
for book, err := range client.Books.ListAll(ctx) {
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
fmt.Println(book.Name)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Begründung:** Iterator-Pattern ist Go-idiomatisch (ab 1.23), Memory-effizient und ermöglicht frühen Abbruch.
|
|||
|
|
|
|||
|
|
### Rate Limiting
|
|||
|
|
|
|||
|
|
- Bookstack: 180 Requests/Minute (default)
|
|||
|
|
- **Keine Library-interne Behandlung** – Aufrufer muss Rate-Limiting selbst handhaben
|
|||
|
|
- Bei 429-Response: `ErrRateLimited` zurückgeben
|
|||
|
|
|
|||
|
|
## 6. Benutzeroberfläche
|
|||
|
|
|
|||
|
|
*Nicht zutreffend – Library ohne UI*
|
|||
|
|
|
|||
|
|
### hqcli-Integration (separates Projekt)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Bücher auflisten
|
|||
|
|
hqcli docs books
|
|||
|
|
hqcli docs books --json
|
|||
|
|
|
|||
|
|
# Seiten eines Buchs
|
|||
|
|
hqcli docs pages --book=<id|slug>
|
|||
|
|
|
|||
|
|
# Seite anzeigen
|
|||
|
|
hqcli docs page <id|slug>
|
|||
|
|
hqcli docs page <id> --json
|
|||
|
|
|
|||
|
|
# Seite exportieren
|
|||
|
|
hqcli docs page <id> --export=md
|
|||
|
|
hqcli docs page <id> --export=pdf
|
|||
|
|
|
|||
|
|
# Suche
|
|||
|
|
hqcli docs search "query"
|
|||
|
|
hqcli docs search "query" --json
|
|||
|
|
|
|||
|
|
# Im Browser öffnen
|
|||
|
|
hqcli docs open <id|slug>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Output-Priorität:** `--json` für AI-Agenten ist Hauptanwendungsfall
|
|||
|
|
|
|||
|
|
## 7. Nicht-funktionale Anforderungen
|
|||
|
|
|
|||
|
|
- **Verfügbarkeit:**
|
|||
|
|
Nicht zutreffend (Library)
|
|||
|
|
|
|||
|
|
- **Dependencies:**
|
|||
|
|
Nur Go-Standardbibliothek (net/http, encoding/json, etc.)
|
|||
|
|
|
|||
|
|
- **Backward Compatibility:**
|
|||
|
|
Semantic Versioning (v0.x während Entwicklung, v1.x nach Stabilisierung)
|
|||
|
|
|
|||
|
|
- **Logging-Strategie:**
|
|||
|
|
Keine eigene Logging – Fehler werden als `error` zurückgegeben
|
|||
|
|
|
|||
|
|
- **Konfiguration:**
|
|||
|
|
Via `Config`-Struct bei Client-Erstellung
|
|||
|
|
|
|||
|
|
## 8. Qualitätssicherung
|
|||
|
|
|
|||
|
|
### Definition of Done
|
|||
|
|
|
|||
|
|
- [ ] Alle public APIs dokumentiert (GoDoc)
|
|||
|
|
- [ ] Unit-Tests für alle Services (≥80% Coverage)
|
|||
|
|
- [ ] Integration-Tests gegen Mock-Server
|
|||
|
|
- [ ] Beispiel-Code in examples/
|
|||
|
|
- [ ] README mit Quick-Start
|
|||
|
|
|
|||
|
|
### Test-Anforderungen
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// Unit-Tests mit Mock-HTTP-Client
|
|||
|
|
func TestBooksService_List(t *testing.T) {
|
|||
|
|
server := httptest.NewServer(...)
|
|||
|
|
client := bookstack.NewClient(bookstack.Config{
|
|||
|
|
BaseURL: server.URL,
|
|||
|
|
TokenID: "test",
|
|||
|
|
TokenSecret: "test",
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
books, err := client.Books.List(ctx, nil)
|
|||
|
|
// assertions...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Launch-Kriterien v1.0
|
|||
|
|
|
|||
|
|
- [ ] Books, Pages, Search vollständig implementiert
|
|||
|
|
- [ ] Export (Markdown, PDF) funktioniert
|
|||
|
|
- [ ] Dokumentation vollständig
|
|||
|
|
- [ ] Keine bekannten Bugs
|
|||
|
|
- [ ] hqcli-Integration getestet
|
|||
|
|
|
|||
|
|
## 9. Technische Implementierungshinweise
|
|||
|
|
|
|||
|
|
### Go-Projektstruktur
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
bookstack-api/
|
|||
|
|
├── bookstack.go # Client, Config, NewClient()
|
|||
|
|
├── books.go # BooksService
|
|||
|
|
├── pages.go # PagesService
|
|||
|
|
├── chapters.go # ChaptersService
|
|||
|
|
├── shelves.go # ShelvesService
|
|||
|
|
├── search.go # SearchService
|
|||
|
|
├── types.go # Alle Datenstrukturen
|
|||
|
|
├── errors.go # Error-Typen
|
|||
|
|
├── http.go # HTTP-Helfer, Request-Building
|
|||
|
|
├── iterator.go # Pagination-Iterator
|
|||
|
|
├── bookstack_test.go # Tests
|
|||
|
|
├── README.md
|
|||
|
|
├── go.mod
|
|||
|
|
├── go.sum
|
|||
|
|
└── examples/
|
|||
|
|
└── basic/
|
|||
|
|
└── main.go
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Error-Handling-Strategie
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// Definierte Error-Typen für häufige Fälle
|
|||
|
|
var (
|
|||
|
|
ErrNotFound = errors.New("bookstack: resource not found")
|
|||
|
|
ErrUnauthorized = errors.New("bookstack: unauthorized")
|
|||
|
|
ErrForbidden = errors.New("bookstack: forbidden")
|
|||
|
|
ErrRateLimited = errors.New("bookstack: rate limited")
|
|||
|
|
ErrBadRequest = errors.New("bookstack: bad request")
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// APIError für detaillierte Fehlerinformationen
|
|||
|
|
type APIError struct {
|
|||
|
|
StatusCode int
|
|||
|
|
Code int `json:"code"`
|
|||
|
|
Message string `json:"message"`
|
|||
|
|
Body []byte // Original Response Body
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (e *APIError) Error() string {
|
|||
|
|
return fmt.Sprintf("bookstack: API error %d: %s", e.StatusCode, e.Message)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (e *APIError) Is(target error) bool {
|
|||
|
|
switch target {
|
|||
|
|
case ErrNotFound:
|
|||
|
|
return e.StatusCode == 404
|
|||
|
|
case ErrUnauthorized:
|
|||
|
|
return e.StatusCode == 401
|
|||
|
|
case ErrForbidden:
|
|||
|
|
return e.StatusCode == 403
|
|||
|
|
case ErrRateLimited:
|
|||
|
|
return e.StatusCode == 429
|
|||
|
|
case ErrBadRequest:
|
|||
|
|
return e.StatusCode == 400
|
|||
|
|
}
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Begründung:** `errors.Is()` ermöglicht einfache Fehlerprüfung, `APIError` bietet Details wenn nötig.
|
|||
|
|
|
|||
|
|
### HTTP-Wrapper
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// Interner HTTP-Helfer
|
|||
|
|
func (c *Client) do(ctx context.Context, method, path string, body, result any) error {
|
|||
|
|
// 1. Request bauen
|
|||
|
|
// 2. Auth-Header setzen
|
|||
|
|
// 3. Request ausführen
|
|||
|
|
// 4. Response prüfen
|
|||
|
|
// 5. Bei Fehler: APIError zurückgeben
|
|||
|
|
// 6. Bei Erfolg: JSON in result unmarshalen
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Entwicklungs-Prioritäten
|
|||
|
|
|
|||
|
|
1. **Phase 1 (v0.1):** Foundation
|
|||
|
|
- Client-Setup, Auth, HTTP-Wrapper
|
|||
|
|
- Books.List, Books.Get
|
|||
|
|
- Pages.List, Pages.Get
|
|||
|
|
- Error-Handling
|
|||
|
|
|
|||
|
|
2. **Phase 2 (v0.2):** Core Features
|
|||
|
|
- Search.All
|
|||
|
|
- Pages.ExportMarkdown, Pages.ExportPDF
|
|||
|
|
- Iterator für Pagination
|
|||
|
|
- Chapters, Shelves
|
|||
|
|
|
|||
|
|
3. **Phase 3 (v0.3):** Write Operations
|
|||
|
|
- Pages.Create
|
|||
|
|
- Pages.Update
|
|||
|
|
|
|||
|
|
4. **Phase 4 (v1.0):** Release
|
|||
|
|
- Dokumentation
|
|||
|
|
- Beispiele
|
|||
|
|
- CI/CD
|
|||
|
|
- Veröffentlichung
|
|||
|
|
|
|||
|
|
### Potenzielle Risiken
|
|||
|
|
|
|||
|
|
| Risiko | Wahrscheinlichkeit | Mitigation |
|
|||
|
|
|--------|-------------------|------------|
|
|||
|
|
| API-Änderungen in Bookstack | Niedrig | Semantic Versioning, Tests |
|
|||
|
|
| Rate-Limiting-Probleme | Mittel | Dokumentation für Aufrufer |
|
|||
|
|
| Große PDF-Exports | Mittel | Streaming statt Buffer |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Anhang: Bookstack API-Referenz
|
|||
|
|
|
|||
|
|
- **Basis-URL:** https://docs.jakoubek.net/api
|
|||
|
|
- **Dokumentation:** https://docs.jakoubek.net/api/docs
|
|||
|
|
- **Beispiele:** https://codeberg.org/bookstack/api-scripts
|
|||
|
|
- **Rate Limit:** 180 req/min (konfigurierbar serverseitig)
|
|||
|
|
|
|||
|
|
### Pagination-Parameter
|
|||
|
|
|
|||
|
|
| Parameter | Beschreibung | Default |
|
|||
|
|
|-----------|--------------|---------|
|
|||
|
|
| count | Anzahl Ergebnisse | 100 (max 500) |
|
|||
|
|
| offset | Start-Position | 0 |
|
|||
|
|
| sort | Sortierung (+name, -created_at) | - |
|
|||
|
|
| filter[field] | Filter (eq, ne, gt, lt, like) | - |
|