Files

1217 lines
30 KiB
YAML

openapi: "3.0.3"
info:
title: Canteen Asset Tracker API
version: "2.0.0"
description: |
REST API for Canteen Asset Geolocation Tool — asset CRUD, check-ins,
customers, locations, rooms, users, geofences, visits, OCR, and CSV exports.
## Base URL
`https://canteen.ourpad.casa:8901`
## Settings entities
Dynamic CRUD at `/api/settings/{entity}` for: `categories`, `makes`,
`models`, `key_names`, `key_types`, `badge_types`.
## Auth
POST `/api/auth/login` returns a Bearer token. Most routes are currently
unauthenticated but the client should attach `Authorization: Bearer <token>`.
servers:
- url: https://canteen.ourpad.casa:8901
description: Production
paths:
# ── Health ────────────────────────────────────────────────────────────────
/health:
get:
summary: Server health check
operationId: health
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: ok
# ── Auth ──────────────────────────────────────────────────────────────────
/api/auth/login:
post:
summary: Login
operationId: login
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LoginRequest"
responses:
"200":
description: JWT token
content:
application/json:
schema:
type: object
properties:
token:
type: string
user:
type: object
/api/auth/me:
get:
summary: Current user info
operationId: auth_me
security:
- bearerAuth: []
responses:
"200":
description: User profile
content:
application/json:
schema:
type: object
# ── Assets ────────────────────────────────────────────────────────────────
/api/assets:
get:
summary: List assets
operationId: list_assets
parameters:
- name: category
in: query
schema:
type: string
responses:
"200":
description: Array of assets
post:
summary: Create asset
operationId: create_asset
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AssetCreate"
responses:
"201":
description: Created asset
/api/assets/{asset_id}:
get:
summary: Get asset
operationId: get_asset
parameters:
- $ref: "#/components/parameters/AssetId"
responses:
"200":
description: Asset object
put:
summary: Update asset
operationId: update_asset
parameters:
- $ref: "#/components/parameters/AssetId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AssetUpdate"
responses:
"200":
description: Updated asset
delete:
summary: Delete asset
operationId: delete_asset
parameters:
- $ref: "#/components/parameters/AssetId"
responses:
"200":
description: Deleted
/api/assets/search:
get:
summary: Search assets by machine ID
operationId: search_by_machine_id
parameters:
- name: machine_id
in: query
required: true
schema:
type: string
responses:
"200":
description: Matching assets
# ── Check-ins ─────────────────────────────────────────────────────────────
/api/checkins:
get:
summary: List check-ins
operationId: list_checkins
parameters:
- name: asset_id
in: query
schema:
type: integer
responses:
"200":
description: Array of check-ins
post:
summary: Create check-in
operationId: create_checkin
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CheckinCreate"
responses:
"201":
description: Created check-in
# ── Customers ─────────────────────────────────────────────────────────────
/api/customers:
get:
summary: List customers
operationId: list_customers
responses:
"200":
description: Array of customers
post:
summary: Create customer
operationId: create_customer
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CustomerCreate"
responses:
"201":
description: Created customer
/api/customers/{cust_id}:
get:
summary: Get customer
operationId: get_customer
parameters:
- $ref: "#/components/parameters/CustId"
responses:
"200":
description: Customer object
put:
summary: Update customer
operationId: update_customer
parameters:
- $ref: "#/components/parameters/CustId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CustomerUpdate"
responses:
"200":
description: Updated customer
delete:
summary: Delete customer
operationId: delete_customer
parameters:
- $ref: "#/components/parameters/CustId"
responses:
"200":
description: Deleted
# ── Locations ─────────────────────────────────────────────────────────────
/api/locations:
get:
summary: List locations
operationId: list_locations
parameters:
- name: customer_id
in: query
schema:
type: integer
responses:
"200":
description: Array of locations (each includes rooms array)
post:
summary: Create location
operationId: create_location
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LocationCreate"
responses:
"201":
description: Created location
/api/locations/{loc_id}:
get:
summary: Get location
operationId: get_location
parameters:
- $ref: "#/components/parameters/LocId"
responses:
"200":
description: Location object
put:
summary: Update location
operationId: update_location
parameters:
- $ref: "#/components/parameters/LocId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/LocationUpdate"
responses:
"200":
description: Updated location
delete:
summary: Delete location
operationId: delete_location
parameters:
- $ref: "#/components/parameters/LocId"
responses:
"200":
description: Deleted
# ── Rooms ─────────────────────────────────────────────────────────────────
/api/rooms:
get:
summary: List rooms
operationId: list_rooms
parameters:
- name: location_id
in: query
schema:
type: integer
responses:
"200":
description: Array of rooms
post:
summary: Create room
operationId: create_room
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RoomCreate"
responses:
"201":
description: Created room
/api/rooms/{room_id}:
get:
summary: Get room
operationId: get_room
parameters:
- $ref: "#/components/parameters/RoomId"
responses:
"200":
description: Room object
put:
summary: Update room
operationId: update_room
parameters:
- $ref: "#/components/parameters/RoomId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RoomUpdate"
responses:
"200":
description: Updated room
delete:
summary: Delete room
operationId: delete_room
parameters:
- $ref: "#/components/parameters/RoomId"
responses:
"200":
description: Deleted
# ── Users ─────────────────────────────────────────────────────────────────
/api/users:
get:
summary: List users
operationId: list_users
responses:
"200":
description: Array of users
post:
summary: Create user
operationId: create_user
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UserCreate"
responses:
"201":
description: Created user
/api/users/{user_id}:
get:
summary: Get user
operationId: get_user
parameters:
- $ref: "#/components/parameters/UserId"
responses:
"200":
description: User object
put:
summary: Update user
operationId: update_user
parameters:
- $ref: "#/components/parameters/UserId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UserUpdate"
responses:
"200":
description: Updated user
delete:
summary: Delete user
operationId: delete_user
parameters:
- $ref: "#/components/parameters/UserId"
responses:
"200":
description: Deleted
/api/users/{user_id}/geofences:
get:
summary: List geofences assigned to a user (service areas)
operationId: list_user_geofences
parameters:
- $ref: "#/components/parameters/UserId"
responses:
"200":
description: Array of geofences assigned to this user
# ── Geofences ─────────────────────────────────────────────────────────────
/api/geofences:
get:
summary: List geofences
operationId: list_geofences
responses:
"200":
description: Array of geofences
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/GeofenceResponse"
post:
summary: Create geofence
operationId: create_geofence
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/GeofenceCreate"
responses:
"201":
description: Created geofence
content:
application/json:
schema:
$ref: "#/components/schemas/GeofenceResponse"
/api/geofences/{geofence_id}:
put:
summary: Update geofence
operationId: update_geofence
parameters:
- $ref: "#/components/parameters/GeofenceId"
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/GeofenceUpdate"
responses:
"200":
description: Updated geofence
content:
application/json:
schema:
$ref: "#/components/schemas/GeofenceResponse"
delete:
summary: Delete geofence
operationId: delete_geofence
parameters:
- $ref: "#/components/parameters/GeofenceId"
responses:
"200":
description: Deleted
/api/geofences/check:
post:
summary: Check if point is inside a geofence
operationId: check_geofence_point
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/GeofencePointCheck"
responses:
"200":
description: Geofence check result
/api/proximity:
get:
summary: Proximity check — find assets near a GPS point
operationId: proximity_check
parameters:
- name: lat
in: query
required: true
schema:
type: number
- name: lng
in: query
required: true
schema:
type: number
- name: radius_km
in: query
schema:
type: number
default: 1.0
responses:
"200":
description: Nearby assets
# ── Visits ────────────────────────────────────────────────────────────────
/api/visits:
get:
summary: List visits
operationId: list_visits
parameters:
- name: asset_id
in: query
schema:
type: integer
responses:
"200":
description: Array of visits
post:
summary: Create visit
operationId: create_visit
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/VisitCreate"
responses:
"201":
description: Created visit
/api/visits/stats:
get:
summary: Visit statistics
operationId: get_visit_stats
responses:
"200":
description: Visit stats
# ── Activity ──────────────────────────────────────────────────────────────
/api/activity:
get:
summary: Activity feed
operationId: list_activity
parameters:
- name: user_id
in: query
schema:
type: integer
- name: limit
in: query
schema:
type: integer
default: 100
responses:
"200":
description: Activity entries
# ── Stats & Exports ───────────────────────────────────────────────────────
/api/stats:
get:
summary: Dashboard statistics
operationId: get_stats
responses:
"200":
description: Aggregate stats
/api/export/assets:
get:
summary: Export assets as CSV
operationId: export_assets_csv
responses:
"200":
description: CSV file
content:
text/csv:
schema:
type: string
/api/export/checkins:
get:
summary: Export check-ins as CSV
operationId: export_checkins_csv
parameters:
- name: asset_id
in: query
schema:
type: integer
responses:
"200":
description: CSV file
content:
text/csv:
schema:
type: string
/api/export/service-summary:
get:
summary: Export service summary as CSV
operationId: export_service_summary_csv
responses:
"200":
description: CSV file
content:
text/csv:
schema:
type: string
# ── Uploads & OCR ─────────────────────────────────────────────────────────
/api/upload/icon:
post:
summary: Upload icon image
operationId: upload_icon
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
"201":
description: Uploaded icon path
/api/upload/photo:
post:
summary: Upload photo
operationId: upload_photo
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
"201":
description: Uploaded photo path
/api/ocr:
post:
summary: OCR a sticker/image — extract machine ID
operationId: ocr_sticker
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
"200":
description: Extracted text
# ── Settings (dynamic) ────────────────────────────────────────────────────
/api/settings/{entity}:
get:
summary: List settings entities
operationId: list_settings
parameters:
- name: entity
in: path
required: true
schema:
type: string
enum: [categories, makes, models, key_names, key_types, badge_types]
responses:
"200":
description: Array of settings values
post:
summary: Create settings entity
operationId: create_setting
parameters:
- name: entity
in: path
required: true
schema:
type: string
enum: [categories, makes, models, key_names, key_types, badge_types]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
responses:
"201":
description: Created entity
/api/settings/{entity}/{eid}:
get:
summary: Get settings entity
operationId: get_setting
parameters:
- name: entity
in: path
required: true
schema:
type: string
enum: [categories, makes, models, key_names, key_types, badge_types]
- $ref: "#/components/parameters/SettingId"
responses:
"200":
description: Settings entity object
put:
summary: Update settings entity
operationId: update_setting
parameters:
- name: entity
in: path
required: true
schema:
type: string
enum: [categories, makes, models, key_names, key_types, badge_types]
- $ref: "#/components/parameters/SettingId"
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
responses:
"200":
description: Updated entity
delete:
summary: Delete settings entity
operationId: delete_setting
parameters:
- name: entity
in: path
required: true
schema:
type: string
enum: [categories, makes, models, key_names, key_types, badge_types]
- $ref: "#/components/parameters/SettingId"
responses:
"204":
description: Deleted
# ── Components ──────────────────────────────────────────────────────────────
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
parameters:
AssetId:
name: asset_id
in: path
required: true
schema:
type: integer
CustId:
name: cust_id
in: path
required: true
schema:
type: integer
LocId:
name: loc_id
in: path
required: true
schema:
type: integer
RoomId:
name: room_id
in: path
required: true
schema:
type: integer
UserId:
name: user_id
in: path
required: true
schema:
type: integer
GeofenceId:
name: geofence_id
in: path
required: true
schema:
type: integer
SettingId:
name: eid
in: path
required: true
schema:
type: integer
schemas:
AssetKey:
type: object
properties:
key_name:
type: string
key_type:
type: string
AssetBadge:
type: object
properties:
badge_name:
type: string
AssetCreate:
type: object
required:
- machine_id
- name
properties:
machine_id:
type: string
name:
type: string
serial_number:
type: string
description:
type: string
category:
type: string
enum: [Furniture, Appliances, "Utensils & Serveware", Equipment, Other]
default: Other
status:
type: string
enum: [active, maintenance, retired]
default: active
make:
type: string
model:
type: string
address:
type: string
building_name:
type: string
building_number:
type: string
floor:
type: string
room:
type: string
trailer_number:
type: string
walking_directions:
type: string
map_link:
type: string
parking_location:
type: string
photo_path:
type: string
customer_id:
type: integer
location_id:
type: integer
assigned_to:
type: integer
latitude:
type: number
longitude:
type: number
geofence_radius_meters:
type: integer
default: 50
keys:
type: array
items:
$ref: "#/components/schemas/AssetKey"
badges:
type: array
items:
type: string
AssetUpdate:
type: object
properties:
machine_id:
type: string
name:
type: string
serial_number:
type: string
description:
type: string
category:
type: string
status:
type: string
make:
type: string
model:
type: string
address:
type: string
building_name:
type: string
building_number:
type: string
floor:
type: string
room:
type: string
trailer_number:
type: string
walking_directions:
type: string
map_link:
type: string
parking_location:
type: string
photo_path:
type: string
customer_id:
type: integer
location_id:
type: integer
assigned_to:
type: integer
latitude:
type: number
longitude:
type: number
geofence_radius_meters:
type: integer
keys:
type: array
items:
$ref: "#/components/schemas/AssetKey"
badges:
type: array
items:
type: string
CheckinCreate:
type: object
required:
- asset_id
properties:
asset_id:
type: integer
latitude:
type: number
longitude:
type: number
accuracy:
type: number
photo_path:
type: string
notes:
type: string
user_id:
type: integer
CustomerContact:
type: object
properties:
name:
type: string
phone:
type: string
email:
type: string
CustomerCreate:
type: object
required:
- name
properties:
name:
type: string
contacts:
type: array
items:
$ref: "#/components/schemas/CustomerContact"
CustomerUpdate:
type: object
properties:
name:
type: string
contacts:
type: array
items:
$ref: "#/components/schemas/CustomerContact"
LoginRequest:
type: object
required:
- username
- password
properties:
username:
type: string
password:
type: string
LocationCreate:
type: object
required:
- name
properties:
customer_id:
type: integer
name:
type: string
address:
type: string
building_name:
type: string
building_number:
type: string
floor:
type: string
trailer_number:
type: string
site_hours:
type: string
access_notes:
type: string
walking_directions:
type: string
map_link:
type: string
latitude:
type: number
longitude:
type: number
LocationUpdate:
type: object
properties:
customer_id:
type: integer
name:
type: string
address:
type: string
building_name:
type: string
building_number:
type: string
floor:
type: string
trailer_number:
type: string
site_hours:
type: string
access_notes:
type: string
walking_directions:
type: string
map_link:
type: string
latitude:
type: number
longitude:
type: number
RoomCreate:
type: object
required:
- location_id
- name
properties:
location_id:
type: integer
name:
type: string
floor:
type: string
RoomUpdate:
type: object
properties:
name:
type: string
floor:
type: string
location_id:
type: integer
UserCreate:
type: object
required:
- username
- password
properties:
username:
type: string
password:
type: string
role:
type: string
enum: [technician, admin]
UserUpdate:
type: object
properties:
role:
type: string
password:
type: string
GeofenceCreate:
type: object
required:
- name
- points
properties:
name:
type: string
points:
type: array
items:
type: object
properties:
lat:
type: number
lng:
type: number
color:
type: string
default: "#3388ff"
user_ids:
type: array
items:
type: integer
description: IDs of users assigned to this service area
GeofenceResponse:
type: object
properties:
id:
type: integer
name:
type: string
points:
type: array
color:
type: string
created_at:
type: string
updated_at:
type: string
assigned_users:
type: array
items:
$ref: "#/components/schemas/UserBrief"
UserBrief:
type: object
properties:
id:
type: integer
username:
type: string
role:
type: string
GeofenceUpdate:
type: object
properties:
name:
type: string
points:
type: array
color:
type: string
user_ids:
type: array
items:
type: integer
description: Replace assigned users for this service area
GeofencePointCheck:
type: object
required:
- lat
- lng
properties:
lat:
type: number
lng:
type: number
VisitCreate:
type: object
required:
- asset_id
properties:
user_id:
type: integer
asset_id:
type: integer
latitude:
type: number
longitude:
type: number
duration_minutes:
type: integer