bruno: regenerate collection from canonical docs + permanent docs↔Bruno parity gate
WO4. The old collection was the drifted artifact AGENTS.md warned about:
bodies pre-truncated at their first {{var}}, routes renamed server-side
but not here (/api/notes/:media_id, /api/book-matching/search,
/api/collections/:id/rules/test), an orphan universal-progress suite for
routes that no longer exist.
scripts/gen_bruno_from_docs.py emits one OpenCollection request per
frontmatter'd endpoint doc (191 requests): gate-verified example-request
JSON as body, {{env}} params per the environment file, device-token
routes get an explicit Bearer {{device_token}} header, login/register/
refresh keep the token-capture after-response scripts that chain the
collection. Old 1:1 mirrors deleted (128); hand-authored NewDevDBSetup,
environments, and edge-case suites kept. 30 scenario files with
truncated bodies (the documented corruption) deleted — they could not
run.
internal/docs/drift_test.go gains TestBrunoMirrorsDocs: every
frontmatter'd doc must have a Bruno request with matching method+URL
shape — the collection can never silently drift from the docs again.
opencollection.yml README block replaced with the real run instructions.
make test green (9 pkgs, parity test included in internal/docs).
This commit is contained in:
1 parent
6fc501b35a
commit
acd82fff0a
353 files changed
+5165
-5293
No files matched your search
@@ -1,12 +0,0 @@
|
||||
info:
|
||||
name: Add Books to Collection
|
||||
type: http
|
||||
seq: 6
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"book_ids\": [\n \"{{book_id_1}}"
|
||||
docs: "## Add Books to Collection\n\n Adds multiple books to an existing collection.\n \n **Method:** POST\n \n **Endpoint:** /api/collections/{collection_id}/books\n \n **Authentication:** Required (Bearer token)\n \n **Path Parameters:**\n - `collection_id` (string): Collection ID\n \n **Request Body:**\n - `book_ids` (array of strings, required): List of book IDs to add\n \n **Response:**\n - `message` (string): Success message\n - `added_count` (integer): Number of books added\n \n **Status Codes:**\n - 200: Success\n - 400: Invalid request\n - 401: Unauthorized\n - 404: Collection not found"
|
||||
@@ -1,13 +0,0 @@
|
||||
info:
|
||||
name: Create Collection
|
||||
type: http
|
||||
seq: 1
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"name\": \"Science Fiction\",\n \"description\": \"My favorite sci-fi books\",\n \"color\": \"#ff0000\",\n \"icon\": \"\U0001F680\",\n \"auto_assign_rules\": [\n {\n \"id\": \"rule-1\",\n \"field\": \"genre\",\n \"operator\": \"equals\",\n \"value\": \"Science Fiction\",\n \"priority\": 8"
|
||||
docs: "## Create Collection\n\n Creates a new collection for organizing books.\n \n **Method:** POST\n \n **Endpoint:** /api/collections\n \n **Authentication:** Required (Bearer token)\n \n **Request Body:**\n - `name` (string, required): Collection name (max 100 chars)\n - `description` (string, optional): Collection description (max 500 chars)\n - `color` (string, optional): Hex color code (default #3498db)\n - `icon` (string, optional): Emoji icon (default \U0001F4DA)\n - `auto_assign_rules` (array, optional): Auto-assignment rules\n - `id` (string): Rule ID\n - `field` (string): Field to match (genre, author, series, etc.)\n - `operator` (string): Comparison operator (equals, contains, startsWith)\n - `value` (string): Value to match\n - `priority` (integer): Rule priority (1-10)\n \n **Response:**\n - Collection object with generated ID\n \n **Status Codes:**\n - 201: Created\n - 400: Invalid request\n - 401: Unauthorized\n - 409: Collection name\
|
||||
\ already exists"
|
||||
@@ -1,12 +0,0 @@
|
||||
info:
|
||||
name: Create Device Mapping
|
||||
type: http
|
||||
seq: 9
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/devices/{{device_id}}/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"collection_id\": \"{{collection_id}}"
|
||||
docs: "## Create Device Mapping\n\n Maps a collection to a device shelf for synchronization.\n \n **Method:** POST\n \n **Endpoint:** /api/devices/{device_id}/collections\n \n **Authentication:** Required (Bearer token)\n \n **Path Parameters:**\n - `device_id` (string): Device ID\n \n **Request Body:**\n - `collection_id` (string, required): Collection ID to map\n - `device_shelf_name` (string, optional): Custom shelf name on device\n - `sync_direction` (string, optional): sync direction (book_to_device, device_to_book, bidirectional)\n \n **Response:**\n - Mapping object with generated ID\n \n **Status Codes:**\n - 201: Created\n - 400: Invalid request\n - 401: Unauthorized\n - 404: Device or collection not found"
|
||||
@@ -1,30 +0,0 @@
|
||||
info:
|
||||
name: Delete Collection
|
||||
type: http
|
||||
seq: 5
|
||||
http:
|
||||
method: DELETE
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
|
||||
docs: |-
|
||||
## Delete Collection
|
||||
|
||||
Permanently deletes a collection and all its mappings.
|
||||
|
||||
**Method:** DELETE
|
||||
|
||||
**Endpoint:** /api/collections/{collection_id}
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Path Parameters:**
|
||||
- `collection_id` (string): Collection ID
|
||||
|
||||
**Response:**
|
||||
- `message` (string): Success message
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 401: Unauthorized
|
||||
- 404: Collection not found
|
||||
@@ -1,31 +0,0 @@
|
||||
info:
|
||||
name: Delete Device Mapping
|
||||
type: http
|
||||
seq: 11
|
||||
http:
|
||||
method: DELETE
|
||||
url: '{{base_url}}/api/devices/{{device_id}}/collections/{{mapping_id}}'
|
||||
auth: inherit
|
||||
|
||||
docs: |-
|
||||
## Delete Device Mapping
|
||||
|
||||
Removes a collection-to-device mapping.
|
||||
|
||||
**Method:** DELETE
|
||||
|
||||
**Endpoint:** /api/devices/{device_id}/collections/{mapping_id}
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Path Parameters:**
|
||||
- `device_id` (string): Device ID
|
||||
- `mapping_id` (string): Mapping ID
|
||||
|
||||
**Response:**
|
||||
- `message` (string): Success message
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 401: Unauthorized
|
||||
- 404: Device or mapping not found
|
||||
@@ -1,44 +0,0 @@
|
||||
info:
|
||||
name: Get Book Collections
|
||||
type: http
|
||||
seq: 12
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{base_url}}/api/collections/{{collection_id}}/books"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"collection_id": "{{collection_id}}"
|
||||
}
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
## Get Book Collections
|
||||
|
||||
Retrieves all collections that a specific book belongs to.
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**Endpoint:** /api/collections/{{collection_id}}/books
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Query Parameters:**
|
||||
- `book_id` (string, required): Book ID
|
||||
|
||||
**Response:**
|
||||
- Array of collection objects containing the book
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 400: Invalid request
|
||||
- 401: Unauthorized
|
||||
- 404: Book not found
|
||||
@@ -1,30 +0,0 @@
|
||||
info:
|
||||
name: Get Collection
|
||||
type: http
|
||||
seq: 3
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
|
||||
docs: |-
|
||||
## Get Collection
|
||||
|
||||
Retrieves detailed information about a specific collection.
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**Endpoint:** /api/collections/{collection_id}
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Path Parameters:**
|
||||
- `collection_id` (string): Collection ID
|
||||
|
||||
**Response:**
|
||||
- Collection object with all fields including books, rules, and mappings
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 401: Unauthorized
|
||||
- 404: Collection not found
|
||||
@@ -1,31 +0,0 @@
|
||||
info:
|
||||
name: Get Collections
|
||||
type: http
|
||||
seq: 2
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/collections?include_auto=true&sort_by=name'
|
||||
auth: inherit
|
||||
|
||||
docs: |-
|
||||
## Get Collections
|
||||
|
||||
Retrieves all collections for the authenticated user.
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**Endpoint:** /api/collections
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Query Parameters:**
|
||||
- `include_auto` (boolean, optional): Include auto-created collections (default false)
|
||||
- `sort_by` (string, optional): Sort field (name, created_at, book_count)
|
||||
- `order` (string, optional): Sort order (asc, desc)
|
||||
|
||||
**Response:**
|
||||
- Array of collection objects
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 401: Unauthorized
|
||||
@@ -1,30 +0,0 @@
|
||||
info:
|
||||
name: Get Device Mappings
|
||||
type: http
|
||||
seq: 8
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/devices/{{device_id}}/collections'
|
||||
auth: inherit
|
||||
|
||||
docs: |-
|
||||
## Get Device Mappings
|
||||
|
||||
Retrieves all collection mappings for a specific device.
|
||||
|
||||
**Method:** GET
|
||||
|
||||
**Endpoint:** /api/devices/{device_id}/collections
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Path Parameters:**
|
||||
- `device_id` (string): Device ID
|
||||
|
||||
**Response:**
|
||||
- Array of device mapping objects with collection details
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 401: Unauthorized
|
||||
- 404: Device not found
|
||||
@@ -1,31 +0,0 @@
|
||||
info:
|
||||
name: Remove Book from Collection
|
||||
type: http
|
||||
seq: 7
|
||||
http:
|
||||
method: DELETE
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books/{{book_id}}'
|
||||
auth: inherit
|
||||
|
||||
docs: |-
|
||||
## Remove Book from Collection
|
||||
|
||||
Removes a single book from a collection.
|
||||
|
||||
**Method:** DELETE
|
||||
|
||||
**Endpoint:** /api/collections/{collection_id}/books/{book_id}
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Path Parameters:**
|
||||
- `collection_id` (string): Collection ID
|
||||
- `book_id` (string): Book ID
|
||||
|
||||
**Response:**
|
||||
- `message` (string): Success message
|
||||
|
||||
**Status Codes:**
|
||||
- 200: Success
|
||||
- 401: Unauthorized
|
||||
- 404: Collection or book not found
|
||||
@@ -1,12 +0,0 @@
|
||||
info:
|
||||
name: Update Collection
|
||||
type: http
|
||||
seq: 4
|
||||
http:
|
||||
method: PUT
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"name\": \"Sci-Fi Favorites\",\n \"description\": \"Updated description\",\n \"color\": \"#00ff00\",\n \"icon\": \"⭐\",\n \"auto_assign_rules\": [\n {\n \"id\": \"rule-2\",\n \"field\": \"series\",\n \"operator\": \"equals\",\n \"value\": \"Foundation\",\n \"priority\": 9"
|
||||
docs: "## Update Collection\n\n Updates an existing collection's properties.\n \n **Method:** PUT\n \n **Endpoint:** /api/collections/{collection_id}\n \n **Authentication:** Required (Bearer token)\n \n **Path Parameters:**\n - `collection_id` (string): Collection ID\n \n **Request Body:**\n - `name` (string, optional): New collection name\n - `description` (string, optional): New description\n - `color` (string, optional): New hex color code\n - `icon` (string, optional): New emoji icon\n - `auto_assign_rules` (array, optional): Updated auto-assignment rules\n \n **Response:**\n - Updated collection object\n \n **Status Codes:**\n - 200: Success\n - 400: Invalid request\n - 401: Unauthorized\n - 404: Collection not found\n - 409: Collection name already exists"
|
||||
@@ -1,12 +0,0 @@
|
||||
info:
|
||||
name: Update Device Mapping
|
||||
type: http
|
||||
seq: 10
|
||||
http:
|
||||
method: PUT
|
||||
url: '{{base_url}}/api/devices/{{device_id}}/collections/{{mapping_id}}'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"device_shelf_name\": \"Science Fiction\",\n \"sync_direction\": \"book_to_device\""
|
||||
docs: "## Update Device Mapping\n\n Updates settings for a collection-to-device mapping.\n \n **Method:** PUT\n \n **Endpoint:** /api/devices/{device_id}/collections/{mapping_id}\n \n **Authentication:** Required (Bearer token)\n \n **Path Parameters:**\n - `device_id` (string): Device ID\n - `mapping_id` (string): Mapping ID\n \n **Request Body:**\n - `device_shelf_name` (string, optional): Custom shelf name on device\n - `sync_direction` (string, optional): Sync direction (book_to_device, device_to_book, bidirectional)\n \n **Response:**\n - Updated mapping object\n \n **Status Codes:**\n - 200: Success\n - 400: Invalid request\n - 401: Unauthorized\n - 404: Device or mapping not found"
|
||||
@@ -0,0 +1,31 @@
|
||||
info:
|
||||
name: Add Auto-Assign Rule
|
||||
type: http
|
||||
seq: 1
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"field": "genre",
|
||||
"operator": "equals",
|
||||
"value": "Science Fiction",
|
||||
"priority": 1,
|
||||
"enabled": true
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Add Auto-Assign Rule
|
||||
|
||||
`POST /api/collections/:id/rules` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/add_auto_assign_rule.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,34 @@
|
||||
info:
|
||||
name: Bulk Add Books
|
||||
type: http
|
||||
seq: 2
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/bulk-add-books'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"operations": [
|
||||
{
|
||||
"collection_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"book_ids": [
|
||||
"660e8400-e29b-41d4-a716-446655440001"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Bulk Add Books
|
||||
|
||||
`POST /api/collections/bulk-add-books` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/bulk_add_books.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,31 @@
|
||||
info:
|
||||
name: Bulk Assign Books
|
||||
type: http
|
||||
seq: 3
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"book_ids": [
|
||||
"660e8400-e29b-41d4-a716-446655440000",
|
||||
"770e8400-e29b-41d4-a716-446655440000",
|
||||
"880e8400-e29b-41d4-a716-446655440000"
|
||||
]
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Bulk Assign Books
|
||||
|
||||
`POST /api/collections/:id/books` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/bulk_assign.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,30 @@
|
||||
info:
|
||||
name: Bulk Remove Books
|
||||
type: http
|
||||
seq: 4
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books/bulk-remove'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"book_ids": [
|
||||
"550e8400-e29b-41d4-a716-446655440000",
|
||||
"660e8400-e29b-41d4-a716-446655440001"
|
||||
]
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Bulk Remove Books
|
||||
|
||||
`POST /api/collections/:id/books/bulk-remove` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/bulk_remove_books.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -1,16 +0,0 @@
|
||||
meta:
|
||||
name: Create Custom Section with Manual Books
|
||||
type: http
|
||||
seq: 2
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"library_id\": \"{{library_id}}\",\n \"name\": \"My Favorites\",\n \"icon\": \"⭐\",\n \"description\": \"My favorite books\",\n \"show_on_dashboard\": true,\n \"auto_assign_rules\": \"\",\n \"manual_book_ids\": [\"{{media_item_id}}\"],\n \"match_type\": \"all\"\n}"
|
||||
runtime:
|
||||
scripts:
|
||||
- type: after-response
|
||||
code: "function onResponse(res) {\ntest(\"status must be 201 with valid request\", function() {\n expect(res.status).to.eql(201);\n});\n\ntest(\"response contains collection id\", function() {\n expect(res.body.id).to.exist;\nexpect(res.body.id).to.be.a('string');\n });\n\ntest(\"response contains collection name\", function() {\n expect(res.body.name).to.eql(\"My Favorites\");\n });\n}"
|
||||
docs: "Create a custom collection with manually selected books.\n\n**Endpoint**: POST /api/collections\n**Auth**: Required (Bearer token)\n\n## Example Request\n\n```json\n{\n \"library_id\": \"cc23c3a7-f8fb-451a-a78d-2a16df1b725a\",\n \"name\": \"My Favorites\",\n \"icon\": \"⭐\",\n \"description\": \"My favorite books\",\n \"show_on_dashboard\": true,\n \"auto_assign_rules\": \"\",\n \"manual_book_ids\": [\"book-id-1\", \"book-id-2\"],\n \"match_type\": \"all\"\n}\n```\n\n## Response\n\nReturns the created collection with generated ID."
|
||||
@@ -1,19 +0,0 @@
|
||||
meta:
|
||||
name: Create Custom Section Missing Required Fields
|
||||
type: http
|
||||
seq: 3
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"library_id\": \"{{library_id}}\",\n \"icon\": \"\U0001F4DA\"\n}"
|
||||
runtime:
|
||||
scripts:
|
||||
- type: after-response
|
||||
code: "function onResponse(res) {\ntest(\"status must be 400 with missing name\", function() {\n expect(res.status).to.eql(400);\n});\n\ntest(\"response contains error message\", function() {\n expect(res.body.error).to.exist;\n });\n}"
|
||||
docs: 'Test error handling when creating a collection without required fields.
|
||||
|
||||
|
||||
**Expected Response**: 400 Bad Request with error message.'
|
||||
@@ -1,17 +0,0 @@
|
||||
meta:
|
||||
name: Create Custom Section with Filter Rules
|
||||
type: http
|
||||
seq: 1
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"library_id\": \"{{library_id}}\",\n \"name\": \"Science Fiction Books\",\n \"icon\": \"\U0001F680\",\n \"description\": \"All my sci-fi books\",\n \"show_on_dashboard\": true,\n \"auto_assign_rules\": \"{\\\"rules\\\":[{\\\"id\\\":\\\"rule1\\\",\\\"field\\\":\\\"genre\\\",\\\"operator\\\":\\\"equals\\\",\\\"value\\\":\\\"Sci-Fi\\\",\\\"priority\\\":1}]}\",\n \"manual_book_ids\": [],\n \"match_type\": \"all\"\n}"
|
||||
runtime:
|
||||
scripts:
|
||||
- type: after-response
|
||||
code: "function onResponse(res) {\ntest(\"status must be 201 with valid request\", function() {\n expect(res.status).to.eql(201);\n});\n\ntest(\"response contains collection id\", function() {\n expect(res.body.id).to.exist;\nexpect(res.body.id).to.be.a('string');\n });\n\ntest(\"response contains collection name\", function() {\n expect(res.body.name).to.eql(\"Science Fiction Books\");\n });\n\ntest(\"response contains is_system false\", function() {\n expect(res.body.is_system).to.exist;\n expect(res.body.is_system).to.eql(false);\n });\n}"
|
||||
docs: "Create a custom collection with filter rules.\n\n**Endpoint**: POST /api/collections\n**Auth**: Required (Bearer token)\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| library_id | string | Yes | Library UUID |\n| name | string | Yes | Collection name |\n| icon | string | No | Emoji icon |\n| description | string | No | Collection description |\n| show_on_dashboard | boolean | No | Show on dashboard (default: true) |\n| auto_assign_rules | string | No | JSON string of filter rules |\n| manual_book_ids | array | No | Array of book IDs |\n| match_type | string | No | \"all\" (AND) or \"any\" (OR) |\n\n## Example Request\n\n```json\n{\n \"library_id\": \"cc23c3a7-f8fb-451a-a78d-2a16df1b725a\",\n \"name\": \"Science Fiction Books\",\n \"icon\": \"\U0001F680\",\n \"description\": \"All my sci-fi books\",\n \"show_on_dashboard\": true,\n \"auto_assign_rules\": \"{\\\"rules\\\":[{\\\"id\\\":\\\"rule1\\\",\\\"field\\\":\\\
|
||||
\"genre\\\",\\\"operator\\\":\\\"equals\\\",\\\"value\\\":\\\"Sci-Fi\\\",\\\"priority\\\":1}]}\",\n \"manual_book_ids\": [],\n \"match_type\": \"all\"\n}\n```\n\n## Response\n\nReturns the created collection with generated ID."
|
||||
@@ -0,0 +1,33 @@
|
||||
info:
|
||||
name: Create Collection
|
||||
type: http
|
||||
seq: 5
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"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" } }
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Create Collection
|
||||
|
||||
`POST /api/collections` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/create_collection.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,29 @@
|
||||
info:
|
||||
name: Create Shelf Mapping
|
||||
type: http
|
||||
seq: 6
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/devices/{{collection_id}}/collections'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"collection_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"device_shelf_name": "Sci-Fi",
|
||||
"sync_direction": "bidirectional"
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Create Shelf Mapping
|
||||
|
||||
`POST /api/devices/:id/collections` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/create_shelf_mapping.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,21 @@
|
||||
info:
|
||||
name: Delete Collection
|
||||
type: http
|
||||
seq: 7
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Delete Collection
|
||||
|
||||
`DELETE /api/collections/:id` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/delete_collection.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,21 @@
|
||||
info:
|
||||
name: Delete Shelf Mapping
|
||||
type: http
|
||||
seq: 8
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: '{{base_url}}/api/devices/{{collection_id}}/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Delete Shelf Mapping
|
||||
|
||||
`DELETE /api/devices/:id/collections/:collectionId` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/delete_shelf_mapping.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,21 @@
|
||||
info:
|
||||
name: Get Collection
|
||||
type: http
|
||||
seq: 9
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Get Collection
|
||||
|
||||
`GET /api/collections/:id` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/get_collection.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,21 @@
|
||||
info:
|
||||
name: Get Book Collections
|
||||
type: http
|
||||
seq: 10
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books'
|
||||
auth: inherit
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Get Book Collections
|
||||
|
||||
`GET /api/collections/:id/books` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/get_collection_books.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,21 @@
|
||||
info:
|
||||
name: List Collections
|
||||
type: http
|
||||
seq: 11
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: '{{base_url}}/api/collections'
|
||||
auth: inherit
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# List Collections
|
||||
|
||||
`GET /api/collections` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/list_collections.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -1,16 +0,0 @@
|
||||
meta:
|
||||
name: Preview Collection
|
||||
type: http
|
||||
seq: 1
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/preview'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"library_id\": \"{{library_id}}\",\n \"rules\": [\n{\n \"id\": \"rule1\",\n \"field\": \"genre\",\n\"operator\": \"equals\",\n \"value\": \"Fiction\",\n\"priority\": 1\n }\n ],\n \"manual_book_ids\": [],\n \"limit\": 20\n}"
|
||||
runtime:
|
||||
scripts:
|
||||
- type: after-response
|
||||
code: "function onResponse(res) {\ntest(\"status must be 200 with valid request\", function() {\n expect(res.status).to.eql(200);\n});\n\ntest(\"response contains items array\", function() {\n expect(res.body.items).to.exist;\nexpect(res.body.items).to.be.an('array');\n });\n}"
|
||||
docs: "Preview collection with filter rules before saving.\n\n**Endpoint**: POST /api/collections/preview\n**Auth**: Required (Bearer token)\n\n## Request Body\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| library_id | string | Yes | Library UUID |\n| rules | array | No | Filter rules to evaluate |\n| manual_book_ids | array | No | Manually selected book IDs |\n| limit | int | No | Max items to return (default: 20, max: 100) |\n\n## Example Request\n\n```json\n{\n \"library_id\": \"cc23c3a7-f8fb-451a-a78d-2a16df1b725a\",\n \"rules\": [\n {\n \"id\": \"rule1\",\n \"field\": \"genre\",\n \"operator\": \"equals\",\n \"value\": \"Fiction\",\n \"priority\": 1\n }\n ],\n \"manual_book_ids\": [],\n \"limit\": 20\n}\n```\n\n## Response\n\nReturns array of matching book items.\n\nThis endpoint is used by the Custom Section Builder to show users what books will match their filter rules before they save the collection."
|
||||
@@ -0,0 +1,30 @@
|
||||
info:
|
||||
name: Preview Collection
|
||||
type: http
|
||||
seq: 12
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/preview'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"library_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"rules": [],
|
||||
"manual_book_ids": [],
|
||||
"limit": 20
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Preview Collection
|
||||
|
||||
`POST /api/collections/preview` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/preview_collection.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,21 @@
|
||||
info:
|
||||
name: Remove Auto-Assign Rule
|
||||
type: http
|
||||
seq: 13
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/rules/{{rule_id}}'
|
||||
auth: inherit
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Remove Auto-Assign Rule
|
||||
|
||||
`DELETE /api/collections/:id/rules/:ruleId` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/remove_auto_assign_rule.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,30 @@
|
||||
info:
|
||||
name: Reorder Collection Items
|
||||
type: http
|
||||
seq: 14
|
||||
|
||||
http:
|
||||
method: PUT
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/items/order'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"item_ids": [
|
||||
"550e8400-e29b-41d4-a716-446655440000",
|
||||
"660e8400-e29b-41d4-a716-446655440001"
|
||||
]
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Reorder Collection Items
|
||||
|
||||
`PUT /api/collections/:id/items/order` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/reorder_items.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -1,18 +0,0 @@
|
||||
info:
|
||||
name: Bulk Add Books to Collections
|
||||
type: http
|
||||
seq: 1
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/bulk-add-books'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"operations\": [\n {\n \"collection_id\": \"{{collectionId1"
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Bulk Add Books to Collections\n\n Adds multiple books to multiple collections in a single request. Each operation specifies a collection and a list of books to add.\n\n **Method:** POST\n\n **Endpoint:** /api/collections/bulk-add-books\n\n **Authentication:** Bearer token\n\n **Request Body:**\n - `operations` (array): Array of collection-book operations\n - `collection_id` (string): Collection UUID\n - `book_ids` (array): Array of book UUIDs to add to the collection\n\n **Response:**\n - `results` (array): Results for each operation\n - `total` (number): Total number of operations\n - `success` (number): Number of successful operations\n - `failed` (number): Number of failed operations\n\n **Status Codes:**\n - 200: Success (with partial results if some failed)\n - 400: Invalid request data\n - 401: Unauthorized\n - 403: Forbidden\n - 500: Internal server error\n\n **Example:**\n ```json\n {\n \"operations\": [\n {\n \"collection_id\":\
|
||||
\ \"collection-uuid-1\",\n \"book_ids\": [\"book-1\", \"book-2\"]"
|
||||
@@ -1,15 +0,0 @@
|
||||
info:
|
||||
name: Bulk Remove Books - All Books
|
||||
type: http
|
||||
seq: 5
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books/bulk-remove'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"book_ids\": [\n \"{{bookId1"
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
docs: "## Bulk Remove Books from Collection\n\n Removes multiple books from a collection in a single request.\n\n **Method:** POST\n\n **Endpoint:** /api/collections/{collection_id"
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Bulk Remove Books - Empty List
|
||||
type: http
|
||||
seq: 2
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books/bulk-remove'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"book_ids\": []"
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Bulk Remove Books - Empty List Validation\n\n Tests validation behavior when providing an empty book_ids array.\n\n **Expected Result:** 400 Bad Request\n\n **Validation Rule:** book_ids array must contain at least one book UUID.\n\n **Purpose:** Ensures the API properly validates input and rejects empty removal requests."
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Bulk Remove Books - Invalid IDs
|
||||
type: http
|
||||
seq: 4
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books/bulk-remove'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"book_ids\": [\n \"{{bookId1"
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Bulk Remove Books - Invalid IDs\n\n Tests behavior when the book_ids array contains invalid UUID formats or non-existent books.\n\n **Expected Result:** 200 OK with partial success\n\n **Purpose:** Verifies that:\n - Invalid UUID formats don't crash the endpoint\n - Non-existent book IDs are handled gracefully\n - Valid IDs in the same request are still processed\n - Response includes detailed results showing which succeeded/failed\n\n **Note:** The endpoint should process all valid IDs and report failures for invalid ones, allowing clients to handle partial failures appropriately."
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Bulk Remove Books - Single Book
|
||||
type: http
|
||||
seq: 3
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/books/bulk-remove'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"book_ids\": [\n \"{{bookId1"
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Bulk Remove Books - Single Book\n\n Tests that bulk remove endpoint works correctly with a single book.\n\n **Expected Result:** 200 OK with removed: 1, total: 1\n\n **Purpose:** Verifies the bulk remove endpoint handles single-item arrays correctly, providing flexibility for clients to use the same endpoint for both single and multiple removals.\n\n **Note:** Using bulk remove for a single book is functionally equivalent to the single remove endpoint but allows for consistent error handling and response format."
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Test Collection Rules - Author Contains
|
||||
type: http
|
||||
seq: 2
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/test-rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"rules\": [\n {\n \"field\": \"author\",\n \"operator\": \"contains\",\n \"value\": \"Asimov\""
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Test Collection Rules - Author Contains\n\n Tests the \"contains\" operator on the author field to find books by a specific author (partial match).\n\n **Example Use Case:** Finding all books by an author whose name contains \"Asimov\" (e.g., \"Isaac Asimov\").\n\n **Operator:** `contains` - Matches if the field contains the specified value as a substring (case-insensitive typically).\n\n **Expected Result:** Returns all books where the author field contains \"Asimov\".\n\n **Purpose:** Demonstrates text-based partial matching for author searches, useful when you don't need the exact author name or want to find books by authors with similar names."
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Test Collection Rules - Copyright Year Greater Than
|
||||
type: http
|
||||
seq: 3
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/test-rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"rules\": [\n {\n \"field\": \"copyright_year\",\n \"operator\": \"greater_than\",\n \"value\": \"2000\""
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Test Collection Rules - Copyright Year Greater Than\n\n Tests the \"greater_than\" operator on the copyright_year field to find books published after a specific year.\n\n **Example Use Case:** Creating a \"Modern Books\" collection with books published after 2000.\n\n **Operator:** `greater_than` - Matches if the field value is greater than the specified value (numeric comparison).\n\n **Field:** `copyright_year` - The year the book was copyrighted/published.\n\n **Expected Result:** Returns all books with copyright_year greater than 2000 (i.e., published in 2001 or later).\n\n **Purpose:** Demonstrates numeric comparison operators for creating date-based collections, useful for organizing books by publication era."
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Test Collection Rules - Empty Rules Array
|
||||
type: http
|
||||
seq: 5
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/test-rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"rules\": []"
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Test Collection Rules - Empty Rules Array\n\n Tests validation behavior when providing an empty rules array.\n\n **Expected Result:** 400 Bad Request\n\n **Validation Rule:** rules array must contain at least one rule object.\n\n **Purpose:** Ensures the API properly validates input and rejects empty rule sets, preventing accidental queries that would return all books or cause performance issues.\n\n **Use Case:** Client-side validation should prevent sending empty rules, but the API should also validate to catch malformed requests."
|
||||
@@ -1,17 +0,0 @@
|
||||
info:
|
||||
name: Test Collection Rules - No Matches
|
||||
type: http
|
||||
seq: 4
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/test-rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"rules\": [\n {\n \"field\": \"genre\",\n \"operator\": \"equals\",\n \"value\": \"NonExistentGenre123456\""
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Test Collection Rules - No Matches\n\n Tests behavior when collection rules don't match any books in the library.\n\n **Example Use Case:** Validating that a new genre name doesn't exist before creating a collection for it, or testing edge cases.\n\n **Expected Result:** 200 OK with empty matches array and total: 0\n\n **Purpose:** Verifies that the API handles zero-match scenarios gracefully:\n - Returns 200 (success) not 404\n - Returns empty array, not null\n - Returns total: 0 for clarity\n - No errors thrown for no results\n\n **Note:** An empty result set is a valid response and doesn't indicate an error. This allows users to test rules confidently before creating collections."
|
||||
@@ -1,18 +0,0 @@
|
||||
info:
|
||||
name: Test Collection Rules
|
||||
type: http
|
||||
seq: 1
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/test-rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: "{\n \"rules\": [\n {\n \"field\": \"genre\",\n \"operator\": \"equals\",\n \"value\": \"Science Fiction\""
|
||||
headers:
|
||||
- key: Content-Type
|
||||
value: application/json
|
||||
- key: Authorization
|
||||
value: Bearer {{authToken
|
||||
docs: "## Test Collection Rules\n\n Tests collection rules against the library to see which books match, without creating a collection. Useful for previewing what books would be included in a collection with specific rules.\n\n **Method:** POST\n\n **Endpoint:** /api/collections/test-rules\n\n **Authentication:** Bearer token\n\n **Request Body:**\n - `rules` (array): Array of rule objects to test\n - `field` (string): Field to test (genre, author, copyright_year, tags, etc.)\n - `operator` (string): Comparison operator\n - `equals`: Exact match\n - `contains`: Contains substring (for text fields)\n - `greater_than`: Greater than (for numeric fields)\n - `less_than`: Less than (for numeric fields)\n - `not_equals`: Not equal to\n - `starts_with`: Starts with\n - `ends_with`: Ends with\n - `is_empty`: Field is empty or null\n - `is_not_empty`: Field is not empty and not null\n - `value` (string): Value to compare against (not required\
|
||||
\ for is_empty/is_not_empty)\n\n **Response:**\n - `matches` (array): Array of matching books\n - `id` (string): Book UUID\n - `title` (string): Book title\n - `author` (string): Book author\n - `genre` (string): Book genre\n - Additional book metadata\n - `total` (number): Total number of matching books\n\n **Status Codes:**\n - 200: Success - returns matching books\n - 400: Invalid request (empty rules array, invalid field/operator)\n - 401: Unauthorized\n - 500: Internal server error\n\n **Example Request:**\n ```json\n {\n \"rules\": [\n {\n \"field\": \"genre\",\n \"operator\": \"equals\",\n \"value\": \"Science Fiction\""
|
||||
@@ -0,0 +1,38 @@
|
||||
info:
|
||||
name: Test Rule
|
||||
type: http
|
||||
seq: 15
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/collections/test-rules'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"field": "genre",
|
||||
"operator": "equals",
|
||||
"value": "Science Fiction"
|
||||
},
|
||||
{
|
||||
"field": "author",
|
||||
"operator": "contains",
|
||||
"value": "Asimov"
|
||||
}
|
||||
]
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Test Rule
|
||||
|
||||
`POST /api/collections/test-rules` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/test_rule.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,34 @@
|
||||
info:
|
||||
name: Update Collection
|
||||
type: http
|
||||
seq: 16
|
||||
|
||||
http:
|
||||
method: PUT
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"name": "To Read (2026)",
|
||||
"description": "Updated description",
|
||||
"color": "#33CCFF",
|
||||
"icon": "📚",
|
||||
"auto_assign_rules": [],
|
||||
"view_settings": { "hide_finished": true },
|
||||
"hide_finished": ["true"],
|
||||
"show_up_next": ["true"]
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Update Collection
|
||||
|
||||
`PUT /api/collections/:id` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/update_collection.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
@@ -0,0 +1,27 @@
|
||||
info:
|
||||
name: Update Collection Rule
|
||||
type: http
|
||||
seq: 17
|
||||
|
||||
http:
|
||||
method: PUT
|
||||
url: '{{base_url}}/api/collections/{{collection_id}}/rules/{{rule_id}}'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"enabled": false
|
||||
}
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
|
||||
docs: |-
|
||||
# Update Collection Rule
|
||||
|
||||
`PUT /api/collections/:id/rules/:ruleId` — auth: jwt.
|
||||
|
||||
Canonical reference: `docs/developer/api/collections/update_rule.md` (docs site → Developer → API). This request is GENERATED from that doc; edit the doc, not this file.
|
||||
Reference in new issue
Block a user