Booth occupancy monitoring API built with AdonisJS 6, PostgreSQL, and Lucid ORM.
The service stores:
- booth metadata in
booths - occupancy history in
booth_statuses(append-only) - uploaded files in
file_entries
Devices send status every minute. A booth is considered offline when its latest status is older than 3 minutes.
- Token-secured write endpoints (
x-api-token) - Booth registry endpoint (
POST /api/v1/booths) - Historical status tracking (
booth_statuses) - File upload with generated miniatures (Sharp + Drive)
- Public URLs for original and miniature images
- Swagger docs at
/api/v1/docs
# 1) Install dependencies
npm install
# 2) Configure environment
cp .env.example .env
# 3) Fresh database setup
node ace migration:fresh
# 4) Generate API token (save it)
node ace generate:token "test-device"
# 5) Start server
npm run dev
# 6) Open docs
open http://localhost:3333/api/v1/docsRequired values are in .env.example:
APP_URL- base URL for generated file linksMINIATURE_MAX_HEIGHT_PX- thumbnail max heightMINIATURE_MAX_PROCESSING_TIME_S- Sharp processing timeout- DB connection vars (
DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_DATABASE)
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/files |
Token | Upload file, returns key (uuid.ext) |
| GET | /api/v1/files/:key |
- | Get file metadata (url, miniaturesUrl) |
| POST | /api/v1/booths |
Token | Create booth metadata |
| POST | /api/v1/booths/status |
Token | Append booth status |
| GET | /api/v1/booths/status |
- | Get latest status for all booths |
| GET | /api/v1/booths/status/:boothId |
- | Get latest status for one booth |
| GET | /api/v1/healthcheck |
- | Health endpoint |
Uploaded files are also served publicly by Drive:
- original:
/uploads/:key - miniature:
/uploads/miniatures/:key
curl -X POST http://localhost:3333/api/v1/files \
-H "x-api-token: YOUR_TOKEN" \
-F "file=@/path/to/photo.jpg"Example response:
{ "key": "7f73b6d8-0f8e-4f9a-a4e0-c95f2f1f3a20.jpg" }curl -X POST http://localhost:3333/api/v1/booths \
-H "x-api-token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"booth_id": "booth-1",
"booth_name": "Main Booth",
"photo_key": "7f73b6d8-0f8e-4f9a-a4e0-c95f2f1f3a20.jpg",
"localization": "Building C, floor 1, near the main stairs"
}'curl -X POST http://localhost:3333/api/v1/booths/status \
-H "x-api-token: YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"booth_id": "booth-1",
"is_occupied": true
}'curl http://localhost:3333/api/v1/booths/status
curl http://localhost:3333/api/v1/booths/status/booth-1# Run static checks
npm run typecheck
# Run API smoke script (expects running server and valid token)
./test-api.sh YOUR_TOKENAGPL-3.0