Use the upload service to create many field boundaries at once from shapefiles, GeoJSON, or KML/KMZ files. This page covers the upload endpoints, supported formats, status values, and the follow-up calls you use to inspect results.
For conceptual background, see Uploading Boundaries.
Base URL
https://api.withleaf.io/services/uploadservice/api
Endpoints
| Endpoint | Method | Path |
|---|
| Upload a field file | POST | /upload |
| Get all uploads | GET | /upload |
| Get an upload | GET | /upload/{uploadId} |
| Get upload entries | GET | /upload/{uploadId}/entries |
You can upload field boundaries in the following formats:
- Shapefile — packaged as a
.zip containing .shp, .shx, .dbf, and optionally .prj
- GeoJSON —
.json or .geojson
- KML / KMZ —
.kml or .kmz
Leaf reprojects all uploaded geometries to WGS 84 (EPSG:4326).
Upload limits
| Constraint | Limit |
|---|
| Maximum file size | 3 GB |
| Maximum fields per upload | 100 |
Upload and entry statuses
Each upload progresses through the following statuses:
| Upload status | Description |
|---|
RECEIVED | The file has been received and is queued for processing. |
PROCESSED | All files in the upload have finished processing, and at least one recognized file created fields successfully. |
FAILED | The upload did not generate any field boundaries successfully. |
Individual entries within an upload have their own statuses:
| Entry status | Description |
|---|
PROCESSING | The entry is being converted and validated. |
CONVERTED | The geometry has been converted and is pending field creation. |
FINISHED | The field has been created from this entry. |
FAILED | The entry could not be processed. |
PARTIALLY_FINISHED | Some geometries in the entry succeeded while others failed. |
Upload a field file
POST /upload
Uploads a field boundary file for the specified Leaf user. The file is processed asynchronously. Use the Get an upload or Get upload entries endpoints to track progress.
Parameters
| Parameter | Type | Description |
|---|
leafUserId | query (UUID) | Required. The Leaf user who owns the fields. |
farmId | query (integer) | Optional farm to associate with the uploaded fields. |
Request
curl -X POST \
-H 'Authorization: Bearer YOUR_TOKEN' \
-F 'file=@/path/to/boundaries.zip' \
'https://api.withleaf.io/services/uploadservice/api/upload?leafUserId=UUID'
Response
{
"id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"leafUserId": "7494c90e-28b8-4bb2-9ede-95c1cc894349",
"originalFileUrl": "https://storage.withleaf.io/upload/f1e2d3c4-b5a6-7890-abcd-ef1234567890.zip",
"fileName": "boundaries.zip",
"status": "RECEIVED",
"createdTime": "2024-01-15T19:48:51.017Z"
}
If the .zip does not contain the required shapefile components (.shp, .shx, .dbf), the upload fails with status FAILED.
Get all uploads
GET /upload
Returns a paginated list of field boundary uploads.
Parameters
| Parameter | Type | Description |
|---|
leafUserId | string (UUID) | Filter by Leaf user. |
status | string | RECEIVED, PROCESSED, or FAILED. |
page | integer | Page number (default 0). |
size | integer | Page size (default 20). |
Request
curl -X GET \
-H 'Authorization: Bearer YOUR_TOKEN' \
'https://api.withleaf.io/services/uploadservice/api/upload?leafUserId=UUID'
Response
[
{
"id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"leafUserId": "7494c90e-28b8-4bb2-9ede-95c1cc894349",
"originalFileUrl": "https://storage.withleaf.io/upload/f1e2d3c4-b5a6-7890-abcd-ef1234567890.zip",
"fileName": "boundaries.zip",
"status": "PROCESSED",
"createdTime": "2024-01-15T19:48:51.017Z"
}
]
Get an upload
GET /upload/{uploadId}
Returns a single field boundary upload by its ID.
Parameters
| Parameter | Type | Description |
|---|
uploadId | path (UUID) | The upload ID. |
Request
curl -X GET \
-H 'Authorization: Bearer YOUR_TOKEN' \
'https://api.withleaf.io/services/uploadservice/api/upload/{uploadId}'
Response
{
"id": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"leafUserId": "7494c90e-28b8-4bb2-9ede-95c1cc894349",
"originalFileUrl": "https://storage.withleaf.io/upload/f1e2d3c4-b5a6-7890-abcd-ef1234567890.zip",
"fileName": "boundaries.zip",
"status": "PROCESSED",
"createdTime": "2024-01-15T19:48:51.017Z"
}
Get upload entries
GET /upload/{uploadId}/entries
Returns the individual entries for each recognized file extracted from an upload. Each entry tracks its own processing status and lists the Leaf field IDs created from that recognized file.
Parameters
| Parameter | Type | Description |
|---|
uploadId | path (UUID) | The upload ID. |
page | integer | Page number (default 0). |
size | integer | Page size (default 20). |
Request
curl -X GET \
-H 'Authorization: Bearer YOUR_TOKEN' \
'https://api.withleaf.io/services/uploadservice/api/upload/{uploadId}/entries'
Response
[
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"uploadId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"leafUserId": "7494c90e-28b8-4bb2-9ede-95c1cc894349",
"fieldId": [
"0071484f-4a75-4190-9fd0-f5995d241c2c",
"9c2d4d24-9f31-4c0b-9b4b-7a5df4d0d5b6"
],
"converterFormat": "GEOJSON",
"originalFileUrl": "https://storage.withleaf.io/upload/entries/a1b2c3d4.geojson",
"status": "FINISHED",
"createFieldErrorDetails": [],
"createdTime": "2024-01-15T19:48:51.017Z",
"processedTime": "2024-01-15T19:49:20.104Z"
}
]
Poll the entries endpoint to track each recognized file inside the upload. Use the fieldId array to fetch the created fields from the Fields API, and inspect createFieldErrorDetails when a file finishes with FAILED or PARTIALLY_FINISHED.