--- method: POST path: /api/collections auth: jwt area: collections --- # Create Collection Creates a new collection for the signed-in user. If any rules are present (or `collection_type` is `"smart"`), the collection is a smart collection whose membership is evaluated live; otherwise it is static. Creating a collection whose name already exists for the user returns **409**. ## Example request ```json example-request { "name": "To Read", "description": "Books I want to read soon", "color": "#00FF00", "icon": "📖", "collection_type": "static", "auto_assign_rules": [], "view_settings": { "kobo": { "view_mode": "grid" } } } ``` ## Example response ```json example-response { "id": "550e8400-e29b-41d4-a716-446655440000", "user_id": "8f14e45f-ceea-467f-a429-0b21bfc0b1a2", "name": "To Read", "description": "Books I want to read soon", "color": "#00FF00", "icon": "📖", "collection_type": "static", "auto_assign_rules": null, "view_settings": { "kobo": { "view_mode": "grid" } }, "book_count": 0, "created_at": "2026-10-24 13:57:01.81234 +0000 UTC" } ``` Note: `created_at` is serialized with Go's `time.String()` format, not RFC3339. Treat it as display text; do not parse it as an ISO timestamp. ## Request fields | Field | Type | Required | Notes | | ----- | ---- | -------- | ----- | | name | string | yes | unique per user | | description | string | no | | | color | string | no | hex color, e.g. `"#FF5733"` | | icon | string | no | emoji | | collection_type | string | no | `"static"` (default) or `"smart"`; also implied by non-empty `auto_assign_rules` | | auto_assign_rules | array | no | rule objects, see below | | view_settings | object | no | per-device display preferences | ### Auto-assign rule object | Field | Type | Required | Notes | | ----- | ---- | -------- | ----- | | id | string | no | rule id | | field | string | yes | one of `genre`, `series`, `author`, `language`, `publisher`, `copyright_year`, `tags` | | operator | string | yes | one of `equals`, `not_equals`, `contains`, `not_contains`, `starts_with`, `ends_with`, `greater_than`, `less_than` | | value | string | yes | value to compare against | | priority | number | no | 1-10; higher values take precedence | | enabled | boolean | no | absent = enabled (rules written before this field existed keep matching) | ## Errors | Status | Body | When | | ------ | ---- | ---- | | 400 | `{"error": "..."}` | invalid JSON or validation failure | | 409 | `{"error": "a collection with this name already exists"}` | name taken | | 500 | `{"error": "..."}` | unexpected server error |