Appearance
Processing API
Automate your LiDAR pipeline end-to-end. The Processing API lets you upload files, trigger processing, and download results programmatically — ideal for batch workflows, integration with your own tools, or building LiDAR processing into your product.
The API is available exclusively on the Advanced plan ($249/month). See plans.
Not a developer? You can skip this page entirely. Everything the API does is also available through the web interface.
Overview
The API is a standard REST API that communicates using JSON. You interact with it by sending HTTP requests (GET, POST, DELETE) to specific URLs.
Base URL: https://cloud-pilot.lidarvisor.com/api
Authentication
Every API request must include your API key in the request header:
x-api-key: lvk_your_api_key_hereAPI keys are prefixed with lvk_ and are generated by the Lidarvisor team. Contact support or your account administrator to obtain one.
Important: Your API key grants full access to your account's processing capabilities. Keep it secret — do not share it in public code repositories, client-side code, or unsecured locations.
Workflow
The typical API workflow follows five steps:
1. Upload a file → creates a project
2. Wait for metadata extraction to complete
3. Start processing with your chosen options
4. Poll for processing status until complete
5. Download the resultsEndpoints
1. Upload a File
POST /v1/projects
Uploads a LAS or LAZ file and creates a new project.
Request: Multipart form data with:
file— the LAS/LAZ filename— a name for the projectepsgCode(optional) — the coordinate system EPSG code. If omitted, Lidarvisor will auto-detect it.callbackUrl(optional) — a URL that Lidarvisor will call when metadata extraction completes (see Webhooks below)
Response:
json
{
"id": "project-uuid",
"name": "My Survey Site",
"status": "uploaded"
}After upload, Lidarvisor automatically begins metadata extraction — reading the file properties and calculating the area. You must wait for this to complete before starting processing.
2. Check Metadata Status
GET /v1/projects/{id}/status
Check whether metadata extraction is complete.
Response:
json
{
"id": "project-uuid",
"status": "ready_to_process",
"area_hectares": 42.5,
"point_count": 185000000
}Possible status values:
uploaded— file received, metadata extraction not yet startedextracting_metadata— reading file propertiesready_to_process— ready to start processingprocessing— processing is in progresscompleted— processing finished successfullyfailed— something went wrong
3. Start Processing
POST /v1/projects/{id}/process
Start processing with your chosen options.
Request body:
json
{
"preset": "topography",
"callbackUrl": "https://your-server.com/webhook"
}Presets provide a convenient way to enable a predefined set of processing options:
| Preset | What It Enables |
|---|---|
topography | Classification + DTM + DSM + contour lines + topographic map |
forestry | Classification + DTM + CHM + tree tops + tree crowns + forest inventory |
powerline | Classification + DTM + DSM + power lines + towers + buffer zones + clearance + tree fall risk |
full | All of the above + buildings + roads + grid + slope analysis |
Alternatively, you can specify individual options instead of a preset:
json
{
"createDTM": true,
"resolutionDTM": 50,
"createContoursMajor": true,
"contoursMajor": 500,
"createContoursMinor": true,
"contoursMinor": 100,
"createBuildings": true,
"buildingsSimplification": "URBAN"
}See Processing Your Data for a full list of available options.
4. Check Processing Status
GET /v1/projects/{id}/status
Poll this endpoint to monitor processing progress.
Response during processing:
json
{
"id": "project-uuid",
"status": "processing",
"progress": 65
}Response when complete:
json
{
"id": "project-uuid",
"status": "completed"
}5. List Results
GET /v1/projects/{id}/results
Returns a list of all generated result files.
Response:
json
{
"results": [
{
"assetId": "asset-uuid-1",
"type": "CLASSIFIED_POINT_CLOUD",
"fileName": "classified_survey.las",
"fileSize": 524288000
},
{
"assetId": "asset-uuid-2",
"type": "DTM",
"fileName": "survey_dtm_50cm.tif",
"fileSize": 12582912
},
{
"assetId": "asset-uuid-3",
"type": "CONTOUR_LINE_MAJOR",
"fileName": "survey_contours_major.geojson",
"fileSize": 2097152
}
]
}6. Download a Result
GET /v1/projects/{id}/results/{assetId}/download?format=geojson
Returns a temporary download URL (valid for 12 hours).
Query parameters:
format(optional, for vector assets) —geojson,shapefile, ordxf
Response:
json
{
"downloadUrl": "https://storage.googleapis.com/...",
"expiresAt": "2026-04-01T12:00:00Z"
}7. List All Projects
GET /v1/projects?limit=10&offset=0
Returns a paginated list of your projects.
8. Delete a Project
DELETE /v1/projects/{id}
Permanently deletes a project and all its data.
Webhooks
Instead of repeatedly polling the status endpoint, you can provide a callback URL when uploading or starting processing. Lidarvisor will send an HTTP POST request to your URL when the operation completes.
Metadata Completion Webhook
Sent when metadata extraction finishes (after upload):
json
{
"event": "metadata.completed",
"projectId": "project-uuid",
"status": "ready_to_process"
}Processing Completion Webhook
Sent when processing finishes:
json
{
"event": "processing.completed",
"projectId": "project-uuid",
"status": "completed",
"results": [
{
"assetId": "asset-uuid",
"type": "DTM",
"fileName": "survey_dtm.tif"
}
]
}Failure Webhook
Sent if metadata extraction or processing fails:
json
{
"event": "processing.failed",
"projectId": "project-uuid",
"status": "failed"
}Example: Python Script
Here is a complete example using Python:
python
import requests
import time
API_KEY = "lvk_your_api_key_here"
BASE_URL = "https://cloud-pilot.lidarvisor.com/api"
HEADERS = {"x-api-key": API_KEY}
# Step 1: Upload
with open("survey.laz", "rb") as f:
response = requests.post(
f"{BASE_URL}/projects",
headers=HEADERS,
files={"file": f},
data={"name": "My Survey Site"}
)
project_id = response.json()["id"]
print(f"Project created: {project_id}")
# Step 2: Wait for metadata extraction
while True:
status = requests.get(
f"{BASE_URL}/projects/{project_id}/status",
headers=HEADERS
).json()
if status["status"] == "ready_to_process":
print(f"Ready. Area: {status['area_hectares']} ha")
break
elif status["status"] == "failed":
print("Metadata extraction failed")
exit(1)
time.sleep(10)
# Step 3: Start processing
requests.post(
f"{BASE_URL}/projects/{project_id}/process",
headers=HEADERS,
json={"preset": "topography"}
)
print("Processing started")
# Step 4: Wait for processing
while True:
status = requests.get(
f"{BASE_URL}/projects/{project_id}/status",
headers=HEADERS
).json()
if status["status"] == "completed":
print("Processing complete!")
break
elif status["status"] == "failed":
print("Processing failed")
exit(1)
print(f"Progress: {status.get('progress', '?')}%")
time.sleep(30)
# Step 5: Download results
results = requests.get(
f"{BASE_URL}/projects/{project_id}/results",
headers=HEADERS
).json()
for result in results["results"]:
download = requests.get(
f"{BASE_URL}/projects/{project_id}/results/{result['assetId']}/download",
headers=HEADERS
).json()
# Download the file
file_data = requests.get(download["downloadUrl"])
with open(result["fileName"], "wb") as f:
f.write(file_data.content)
print(f"Downloaded: {result['fileName']}")Rate Limiting
The API enforces rate limits to ensure fair usage. If you exceed the limit, you will receive a 429 Too Many Requests response. Wait and retry after a short delay.
Error Handling
All errors return a JSON response with a message:
json
{
"statusCode": 400,
"message": "File format not supported. Please upload a LAS or LAZ file."
}Common error codes:
400— Bad request (invalid parameters)401— Unauthorized (missing or invalid API key)403— Forbidden (insufficient permissions or plan)404— Not found (project or asset does not exist)429— Too many requests (rate limit exceeded)500— Server error (contact support)
Getting Help
- For API issues or questions: contact@lidarvisor.com
- Python and JavaScript SDKs are in development — check lidarvisor.com for updates
Next Step
For common questions, check the FAQ.