API Reference
This document summarizes the FastAPI endpoints exposed by the backend.
Base URL
By default the server runs at http://127.0.0.1:5000. The convenience script uses port 5000.
Authentication
Most mutating routes require authentication using a bearer token. The token is issued by /auth/login and should be sent as:
Authorization: Bearer <token>
POST /auth/login
Authenticate a user and receive an access token.
Request body must use form fields:
username=<username>
password=<password>
Example:
curl -X POST http://127.0.0.1:5000/auth/login \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'username=admin&password=secret'
Response:
{"access_token":"...","token_type":"bearer"}
GET /auth/authorized
Validates the current access token.
User management
POST /users/create
Create a user. Requires admin role.
Form fields: username, password, role.
PUT /users/update
Update a user password or role. Requires admin role.
DELETE /users/remove
Remove a user. Requires admin role.
GET /users/get/all
List all users. Requires admin role.
GET /users/get/me
Get the current authenticated user profile.
Item and hierarchy routes
GET /get/root
Get the root item. The root uses the empty placement code "".
GET /get
Get an item by placement code.
Example:
curl http://127.0.0.1:5000/get?code=A
GET /get/children
List child items for a parent placement code.
Example:
curl http://127.0.0.1:5000/get/children?code=A
GET /get/children/root
List the root's child items.
GET /get/all
Return all items. Add only_leaves=true to return only leaf nodes.
GET /search
Search items by text.
Common query parameters:
- q: search string
- max_results: maximum number of results
- skip_number: offset for pagination
- only_leaves: only return leaves
- info_level: 0 for full item details, 1 for basic fields
GET /trail
Return the breadcrumb trail for a placement code.
GET /has_children
Check whether a placement code has children.
Item mutation routes
POST /add
Create a new item. Requires admin or maintainer role.
Form fields include placement_code, name, description, keywords, children_arrangement, self_alignment, color, map_image, and desc_image.
DELETE /remove
Delete one or more items. The form field codes accepts a list of placement codes. Requires admin or maintainer role.
PUT /update/root
Update the root item. Requires admin, maintainer, or editor role.
PUT /update
Update an item by placement code. Requires admin, maintainer, or editor role.
Image routes
GET /descimage/root
Get the description image for the root item.
GET /mapimage/root
Get the map image for the root item.
GET /descimage
Get the description image for a specific placement code.
GET /mapimage
Get the map image for a specific placement code.
Utility routes
GET /id
Return the server identifier.
GET /ping
Health check endpoint.
Backup routes
GET /backups/get/all
List available backups. Requires admin role.
POST /backups/dump
Create a new backup immediately. Requires admin role.
POST /backups/schedule_restore
Schedule a restore from a backup ID. Requires admin role. The restore is applied on the next startup.
DELETE /backups/remove
Delete a backup archive. Requires admin role.
Settings routes
GET /settings/get
Read a setting by ID.
PUT /settings/update
Update settings such as image_quality, max_backups_size, and backup_interval_seconds. Requires admin role.
get_siblings(placement_code) -> list[dict]
Get sibling inholders at the same hierarchical level.
Parameters:
placement_code(str) - The placement code
Returns: List of inholder dictionaries at the same depth, excluding the node itself
is_leaf(placement_code) -> bool
Check if an inholder has no children.
Parameters:
placement_code(str) - The placement code
Returns: True if leaf node (no children), False otherwise
search(query, only_leaves, max_results, skip_number=0) -> list[dict]
Perform fuzzy search on inholders.
Parameters:
query(str) - Search queryonly_leaves(bool) - IfTrue, only return leaf nodesmax_results(int | None) - Maximum results (None for unlimited)skip_number(int) - Results to skip for pagination
Returns: List of matching inholder dictionaries
Image Operations
verify_placement_code_syntax(placement_code) -> bool
Validate placement code format.
Rules:
- Empty string is valid
- Parts separated by
- - Each part must be alphanumeric uppercase ASCII or digits only
Returns: True if valid, False otherwise
map_image_path(placement_code) -> Path
Get the file path for a map image.
Returns: Path object
Missing Request Data (400):
- Required fields not provided (e.g., missing
placement_code,namein POST request) - Query parameters not provided (e.g., missing
qin search)
Invalid Request Data (400):
- Invalid placement code syntax (doesn't match pattern)
- Wrong data type for field (e.g., number where string expected)
Unauthorized (401):
- No JWT token provided in Authorization header
- JWT token is expired or invalid
- User lacks required permission for the operation
Not Found (404):
- Placement code doesn't exist in database
- Image file not found for the inholder
- User requested doesn't exist
Conflict (409):
- Attempting to add inholder that already exists
- Renaming to a placement code that's already in use
Environment Variables
Configuration via .env file (auto-created on first run):
| Variable | Default | Description |
|---|---|---|
JWT_SECRET |
(auto-generated) | Secret key for signing JWT tokens. Auto-generated on first run if not set. Must be kept secret. |
ID |
(auto-generated) | Unique server identifier (UUID format). Auto-generated on first run. Used to identify this server instance. |
SERVER_NAME |
(not set) | Display name for the server. Used in beacon broadcast. |
PORT |
5000 |
Server listening port. Change to run multiple instances on different ports. |
BACKUP_INTERVAL_SECONDS |
3600 |
Time between automatic backups in seconds (default: 1 hour). |
BACKUP_FOLDER |
backups |
Directory path for storing backup ZIP files. Created if it doesn't exist. |
Notes:
- The
.envfile is created in the server working directory on first run JWT_SECRETis critical for security - keep it confidential- Changing
PORTrequires restarting the server - Backup folder path can be relative or absolute
Best Practices & Implementation Guide
Authentication Flow
- Initial Login: POST
/loginwith username/password to get tokens - Store Tokens: Save both
access_token(short-lived) andrefresh_token(long-lived) - Use Access Token: Include access token in Authorization header for regular requests
- Token Refresh: Before token expires, use
refresh_tokento get new tokens via POST/refresh - Logout: Use POST
/logoutwith refresh token to revoke access
Token Expiration Handling
- Access tokens expire after 15 minutes - Client should track expiration time
- Refresh tokens expire after 24 hours - User must log in again after 24 hours
- Implement automatic token refresh 1 minute before expiration
- On 401 response, attempt refresh; if refresh fails, redirect to login
Search Best Practices
- Use pagination for large result sets:
max_resultsandskip_number - Cache search results on client for frequently repeated queries
- Empty query (
q="") returns all items - consider limiting withmax_results - Use
only_leaves=truewhen searching for actual storage locations only - Fuzzy matching is flexible - typos and partial matches work well
Hierarchy Management
- Plan your placement code structure before bulk import
- Parent must exist before child: Cannot create "A-1-B" if "A-1" doesn't exist
- Use meaningful codes: "A-1" is better than "TEMP-X" for maintainability
- Breadcrumb navigation: Use
/trailendpoint for UI navigation components - Recursive delete: Remember
/removedeletes all descendants
Image Handling
- Supported formats: PNG, JPEG, HEIC, and most Pillow-supported formats
- Images are converted to WebP automatically for efficient storage
- Recommended image sizes:
- Map images: 800x600 to 1920x1440 pixels
- Description images: 600x400 to 1024x768 pixels
- Image quality: Default 85/100 (configurable via
IMAGE_QUALITYconfig) - Always provide both images for complete UI experience
Error Handling
# Example error handling pattern
import requests
try:
response = requests.post('http://localhost:5000/add',
headers={'Authorization': f'Bearer {token}'},
json={...})
if response.status_code == 409:
# Inholder already exists
handle_conflict()
elif response.status_code == 401:
# Token expired or permission denied
refresh_token_or_login()
elif response.status_code == 400:
# Invalid data
show_validation_error(response.json())
else:
response.raise_for_status()
except requests.exceptions.RequestException as e:
# Network error
handle_network_error(e)
Connection & Timeout Settings
- Connection timeout: Use 5-10 seconds
- Read timeout: Use 15-30 seconds (allows time for large database operations)
- Retry policy: Implement exponential backoff for network errors
- Connection pooling: Reuse connections for multiple requests
Performance Tips
- Use
/get_children/for tree traversal instead of loading all items - Cache inholder data if not changing frequently
- Batch multiple image uploads into single requests where possible
- Use
skip_numberfor pagination rather than filtering results client-side - Avoid repeated
/get_allcalls - cache results with change tracking
Multi-Server Deployment
- Use
/server_idendpoint to identify which server client is connected to - Different servers have different
IDvalues (auto-generated UUIDs) - Each server maintains independent database and user list
- Plan for server discovery mechanism using beacon broadcasts
Data Models
Inholder
Represents an item in the hierarchical storage system.
{
"placement_code": str, # Hierarchical identifier (e.g., "A-1-B")
# Empty string "" represents the root
# Format: uppercase alphanumeric and hyphens only
"name": str, # Display name (required)
"description": str, # Description text (optional)
"keywords": str, # Searchable keywords, typically comma-separated (optional)
"children_arrangement": str, # Layout/arrangement setting for child items (optional)
"self_alignment": str, # Alignment setting for this item (optional)
"color": str, # Color value for UI representation (optional)
"has_map_image": bool, # Whether a map/layout image is stored
"has_description_image": bool # Whether a description image is stored
}
Placement Code Rules:
- Must be uppercase alphanumeric ASCII and hyphens only
- Segments are separated by hyphens (e.g.,
A,A-1,A-1-B) - Empty string is reserved for the root inholder
- Parent of placement code
A-1-BisA-1
User
Represents a user account with authentication and permissions.
{
"id": str, # Unique user identifier (UUID)
"username": str, # Username for login
"permissions": list[str] # List of granted permissions
# Possible values: "add", "update", "remove", "rename_server"
}
Note: User passwords are hashed with werkzeug.security.generate_password_hash and never exposed in API responses.
Permission System
Available permissions that can be assigned to users:
| Permission | Description |
|---|---|
"add" |
Can create new inholders via POST /add |
"update" |
Can modify existing inholders via PUT /update |
"remove" |
Can delete inholders via DELETE /remove |
"rename_server" |
Can update root inholder name via PUT /update_root |