Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ricardomb-tech/surqo/llms.txt
Use this file to discover all available pages before exploring further.
The Surqo API is a FastAPI-powered REST backend deployed on Fly.io (Dallas — dfw) with min_machines_running = 1 and auto_stop_machines = false. There are no cold starts — every request hits a live machine. All endpoints live under the base path /api/v1/. Interactive Swagger UI (/docs) and ReDoc (/redoc) are available in local development only; both are disabled in production for security.
Base URLs
| Environment | URL |
|---|
| Production | https://surqo-api.fly.dev |
| Local dev | http://localhost:8000 |
| Swagger UI | http://localhost:8000/docs (dev only) |
HTTP Status Codes
Every response conforms to standard HTTP semantics. The table below covers all codes you will encounter across Surqo endpoints.
| Code | Meaning |
|---|
200 | OK — request succeeded, body contains data |
201 | Created — resource successfully created |
204 | No Content — successful DELETE, no response body |
401 | JWT missing, expired, or invalid |
402 | Plan quota exceeded (farms limit or AI analyses) |
403 | Resource belongs to a different user |
404 | Resource not found |
422 | Pydantic validation error — check request body shape |
429 | Rate limit exceeded (slowapi per-IP / per-user) |
The 402 response is used for quota enforcement, not payment. When a free-tier user exhausts their 4 lifetime AI analyses or tries to create a second farm, the API returns 402 with a structured error body containing code, message, and contact_url.
Rate Limits
Rate limiting is handled by slowapi. Limits are enforced per authenticated user when a valid JWT is present (keyed on the sub claim), or per IP for unauthenticated requests. Exceeding a limit returns 429 Too Many Requests.
| Endpoint group | Limit |
|---|
POST /api/v1/farms/ | 10 / minute |
POST /api/v1/analysis/analyze | 10 / minute |
POST /api/v1/analysis/chat | 20 / minute |
POST /api/v1/sensors/reading | 120 / minute |
POST /api/v1/devices/register | 30 / minute |
GET /api/v1/users/me | 60 / minute |
Endpoint Index
A complete reference of every route exposed by the API. All authenticated endpoints require Authorization: Bearer <jwt>.
| Method | Path | Auth | Description |
|---|
GET | /health | No | Server health check |
POST | /api/v1/sensors/reading | Yes | Ingest a sensor reading |
GET | /api/v1/sensors/timeseries/{farm_id} | Yes | Time-series data (query: hours, metric) |
GET | /api/v1/sensors/latest/{device_id} | Yes | Latest reading for a device |
GET | /api/v1/sensors/stats/{farm_id} | Yes | Aggregated 24 h statistics |
WS | /api/v1/sensors/ws/live/{farm_id} | Yes (token param) | Live sensor stream over WebSocket |
POST | /api/v1/farms/ | Yes | Create a farm (free plan: max 1) |
GET | /api/v1/farms/ | Yes | List all farms for the authenticated user |
GET | /api/v1/farms/{id} | Yes | Get a single farm |
PATCH | /api/v1/farms/{id} | Yes | Update farm fields (all optional) |
DELETE | /api/v1/farms/{id} | Yes | Delete farm and all associated data |
GET | /api/v1/farms/{id}/kpis | Yes | Agronomic KPIs for the last 24 h |
POST | /api/v1/analysis/analyze | Yes | Run an AI analysis (free plan: 4 lifetime) |
GET | /api/v1/analysis/history/{farm_id} | Yes | Analysis history (latest 10) |
GET | /api/v1/analysis/{id} | Yes | Retrieve a single analysis result |
POST | /api/v1/analysis/chat | Yes | Chat with the AI agronomist |
GET | /api/v1/alerts/active | Yes | Active alerts (query: farm_id) |
GET | /api/v1/alerts/history | Yes | All alerts — active and resolved |
PATCH | /api/v1/alerts/{id}/resolve | Yes | Mark an alert as resolved |
POST | /api/v1/alerts/{id}/notify | Yes | Re-send alert email manually |
GET | /api/v1/kpis/farm/{id} | Yes | Detailed KPIs (VPD, ETc, GDD, soil score) |
GET | /api/v1/kpis/farm/{id}/vpd-history | Yes | VPD readings over the last 48 h |
GET | /api/v1/kpis/farm/{id}/water-balance | Yes | 7-day water balance (ETc vs rainfall) |
GET | /api/v1/kpis/farm/{id}/pest-risk | Yes | Pest risk score and pathogen list |
POST | /api/v1/devices/register | No | ESP32 self-registration |
POST | /api/v1/devices/{device_mac}/reading | No | ESP32 HTTP fallback — publishes a reading by MAC when MQTT is unavailable |
GET | /api/v1/devices/ | Yes | List devices paired to the user’s farms |
GET | /api/v1/devices/discoverable | Yes | Unpaired devices available to claim |
POST | /api/v1/devices/claim | Yes | Pair a device to a farm |
PATCH | /api/v1/devices/{id} | Yes | Rename a paired device |
DELETE | /api/v1/devices/{id} | Yes | Unpair a device from its farm |
GET | /api/v1/users/me | Yes | Authenticated user’s profile |
GET | /api/v1/users/me/plan-limits | Yes | Current quota status and remaining allowances |
PATCH | /api/v1/users/{id}/plan | Admin | Change a user’s plan (free → paid) |
Health Check
Use the /health endpoint to verify the backend is reachable. In production it returns a minimal body to avoid exposing internal state.
curl https://surqo-api.fly.dev/health
In local development the health response is more verbose, including db, mqtt_active, and ws_connections fields — useful for confirming all subsystems started correctly.