docs: add Carousel dashboard implementation plan

This commit is contained in:
2026-02-17 17:00:46 -05:00
parent fce16b53f7
commit 96730d9475
407 changed files with 10834 additions and 10983 deletions
-65
View File
@@ -1,65 +0,0 @@
meta {
name: Add Books to Kobo Shelf
type: http
seq: 1
}
post {
url: {{baseURL}}/api/devices/{{deviceID}}/shelves
body: json
auth: inherit
}
headers {
Authorization: Bearer {{userToken}}
Content-Type: application/json
}
body:json {
{
"media_item_ids": [
"{{bookUUID1}}",
"{{bookUUID2}}"
],
"shelf_name": "Reading List",
"shelf_position": 0
}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Add Books to Kobo Shelf
Add one or more books to a Kobo device shelf. Manages which books should be synced to a specific Kobo device. Supports multiple shelves for organization.
**Method:** POST
**Endpoint:** /api/devices/{deviceID}/shelves
**Authentication:** Bearer token
**Path Parameters:**
- `deviceID` (string): Device UUID
**Request Body:**
- `media_item_ids` (array): Array of book UUIDs to add
- `shelf_name` (string): Name of the shelf (e.g., "Reading List", "Favorites")
- `shelf_position` (number, optional): Position on the shelf (default: 0)
**Response:**
- `message` (string): Success message
- `added_count` (number): Number of books added
**Status Codes:**
- 200: Success - books added to shelf
- 400: Invalid request data
- 401: Unauthorized
- 404: Device or one or more books not found
- 500: Internal server error
**Note:** Adding a book that's already on the shelf updates its position if a new position is specified. Supports multiple shelves for organizing content on the Kobo device.
}
@@ -1,44 +0,0 @@
meta {
name: Approve Device Registration
type: http
seq: 6
}
get {
url: {{base_url}}/api/devices/approve/{{registration_id}}
body: none
auth: inherit
}
docs {
## Approve Device Registration
Approves a pending device registration request.
**Method:** GET
**Endpoint:** /api/devices/approve/:registration_id
**Authentication:** Bearer token
**Path Parameters:**
- `registration_id` (string): Registration request UUID
**Response:**
- Success message with approved device details
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 404: Registration not found
- 400: Invalid registration status
**Example Response:**
```json
{
"message": "Device registration approved",
"device_id": "uuid",
"device_name": "My Kobo"
}
```
}
@@ -1,17 +0,0 @@
meta {
name: Check Registration Status
type: http
seq: 2
}
post {
url: {{base_url}}/api/devices/register/status
body: json
auth: none
}
body:json {
{
"registration_id": "{{registrationId}}"
}
}
-50
View File
@@ -1,50 +0,0 @@
meta {
name: Clear Kobo Shelf
type: http
seq: 1
}
delete {
url: {{baseURL}}/api/devices/{{deviceID}}/shelves/clear?shelf={{shelfName}}
body: none
auth: inherit
}
headers {
Authorization: Bearer {{userToken}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Clear Kobo Shelf
Clear all books from a Kobo device shelf, or all shelves if no shelf name is specified.
**Method:** DELETE
**Endpoint:** /api/devices/{deviceID}//shelves/clear?shelf={shelfName}
**Authentication:** Bearer token
**Path Parameters:**
- `deviceID` (string): Device UUID
**Query Parameters:**
- `shelf` (string, optional): Shelf name to clear. If omitted, clears all shelves.
**Response:**
- `message` (string): Success message
- `cleared_count` (number): Number of books removed from shelf
**Status Codes:**
- 200: Success - shelf cleared
- 401: Unauthorized
- 404: Device not found
- 500: Internal server error
**Note:** Removes all books from the specified shelf. If no shelf name is provided, clears all shelves for the device. This operation cannot be undone.
}
@@ -1,97 +0,0 @@
meta {
name: Create Device File Alias
type: http
seq: 1
}
post {
url: {{base_url}}/api/devices/{{device_id}}/file-aliases
body: json
auth: inherit
}
body:json {
{
"file_path": "/mnt/sd/books/my-book.kepub.epub",
"media_item_id": "{{media_item_id}}"
}
}
headers {
Content-Type: application/json
}
tests {
test_create_device_file_alias_success(status, headers, body) {
if (status !== 201 && status !== 200) {
throw new Error("Expected status 201 or 200, got " + status);
}
const contentType = headers["content-type"];
if (!contentType || !contentType.includes("application/json")) {
throw new Error("Expected content-type to contain application/json");
}
let data;
try {
data = JSON.parse(body);
} catch (e) {
throw new Error("Response body is not valid JSON");
}
if (!data.id) {
throw new Error("Response missing id field");
}
if (!data.file_path) {
throw new Error("Response missing file_path field");
}
return true;
}
}
vars:pre-request {
deviceId: "8821b703-1234-5678-9123-446655440002"
mediaItemId: "8821b703-1234-5678-9123-446655440001"
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Create Device File Alias
Creates a new file alias for a device. File aliases map device-specific file paths to media items.
**Method:** POST
**Endpoint:** /api/devices/:id/file-aliases
**Authentication:** Required (Bearer token)
**Path Parameters:**
- `id` (string, required): Device UUID
**Request Body:**
- `file_path` (string, required): Device-specific file path
- `media_item_id` (string, required): Media item UUID to link to
**Response:** Created file alias object
- `id` (string): Alias UUID
- `device_id` (string): Device UUID
- `file_path` (string): Device-specific file path
- `media_item_id` (string): Associated media item UUID
- `created_at` (string): Creation timestamp
- `updated_at` (string): Last update timestamp
**Status Codes:**
- 201: Created
- 200: Success
- 400: Invalid request body
- 401: Unauthorized
- 404: Device not found
- 500: Internal server error
}
-45
View File
@@ -1,45 +0,0 @@
meta {
name: Delete Device
type: http
seq: 6
}
delete {
url: {{base_url}}/api/devices/{{deviceId}}
body: none
auth: inherit
}
headers {
Authorization: Bearer {{token}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Delete Device
Deletes a device and unregisters it from the user's account.
**Method:** DELETE
**Endpoint:** /api/devices/{deviceId}
**Authentication:** Bearer token
**Path Parameters:**
- `deviceId` (string): Device UUID
**Response:** 204 No Content on success
**Status Codes:**
- 204: Success - device deleted
- 401: Unauthorized
- 404: Device not found
- 500: Internal server error
**Note:** This action cannot be undone. All device data and sync history will be removed.
}
-78
View File
@@ -1,78 +0,0 @@
meta {
name: Get Device File Aliases
type: http
seq: 1
}
get {
url: {{base_url}}/api/devices/{{device_id}}/file-aliases
auth: inherit
}
headers {
Content-Type: application/json
}
tests {
test_get_device_file_aliases_success(status, headers, body) {
if (status !== 200) {
throw new Error("Expected status 200, got " + status);
}
const contentType = headers["content-type"];
if (!contentType || !contentType.includes("application/json")) {
throw new Error("Expected content-type to contain application/json");
}
let data;
try {
data = JSON.parse(body);
} catch (e) {
throw new Error("Response body is not valid JSON");
}
if (!Array.isArray(data)) {
throw new Error("Expected response body to be an array");
}
return true;
}
}
vars:pre-request {
deviceId: "8821b703-1234-5678-9123-446655440002"
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Get Device File Aliases
Retrieves all file aliases for a specific device. File aliases are used to map device-specific file paths to media items.
**Method:** GET
**Endpoint:** /api/devices/:id/file-aliases
**Authentication:** Required (Bearer token)
**Path Parameters:**
- `id` (string, required): Device UUID
**Response:** Array of file alias objects
- `id` (string): Alias UUID
- `device_id` (string): Device UUID
- `file_path` (string): Device-specific file path
- `media_item_id` (string): Associated media item UUID
- `created_at` (string): Creation timestamp
- `updated_at` (string): Last update timestamp
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 404: Device not found
- 500: Internal server error
}
-50
View File
@@ -1,50 +0,0 @@
meta {
name: Get Device
type: http
seq: 4
}
get {
url: {{base_url}}/api/devices/{{deviceId}}
body: none
auth: inherit
}
headers {
Authorization: Bearer {{token}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Get Device
Retrieves detailed information about a specific device.
**Method:** GET
**Endpoint:** /api/devices/{deviceId}
**Authentication:** Bearer token
**Path Parameters:**
- `deviceId` (string): Device UUID
**Response:**
- `id` (string): Device UUID
- `name` (string): Device name
- `device_type` (string): Type (kobo, koreader, web)
- `last_sync` (string): Last sync timestamp
- `is_active` (boolean): Whether device is active
- `created_at` (string): Registration timestamp
- `sync_settings` (object): Device-specific sync settings
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 404: Device not found
- 500: Internal server error
}
-56
View File
@@ -1,56 +0,0 @@
meta {
name: Get Kobo Shelf Books
type: http
seq: 1
}
get {
url: {{baseURL}}/api/devices/{{deviceID}}/shelves?shelf={{shelfName}}
body: none
auth: inherit
}
headers {
Authorization: Bearer {{userToken}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Get Kobo Shelf Books
Get all books on a Kobo device shelf, optionally filter by shelf name.
**Method:** GET
**Endpoint:** /api/devices/{deviceID}/shelves?shelf={shelfName}
**Authentication:** Bearer token
**Path Parameters:**
- `deviceID` (string): Device UUID
**Query Parameters:**
- `shelf` (string, optional): Shelf name to filter by. If omitted, returns all shelves.
**Response:**
- Array of books with:
- `id` (string): Book UUID
- `title` (string): Book title
- `author` (string): Book author
- `shelf_name` (string): Name of the shelf
- `shelf_position` (number): Position on the shelf
- `entitlement_id` (string): Kobo entitlement ID
- `revision_id` (string): Kobo revision number
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 404: Device not found
- 500: Internal server error
**Note:** Returns Kobo-specific metadata (entitlement ID, revision number) required for proper Kobo sync operations.
}
@@ -1,19 +0,0 @@
meta {
name: Initiate Device Registration
type: http
seq: 1
}
post {
url: {{base_url}}/api/devices/register
body: json
auth: none
}
body:json {
{
"device_name": "My Kindle Paperwhite",
"device_type": "koreader",
"device_identifier": "kindle-pw5-hardware-id-12345"
}
}
-46
View File
@@ -1,46 +0,0 @@
meta {
name: List Devices
type: http
seq: 3
}
get {
url: {{base_url}}/api/devices
body: none
auth: inherit
}
headers {
Authorization: Bearer {{token}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## List Devices
Lists all devices registered to the authenticated user's account.
**Method:** GET
**Endpoint:** /api/devices
**Authentication:** Bearer token
**Response:**
- `devices` (array): Array of device objects
- `id` (string): Device UUID
- `name` (string): Device name
- `device_type` (string): Type (kobo, koreader, web)
- `last_sync` (string): Last sync timestamp
- `is_active` (boolean): Whether device is active
- `created_at` (string): Registration timestamp
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 500: Internal server error
}
@@ -1,43 +0,0 @@
meta {
name: List Pending Device Registrations
type: http
seq: 5
}
get {
url: {{base_url}}/api/devices/pending
body: none
auth: inherit
}
docs {
## List Pending Device Registrations
Retrieves all pending device registration requests awaiting approval.
**Method:** GET
**Endpoint:** /api/devices/pending
**Authentication:** Bearer token
**Response:**
- Array of pending device registrations
**Status Codes:**
- 200: Success
- 401: Unauthorized
**Example Response:**
```json
[
{
"id": "uuid",
"device_name": "My Kobo",
"device_type": "kobo",
"user_id": "uuid",
"created_at": "2024-01-01T00:00:00Z"
}
]
```
}
@@ -1,42 +0,0 @@
meta {
name: Reject Device Registration
type: http
seq: 7
}
post {
url: {{base_url}}/api/devices/reject/{{registration_id}}
body: none
auth: inherit
}
docs {
## Reject Device Registration
Rejects a pending device registration request.
**Method:** POST
**Endpoint:** /api/devices/reject/:registration_id
**Authentication:** Bearer token
**Path Parameters:**
- `registration_id` (string): Registration request UUID
**Response:**
- Success message confirming rejection
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 404: Registration not found
- 400: Invalid registration status
**Example Response:**
```json
{
"message": "device registration rejected"
}
```
}
@@ -1,49 +0,0 @@
meta {
name: Remove Book from Kobo Shelf
type: http
seq: 1
}
delete {
url: {{baseURL}}/api/devices/{{deviceID}}/shelves?media_item_id={{bookUUID}}
body: none
auth: inherit
}
headers {
Authorization: Bearer {{userToken}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Remove Book from Kobo Shelf
Remove a specific book from a Kobo device shelf, preventing it from syncing to that device.
**Method:** DELETE
**Endpoint:** /api/devices/{deviceID}/shelves?media_item_id={bookUUID}
**Authentication:** Bearer token
**Path Parameters:**
- `deviceID` (string): Device UUID
**Query Parameters:**
- `media_item_id` (string): Book UUID to remove from shelf
**Response:**
- `message` (string): Success message
**Status Codes:**
- 200: Success - book removed from shelf
- 401: Unauthorized
- 404: Device or book not found
- 500: Internal server error
**Note:** Removing a book from the device shelf prevents it from syncing to that device in future sync operations.
}
-20
View File
@@ -1,20 +0,0 @@
meta {
name: Update Device
type: http
seq: 5
}
put {
url: {{base_url}}/api/devices/{{deviceId}}
body: json
auth: inherit
}
body:json {
{
"device_name": "My Updated Kindle",
"sync_enabled": true,
"auto_sync": true,
"sync_frequency_minutes": 10
}
}
-134
View File
@@ -1,134 +0,0 @@
meta {
name: "Bookhoard Device Management API"
type: "collection"
environment: {
development: {
base_url: "http://localhost:8765/api"
},
production: {
base_url: "https://your-domain.com/api"
}
}
}
# Register Device
@name("Register Device")
POST {{environment.base_url}}/devices/register
Content-Type: application/json
{
"device_name": "My Kobo Clara",
"device_type": "kobo",
"device_identifier": "N1234567890123"
}
@name("Register KOReader Device")
POST {{environment.base_url}}/devices/register
Content-Type: application/json
{
"device_name": "My Kindle Paperwhite",
"device_type": "koreader",
"device_identifier": "G090GP123456789"
}
@name("Register Web Device")
POST {{environment.base_url}}/devices/register
Content-Type: application/json
{
"device_name": "Chrome Browser",
"device_type": "web",
"device_identifier": "web-client-abc123"
}
# Check Registration Status
@name("Check Pending Registration")
POST {{environment.base_url}}/devices/register/status
Content-Type: application/json
{
"registration_id": "registration-uuid-here"
}
@name("Check Approved Registration")
POST {{environment.base_url}}/devices/register/status
Content-Type: application/json
{
"registration_id": "registration-uuid-here"
}
# List Devices (requires authentication)
@name("List User Devices")
GET {{environment.base_url}}/devices
Authorization: Bearer {{jwt_token}}
@name("Get Device Details")
GET {{environment.base_url}}/devices/{{device_id}}
Authorization: Bearer {{jwt_token}}
# Update Device Settings
@name("Update Device Settings")
PUT {{environment.base_url}}/devices/{{device_id}}
Authorization: Bearer {{jwt_token}}
Content-Type: application/json
{
"device_name": "Updated Device Name",
"sync_enabled": true,
"auto_sync": true,
"sync_frequency_minutes": 10
}
@name("Disable Device Sync")
PUT {{environment.base_url}}/devices/{{device_id}}
Authorization: Bearer {{jwt_token}}
Content-Type: application/json
{
"device_name": "My Kobo Clara",
"sync_enabled": false,
"auto_sync": false,
"sync_frequency_minutes": 30
}
@name("Update Sync Frequency")
PUT {{environment.base_url}}/devices/{{device_id}}
Authorization: Bearer {{jwt_token}}
Content-Type: application/json
{
"device_name": "My Kobo Clara",
"sync_enabled": true,
"auto_sync": true,
"sync_frequency_minutes": 15
}
# Delete/Revoke Device
@name("Delete Device")
DELETE {{environment.base_url}}/devices/{{device_id}}
Authorization: Bearer {{jwt_token}}
# Get Pending Registrations
@name("Get Pending Registrations")
GET {{environment.base_url}}/devices/pending
Authorization: Bearer {{jwt_token}}
# Approve Device Registration
@name("Approve Device Registration")
GET {{environment.base_url}}/devices/approve/{{registration_id}}
Authorization: Bearer {{jwt_token}}
@name("Approve Registration - KOReader")
GET {{environment.base_url}}/devices/approve/reg-uuid-123
Authorization: Bearer {{jwt_token}}
@name("Approve Registration - Kobo")
GET {{environment.base_url}}/devices/approve/reg-uuid-456
Authorization: Bearer {{jwt_token}}
# Reject Device Registration
@name("Reject Device Registration")
POST {{environment.base_url}}/devices/reject/{{registration_id}}
Authorization: Bearer {{jwt_token}}
@name("Reject Registration - KOReader")
POST {{environment.base_url}}/devices/reject/reg-uuid-123
Authorization: Bearer {{jwt_token}}
@name("Reject Registration - Kobo")
POST {{environment.base_url}}/devices/reject/reg-uuid-456
Authorization: Bearer {{jwt_token}}
@@ -1,26 +0,0 @@
meta {
name: Regenerate Device Token - Forbidden
type: http
seq: 3
}
put {
url: {{base_url}}/api/devices/{{other_device_id}}/regenerate-token
body: none
auth: inherit
}
docs {
## Regenerate Device Token - Forbidden
Tests that users cannot regenerate tokens for devices belonging to other users.
**Expected Behavior:** Returns 403 Forbidden when trying to regenerate token for another user's device
**Status Codes:**
- 403: Forbidden (device belongs to different user)
**Use Case:** Verify authorization - users can only manage their own devices
**Setup:** Use Bearer token from user A, try to regenerate token for user B's device
}
@@ -1,26 +0,0 @@
meta {
name: Regenerate Device Token - Not Found
type: http
seq: 4
}
put {
url: {{base_url}}/api/devices/00000000-0000-0000-0000-000000000000/regenerate-token
body: none
auth: bearer
}
docs {
## Regenerate Device Token - Not Found
Tests that token regeneration returns 404 for non-existent devices.
**Expected Behavior:** Returns 404 Not Found when device UUID doesn't exist
**Status Codes:**
- 404: Device not found
**Use Case:** Verify proper error handling for invalid device IDs
**Setup:** Use all-zero UUID (guaranteed to not exist in database)
}
@@ -1,24 +0,0 @@
meta {
name: Regenerate Device Token - Unauthorized
type: http
seq: 2
}
put {
url: {{base_url}}/api/devices/{{device_id}}/regenerate-token
body: none
auth: none
}
docs {
## Regenerate Device Token - Unauthorized
Tests that token regeneration requires authentication.
**Expected Behavior:** Returns 401 Unauthorized when no Bearer token is provided
**Status Codes:**
- 401: Unauthorized (missing or invalid token)
**Use Case:** Verify authentication is required for token regeneration
}
-73
View File
@@ -1,73 +0,0 @@
meta {
name: Regenerate Device Token
type: http
seq: 1
}
put {
url: {{base_url}}/api/devices/{{device_id}}/regenerate-token
body: none
auth: inherit
}
docs {
## Regenerate Device Token
Regenerates auth token for a device, invalidating old token immediately.
**Method:** PUT
**Endpoint:** /api/devices/{device_id}/regenerate-token
**Authentication:** Bearer token (JWT)
**Path Parameters:**
- `device_id` (string): Device UUID
**Response:**
- `message` (string): Success message
- `auth_token` (string): New auth token
- `device` (object): Updated device details
- `sync_urls` (object): Device-specific sync URLs with new token
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 403: Forbidden (device belongs to different user)
- 404: Device not found
- 500: Internal server error
**Important Notes:**
- Old token stops working immediately
- Device must be updated with new token to resume syncing
- No data loss - device ID remains same
**Example Response:**
```json
{
"message": "Token regenerated successfully",
"auth_token": "dev_abc123...",
"device": {
"id": "uuid-here",
"device_name": "My Kobo Clara",
"device_type": "kobo",
"sync_enabled": true,
"auto_sync": true,
"sync_frequency_minutes": 5,
"created_at": "2026-02-12T10:00:00Z",
"device_metadata": "{...}"
},
"sync_urls": {
"sync_url": "http://localhost:8765/api/sync/kobo/dev_new_token",
"markup": "http://localhost:8765/api/sync/kobo/dev_new_token/markup",
"bookmark": "http://localhost:8765/api/sync/kobo/dev_new_token/bookmark",
"init": "http://localhost:8765/api/sync/kobo/dev_new_token/v1/initialization"
}
}
```
**Important Notes:**
- Old token stops working immediately
- Device must be updated with new token to resume syncing
- No data loss - device ID remains same
}