Skip to main content

Validation

Run validation checks against your synthetic datasets. Lucitra scores data across four dimensions — coverage, physics plausibility, distribution quality, and sim-to-real gap — each producing a score from 0 to 100.

Validation Types

Coverage

Checks whether your dataset adequately covers required scenarios, object classes, edge cases, and environmental conditions.

Physics

Detects physically impossible artifacts — intersecting geometry, impossible lighting, unrealistic materials, and gravity violations.

Sim-to-Real

Quantifies domain gap by comparing your synthetic data against a real-world reference dataset.

Full

Runs all validation checks in a single pass. Requires a reference dataset for the sim-to-real component.

Run a Validation

All validation endpoints accept a dataset ID and return immediately with a run_id for polling. The actual validation runs asynchronously.
Evaluate scenario and class coverage without a reference dataset.
curl -X POST https://api.lucitra.io/v1/validate/coverage \
  -H "Authorization: Bearer luci_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "dataset_id": "ds_7kx9m2",
    "options": {
      "min_class_samples": 50,
      "required_conditions": ["rain", "night", "fog"]
    }
  }'
dataset_id
string
required
The dataset to validate.
options
object
Validation-specific configuration. For coverage, you can set min_class_samples and required_conditions.
All validation endpoints return 202 Accepted:
{
  "run_id": "run_3fa85f64",
  "status": "queued"
}

Poll for Status

Validation runs progress through three statuses before completing.
queued → running → completed | failed
curl "https://api.lucitra.io/v1/validate/run_3fa85f64/status" \
  -H "Authorization: Bearer luci_your_api_key"
{
  "run_id": "run_3fa85f64",
  "status": "running",
  "progress": 0.45,
  "estimated_time_remaining": 120,
  "report_id": null
}
run_id
string
required
The validation run identifier.
status
string
required
Current status: queued, running, completed, or failed.
progress
float
required
Completion fraction from 0.0 to 1.0.
estimated_time_remaining
integer
Estimated seconds until completion. Null when queued or failed.
report_id
string
The generated report ID. Only present when status is completed.

Polling Pattern

Use this pattern to wait for a validation run to complete.
import time
import requests

def wait_for_validation(run_id, api_key, interval=5, timeout=600):
    """Poll until validation completes or times out."""
    url = f"https://api.lucitra.io/v1/validate/{run_id}/status"
    headers = {"Authorization": f"Bearer {api_key}"}
    elapsed = 0

    while elapsed < timeout:
        resp = requests.get(url, headers=headers)
        resp.raise_for_status()
        data = resp.json()

        if data["status"] == "completed":
            print(f"Validation complete. Report: {data['report_id']}")
            return data
        elif data["status"] == "failed":
            raise RuntimeError(f"Validation failed: {data}")

        print(f"Status: {data['status']} | Progress: {data['progress']:.0%}")
        time.sleep(interval)
        elapsed += interval

    raise TimeoutError(f"Validation {run_id} did not complete within {timeout}s")


result = wait_for_validation("run_3fa85f64", "luci_your_api_key")

Rate Limits

Each plan includes a monthly validation run limit. If you exceed your quota, the API returns 429 Too Many Requests with details about when your limit resets.
{
  "error": "monthly_run_limit_exceeded",
  "limit": 100,
  "used": 100,
  "resets_at": "2026-04-01T00:00:00Z"
}
Use webhooks instead of polling for production workflows. They deliver real-time notifications when validation runs complete or fail.