Skip to content

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_here

API 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 results

Endpoints

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 file
  • name — a name for the project
  • epsgCode (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 started
  • extracting_metadata — reading file properties
  • ready_to_process — ready to start processing
  • processing — processing is in progress
  • completed — processing finished successfully
  • failed — 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:

PresetWhat It Enables
topographyClassification + DTM + DSM + contour lines + topographic map
forestryClassification + DTM + CHM + tree tops + tree crowns + forest inventory
powerlineClassification + DTM + DSM + power lines + towers + buffer zones + clearance + tree fall risk
fullAll 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, or dxf

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.

Lidarvisor — Process LiDAR in Minutes, Not Hours