Skip to main content
Use the Leaf Lake endpoint to run SQL queries against your operation data, SSURGO soil polygons, and US state/county boundaries. Queries are automatically scoped to the authenticated API owner. Leaf Lake uses BigQuery SQL. For schema details and example queries, see Querying Leaf Lake.

Base URL

https://api.withleaf.io/services/pointlake/api/v2

Endpoints

MethodPathDescription
POST/queryExecute a SQL query
GET/queryExecute a SQL query (via query parameter)
POST/export-query-geoparquetExport query results as GeoParquet

Execute a SQL query

POST /query Executes a SQL query against the Leaf Lake tables and returns the results as a JSON array of rows. All queries are scoped to the authenticated API owner. You can only access data belonging to your own Leaf users. Only read queries are allowed (SELECT, WITH, ORDER BY, UNION). Write operations are not supported. This endpoint accepts both POST (SQL in the request body) and GET (SQL in the sql query parameter). POST is recommended for longer queries.

POST request

Send the SQL query as the request body with Content-Type: text/plain.
HeaderValue
AuthorizationBearer YOUR_TOKEN
Content-Typetext/plain

GET request

Pass the SQL as the sql query parameter. Useful for short queries or browser testing.
GET /query?sql=SELECT+operationType,+COUNT(*)+AS+cnt+FROM+points+GROUP+BY+operationType

Request body (POST)

The raw SQL query as plain text. See Querying Leaf Lake for available tables, columns, and example queries.

Request

curl -X POST \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: text/plain' \
  -d "SELECT operationType, crop, COUNT(*) AS point_count FROM points GROUP BY operationType, crop" \
  'https://api.withleaf.io/services/pointlake/api/v2/query'

Response

The response is a JSON array where each element is an object representing one row. Column names match the aliases used in the SQL query.
[
  {
    "operationType": "planted",
    "crop": "corn",
    "point_count": 48523
  },
  {
    "operationType": "harvested",
    "crop": "corn",
    "point_count": 52104
  },
  {
    "operationType": "applied",
    "crop": "corn",
    "point_count": 31890
  },
  {
    "operationType": "harvested",
    "crop": "soybeans",
    "point_count": 44217
  }
]

Query by field ID

The simplest way to scope a query to a specific field is by Leaf field UUID using the fieldIds column on the points table. No WKT boundary polygon needed.
curl -X POST \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: text/plain' \
  -d "SELECT crop, ROUND(AVG(wetMassPerArea) / 62.77, 1) AS avg_yield_bu_ac, COUNT(*) AS points FROM points WHERE operationType = 'harvested' AND 'YOUR_FIELD_UUID' IN UNNEST(fieldIds) GROUP BY crop" \
  'https://api.withleaf.io/services/pointlake/api/v2/query'

Spatial query example

You can also filter by geography using spatial functions and a WKT boundary polygon.
curl -X POST \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: text/plain' \
  -d "SELECT crop, ROUND(AVG(wetMassPerArea) / 62.77, 1) AS avg_yield_bu_ac, COUNT(*) AS points FROM points WHERE operationType = 'harvested' AND ST_Intersects(geometry, ST_GeogFromText('POLYGON((-89.80 40.47, -89.81 40.47, -89.81 40.48, -89.80 40.48, -89.80 40.47))')) GROUP BY crop" \
  'https://api.withleaf.io/services/pointlake/api/v2/query'

Error handling

Status codeMeaning
200Query executed successfully
204Query executed but returned no rows
400Invalid SQL syntax, unknown table/column, or non-SELECT query
401Missing or expired Bearer token
403Insufficient permissions
When a 400 error occurs, the response body contains a Problem JSON (RFC 7807) object with details about the issue.
A 204 No Content response has no body. Check the status code before attempting to parse JSON.

Export query results as GeoParquet

POST /export-query-geoparquet Runs a SQL query and returns the results as a downloadable GeoParquet file instead of JSON. Useful when you need to load results directly into GIS software or spatial analysis tools. The request format is the same as the query endpoint — send the SQL as the request body with Content-Type: text/plain.

Request

curl -X POST \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: text/plain' \
  -d "SELECT crop, wetMassPerArea, geometry FROM points WHERE operationType = 'harvested' AND ST_Intersects(geometry, ST_GeogFromText('POLYGON((-89.80 40.47, -89.81 40.47, -89.81 40.48, -89.80 40.48, -89.80 40.47))'))" \
  -o results.parquet \
  'https://api.withleaf.io/services/pointlake/api/v2/export-query-geoparquet'

Response

The response is a binary GeoParquet file with Content-Type: application/octet-stream. Save the response body to a .parquet file to use with tools like GeoPandas, QGIS, or DuckDB.

What to do next

Last modified on March 24, 2026