🌿 TURFInsight API Reference

REST API documentation for the TURFInsight SAAS platform v0.1.0

Base URL:

System

GET /api/health Service health check

Response

{ "status": "ok", "version": "0.1.0", "courses": 1 }

Courses

GET /api/courses List all courses

Response

{ "courses": [{ "id": "...", "name": "Castle Pines", "slug": "castle_pines", ... }] }
GET /api/courses/{slug} Get course by slug
Param Type Info
slug string required URL slug
POST /api/courses Create a new course

Request Body (JSON)

{ "name": "My Course", "slug": "my_course", "bounds_xmin": -105.0, "bounds_ymin": 39.5, "bounds_xmax": -104.9, "bounds_ymax": 39.6 }

Flights

GET /api/courses/{slug}/flights List flights for a course

Observations

GET /api/courses/{slug}/observations List observations (with filters)
Query Param Type Info
severity string high | medium | low | info
status string open | resolved
limit int Max results (default: all)
POST /api/courses/{slug}/observations Create observation (multipart: photo + metadata)

Multipart Fields

Field Type Info
photo file required JPEG/PNG image
metadata JSON required Observation data

Metadata JSON

{
  "latitude": 39.738, "longitude": -104.99,
  "captured_at": "2026-03-08T12:00:00Z",
  "severity": "medium", "category": "Disease",
  "description": "Brown patch on green 5",
  "inspector": "Field Inspector"
}

💡 EXIF fallback: If lat/lng are 0, GPS coords are extracted from photo EXIF data.

POST /api/courses/{slug}/observations/batch Batch multi-photo upload with auto-EXIF

Multipart Fields

Field Type Info
photo1, photo2, … file Multiple JPEG/PNG images
metadata JSON Shared batch metadata (severity, category, etc.)

Response

{ "total": 5, "created": 5, "results": [{ "id": "...", "status": "created" }] }
GET /api/observations/{id}/photo Serve full-size photo

Returns the original JPEG image as image/jpeg.

GET /api/observations/{id}/thumb Serve 400px thumbnail

Returns a 400px-wide JPEG thumbnail. Auto-generated on upload.

PATCH /api/courses/{slug}/observations/{id} Update observation (status, severity, description)
{ "status": "resolved", "severity": "low", "description": "Fixed" }
DELETE /api/courses/{slug}/observations/{id} Delete observation + cleanup files

Deletes observation record, photo file, and thumbnail.

Annotations

GET /api/courses/{slug}/annotations List annotations (optional group_id, type filters)
Query Type Info
group_id string Filter by annotation group
type string point | linestring | polygon | circle
POST /api/courses/{slug}/annotations Create annotation (GeoJSON geometry)
{
  "group_id": "group-uuid", "geometry_type": "polygon",
  "geometry_json": "{\"type\":\"Polygon\",\"coordinates\":...}",
  "label": "Green 5 boundary", "color": "#8dc63f"
}
GET /api/courses/{slug}/annotations/groups List annotation groups

GeoJSON Import / Export

GET /api/courses/{slug}/annotations/export Export all annotations as GeoJSON FeatureCollection
POST /api/courses/{slug}/annotations/import Import GeoJSON FeatureCollection as annotations

Send a GeoJSON FeatureCollection in the request body.