DeepLeaf Yield DeepLeaf Yield

API reference

Everything the app does goes through a JSON API that you can use with your organization key. The full, interactive reference is at /api/docs, built from /openapi.json.

The registry hierarchy that the API paths follow: organization, farm, greenhouse, row, crop cycle.The registry hierarchy that the API paths follow: organization, farm, greenhouse, row, crop cycle.
Registry paths follow the hierarchy from organization down to crop cycle.

Authentication

curl -H "X-API-Key: dl_…" https://your-deepleaf-address/api/organizations/org-1
curl -H "Authorization: Bearer dl_…" https://your-deepleaf-address/api/organizations/org-1

Missing, unknown, or revoked keys get 401. A path under another organization gets 404. A member key gets 403 on key management and billing payments; see Organization and keys. Use the address you open the app on.

Path shorthand

Below, {cycle} stands for the full crop cycle path:

/api/organizations/{organization_id}/farms/{farm_id}/greenhouses/{greenhouse_id}/rows/{row_id}/cycles/{cycle_id}

Weeks are written 2026-W40 or as any date in that week, YYYY-MM-DD.

Scoring

Method and pathWhat it does
POST /api/observationsUpload a photo or video (multipart file, with optional mode, conf, sample_seconds, max_frames, mm_per_pixel). Returns a job id.
GET /api/observations/{id}Status, progress, and the result with frames, fruit, stems, plants, and quality.
GET /api/observations/{id}/frames/{frame}/{name}A frame image or overlay.
POST /api/examples/{key}Score one of the example photos.
POST {cycle}/videosUpload and save a walk to a cycle and a week.
POST {cycle}/videos/batchUp to 12 video clips as repeated files fields, in walking order, scored and counted as one walk. The job's clips field shows progress per clip.

Registry

Method and pathWhat it does
GET /api/organizations/{org}The organization's tree of farms, greenhouses, rows, and cycles.
POST …/farms, …/greenhouses, …/rows, …/cyclesCreate a level.
PATCH a level's pathChange names and details. Ids stay.
GET a level's path + /contentsCounts of everything under the level.
DELETE a level's path409 with counts while it holds anything. ?cascade=true deletes it with its contents.

Records

Method and pathWhat it does
POST / GET {cycle}/harvestsLog one harvest (week, kg, note), or list them. ?week= filters.
POST {cycle}/harvests/csvUpload a week,kg[,note] file.
PATCH / DELETE {cycle}/harvests/{id}Edit or delete one harvest.
POST / GET {cycle}/irrigationLog one entry, or list them newest first.
PATCH / DELETE {cycle}/irrigation/{id}Edit or delete one entry.
POST / GET {cycle}/climateAdd readings as {"points": [...]}, or list them (metric, from, to, limit, offset).
POST {cycle}/climate/csv/previewCheck a climate file without storing it: the detected layout, each column's metric, unit, conversion and confidence, the time zone and time range, the first rows, warnings and blocking problems, and a mapping to confirm. Takes the same form fields as the upload, including compartment and date_order (dmy or mdy).
POST {cycle}/climate/csvUpload a climate file. Send the mapping from the preview to import exactly what was previewed (columns left out of it are not imported), or columns to name them yourself; refused with 400 while the file has problems, and 413 above the size cap.
POST {cycle}/climate/file/previewCheck a climate computer export (CSV, text or .xlsx) without storing it: the file, the clock it is read on (time_zone), each column with its metric and unit, setpoints, the first hours, what is already stored, warnings, blocking problems, and a mapping to confirm.
POST {cycle}/climate/fileStore the export's hours with the confirmed mapping; remember saves the column choices for the greenhouse. Re-imported hours are updated, never doubled.
POST {cycle}/climate/ingestThe same import for a script of your own: the file as the request body, a key in a header only, the greenhouse's saved column choices. See Import your climate computer data.
GET / DELETE {greenhouse}/climate/file-mappingThe column choices saved for a greenhouse, or forget them.
GET {cycle}/climate/importsThe cycle's recent climate imports, newest first.
POST {cycle}/climate/imports/{id}/undoUndo one import: removes the readings it added and puts back the values it changed. 409 when a later import changed the same readings, unless the body is {"confirm": true}.
PATCH / DELETE {cycle}/climate/{id}Edit or delete one reading.
POST {cycle}/fruit-massTyped grams for green_g, turning_g, red_g.
POST {cycle}/weatherRefresh outdoor weather for the greenhouse location now (past_days, forecast_days).

Weeks and forecasts

Method and pathWhat it does
GET {cycle}/weeks/{week}The week read: walk counts, harvest, irrigation, climate, water productivity, and forecast.
GET {cycle}/forecast?week=The forecast for the walk week and the seven after it (default: latest walk week).
POST / GET {cycle}/forecastsIssue and store the current forecast, or list stored ones with the harvest since.
GET {cycle}/backtestReplayed error per horizon against the harvests.
GET {cycle}/export.csvOne row per week.

Walk corrections

Below, {walk} stands for /api/organizations/{org}/walks/{walk_id}, where walk_id is the walk's job id. See Correct a walk.

Method and pathWhat it does
GET {walk}/correctionsThe walk's corrections, its fruit after them, the crop-cycle weeks it is saved to, and the model and corrected counts.
POST {walk}/correctionsAdd one. kind is ripeness (track_id, ripeness), remove (track_id), add (ripeness, frame_id, box as [x1, y1, x2, y2] in pixels), or counts (counts with any of green, turning, red). Each takes an optional note.
PATCH {walk}/corrections/{correction_id}Change the ripeness, the box, the counts, or the note. The kind and the fruit stay.
DELETE {walk}/corrections/{correction_id}Undo one correction.

Every answer carries the walk's model and corrected counts. Any key of the organization may correct, admin or member. A walk of another organization reads as 404, and a walk still scoring as 409. A second correction on the same fruit, a second set of counts, or more than 2,000 corrections on one walk get 409. Counts are whole numbers from 0 to 1,000,000, and a note is at most 500 characters.

Session and status

Method and pathWhat it does
GET /api/healthWhether scoring and the database are available. No key needed.
GET / POST / DELETE /api/sessionRead (with the key's role), sign in (sets the cookie), or sign out.
GET / POST /api/organizations/{org}/keysList or create keys. Admin keys only; a new key is shown once.
PATCH …/keys/{id}, POST …/keys/{id}/revokeRename or revoke a key. The last admin key gets 409.