Bonaire API

v1
Health Boulevard

API Gateway

Standalone REST API for the Bonaire mobile app and future integrations.

Base URL

https://api.bonairedev.xyz/v1

Auth

Bearer token

Format

JSON

Authentication

All /v1/ endpoints (except login) require a Bearer token in the Authorization header.

# 1. Login to get a token

curl -X POST https://api.bonairedev.xyz/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "your.user", "password": "your_pass"}'

# 2. Use the token

curl https://api.bonairedev.xyz/v1/auth/me \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Login response includes access_token, refresh_token, token_type, and a user object with id, display_name, role, locations[], and has_stock_check_access.

Auth

POST /v1/auth/login No auth Login, get token
GET /v1/auth/me Token Current user info
POST /v1/auth/refresh Token Issue new token
POST /v1/auth/logout Token Revoke token

Locations

GET /v1/locations/ List accessible locations
GET /v1/user-locations User locations + active selection
POST /v1/set-active-location Set active location
GET /v1/manager-staff?location=X Manager's team at location

Stock Check

Upload an Inventory On Hand CSV to create a counting session, then submit counts item-by-item.

POST /v1/stock-check/upload Upload CSV, create session
GET /v1/stock-check/active-session?location_id=X Check for active session
GET /v1/stock-check/recent-activity?limit=20 Recent sessions
GET /v1/stock-check/{id} Session summary
GET /v1/stock-check/{id}/products Session items
POST /v1/stock-check/{id}/submit-count Submit a count
POST /v1/stock-check/{id}/complete Complete session
POST /v1/stock-check/{id}/take-over Take over (higher role)
POST /v1/stock-check/{id}/request-takeover Request takeover (lower role)
DEL /v1/stock-check/{id} Delete session
Upload CSV — Example
curl -X POST https://api.bonairedev.xyz/v1/stock-check/upload \
  -H "Authorization: Bearer TOKEN" \
  -F "location_id=farmington" \
  -F "sequence_id=my_sequence" \
  -F "inventory_csv=@Inventory_On_Hand.csv"

Response 201

{
  "session_id": "a1b2c3d4e5f6",
  "location": "farmington",
  "location_name": "Farmington",
  "total_items": 342,
  "total_brands": 28,
  "sequence_mode": true,
  "status": "active",
  "message": "342 products across 28 stages ready to count."
}
Submit Count — Example
curl -X POST https://api.bonairedev.xyz/v1/stock-check/SESSION_ID/submit-count \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"item_id": "abc123", "counted_quantity": 5}'

Response

{
  "result": "verified",
  "item_id": "abc123",
  "expected": 5,
  "counted": 5,
  "attempts": 1,
  "is_verified": true,
  "is_mismatch": false,
  "progress": {"counted": 45, "total": 342, "percent": 13}
}
Result values: verified (match), mismatch (wrong, <3 tries), auto_override (3rd fail, creates override request)

Session Rules

  • One active session per location. Upload returns 409 if one exists.
  • Only the assigned user can count. Others get 403.
  • Takeover: Higher-role users can take over directly; lower-role must request.
  • Complete: Auto-approves any pending override requests.

Sequences

Custom counting order definitions for stock checks.

GET /v1/sc-sequences?location_id=X List sequences
GET /v1/sc-sequences/{id} Sequence detail

Inventory

GET /v1/inventory/?location_id=X Product list from latest CSV
GET /v1/inventory/summary?location_id=X Inventory stats
GET /v1/inventory/suppliers Brand / supplier list

Staff

GET /v1/staff/ Staff list (scoped by role)

Admins see all users. Managers see their assigned team.

Stubs

Endpoints wired up with placeholder responses. Ready for business logic.

Notifications

GET /v1/notifications/

GET /v1/notifications/unread-count

PUT /v1/notifications/{id}/read

Tasks

GET /v1/tasks/

POST /v1/tasks/

GET /v1/tasks/{id}

PUT /v1/tasks/{id}

DEL /v1/tasks/{id}

Purchase Orders

GET /v1/purchase-orders/

POST /v1/purchase-orders/

GET /v1/purchase-orders/{id}

POST /v1/purchase-orders/{id}/submit

Analytics

GET /v1/analytics/summary

Boulevard Integration

Webhook receiver and sync stubs. Waiting for OAuth2 credentials.

GET /v1/boulevard/status No auth Integration status
POST /v1/boulevard/webhooks HMAC Receive Boulevard events
Supported events: appointment.created, appointment.updated, appointment.cancelled, staff.created, staff.updated

Error Responses

All errors return JSON with an error field.

{"error": "Description of what went wrong"}
StatusMeaning
400Bad request — missing required field
401Unauthorized — invalid or missing token
403Forbidden — insufficient role / permissions
404Not found
409Conflict — e.g. active session already exists

Location Keys

KeyDisplay Name
farmingtonFarmington
houstonHouston
salt_lake_citySalt Lake City
sugar_landSugar Land
gilbertGilbert

Infrastructure

Serverapi.bonairedev.xyz
Port5058
SSLLet's Encrypt
ProcessPM2 bonaire-api
RuntimeGunicorn × 2 workers
Databasebonairedb (PostgreSQL)

Related Services

Web Appbonairedev.xyz :5050
Solene AIsolene.bonairedev.xyz :5556
Staff Appstaff.bonairedev.xyz :5057
API Gatewayapi.bonairedev.xyz :5058