Photos
The photos endpoint returns the results per photo for your organisation. Each photo is an analysis which belongs to a specific batch.
Photos are only available on v2. GET /v1/photos returns 404 Not Found.
v2 — Paginated
Returns photos in pages. Each response includes a next_token field — if present, pass it in the next request to retrieve the following page. A page has up to 200 photos, or up to 40 with include=seedlings.
Endpoint: GET /v2/photos
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
start_date |
string (ISO 8601, UTC) |
No | Return photos of batches completed on or after this date |
end_date |
string (ISO 8601, UTC) |
No | Return photos of batches completed on or before this date |
next_token |
string |
No | Pagination cursor from the previous response |
include |
string |
No | seedlings adds the leaf area of each seedling |
Sample usage
# First page
curl https://portal-api.visiontrack.nl/v2/photos \
-H "Authorization: Bearer ACCESS_TOKEN"
# With seedlings
curl "https://portal-api.visiontrack.nl/v2/photos?include=seedlings" \
-H "Authorization: Bearer ACCESS_TOKEN"
import httpx
headers = {"Authorization": "Bearer ACCESS_TOKEN"}
next_token = None
while True:
params = {"include": "seedlings"}
if next_token:
params["next_token"] = next_token
resp = httpx.get("https://portal-api.visiontrack.nl/v2/photos", headers=headers, params=params)
resp.raise_for_status()
body = resp.json()
for photo in body["data"]:
print(photo["batch_id"], photo["analysis_id"], photo["germination_rate"])
next_token = body.get("next_token")
if not next_token:
break
Response
{
"data": [
{
"batch_id": "133b975c-8397-43e4-bb5a-e699f7b4b492",
"batch_name": "batch_abc789",
"batch_creation_date": "2025-05-20T16:22:10.123456+02:00",
"analysis_id": "64da0e89-2d77-48e9-b293-dac24c104013",
"germinated_seedlings": 110,
"non_germinated_seedlings": 18,
"germination_rate": "85.94",
"usable_seedlings": 105,
"non_usable_cells": 23,
"usable_seedling_rate": "82.03",
"coefficient_of_variation": "30.05",
"median_seedling_size_mm2": "383.18",
"warnings": false,
"analysis_link": "https://portal.example.com/batch-summary/abc/64da0e89",
"input_photo_link": "https://portal.example.com/analysis/input.jpg",
"detections_photo_link": "https://portal.example.com/analysis/assets/detections.jpg",
"seedlings": [
{ "leaf_area_mm2": 312.4, "leaf_area_pixels": 5120.0 }
]
}
],
"next_token": "MjAyNS0wNC0xMCAxNDoyNTo1Ni4wMDAwMDA"
}
If next_token is empty or null, you have reached the last page.
Response fields
| Field | Type | Description |
|---|---|---|
batch_id |
string |
Batch the photo belongs to, same as batch_id in Batches |
batch_name |
string |
Name of the batch, same as batch_name in Batches |
batch_creation_date |
string (ISO 8601) |
When the batch was created, same as batch_creation_date in Batches, see Date format |
analysis_id |
string |
Unique photo identifier |
germinated_seedlings |
integer \| null |
Germinated seedlings on the photo |
non_germinated_seedlings |
integer \| null |
Non-germinated seedlings on the photo |
germination_rate |
decimal \| null |
Germination rate (%) |
usable_seedlings |
integer \| null |
Usable seedlings on the photo |
non_usable_cells |
integer \| null |
Non-usable cells on the photo |
usable_seedling_rate |
decimal \| null |
Usable seedling rate (%) |
coefficient_of_variation |
decimal \| null |
Coefficient of variation of the seedling size (%) |
median_seedling_size_mm2 |
decimal \| null |
Median seedling size (mm²) |
warnings |
boolean |
Whether the photo has any warnings |
analysis_link |
string \| null |
URL to the analysis of the photo |
input_photo_link |
string \| null |
URL to the input photo |
detections_photo_link |
string \| null |
URL to the photo with the detections |
seedlings |
array |
Only with include=seedlings. One item per seedling: leaf_area_mm2 (decimal \| null) and leaf_area_pixels (decimal \| null) |
Only photos of batches where all photos are analysed are returned. For the date format, see Batches.