Getting started

Quickstart

Capture a real site with WaveForm Field, publish a nav-pack, and pull it from a test robot — in about 30 minutes.

What you'll need
  • An iPhone with LiDAR (12 Pro or newer).
  • A WaveForm account at app.waveform.vision. Sign-up takes one email round-trip.
  • Python 3.10+ on your laptop for the admin SDK + nav-pack publish.

Step 1 — Sign up + create a customer

Visit app.waveform.vision/signup and complete the magic-link flow. You’ll land on the project picker with a single empty customer scope. Note your customer_id — every API call below carries it.

Step 2 — Capture a site (WaveForm Field)

  1. Install WaveForm Field from TestFlight (or the App Store once GA).
  2. Sign in with the same email — the iOS app uses the same magic-link flow as the web app.
  3. Tap New site, drop a pin on a map, and tap Start capture.
  4. Walk a slow loop (about 0.5 m/s) around the area of interest. The coverage heatmap turns green as you go.
  5. Tap Finish. The app queues the bundle and uploads opportunistically — you can finish in the field with no signal and let it sync at home.
Watching the upload
Pull the in-app upload panel to see per-bundle progress. Each bundle is HMAC-signed by the device key, so the server only accepts captures it can prove came from your phone.

Step 3 — Wait for reconstruction

Once the bundle finishes uploading, the platform queues a reconstruction job. For an indoor scene of ~200 frames this takes 5–10 minutes. You can watch it run in the web app under Sites → your site → Snapshots.

The reconstruction produces a georeferenced 3D snapshot, which is the input to nav-pack publishing.

Step 4 — Publish a nav-pack

Install the admin SDK and authenticate with a platform-admin API token (see Settings → API keys in the web app):

bash
pip install waveform-nav-pack-sdk
export WAVEFORM_API_TOKEN=sk_...
export WAVEFORM_BASE_URL=https://api.waveform.vision

Then in Python:

python
import asyncio
import httpx
from rough_rider.clients.nav_pack_client import NavPackClient

async def main():
    async with httpx.AsyncClient(
        base_url="https://api.waveform.vision",
        headers={"Authorization": f"Bearer {os.environ['WAVEFORM_API_TOKEN']}"},
    ) as http:
        client = NavPackClient(http=http)
        # Resolve the area you captured — the site_id is shown in the
        # web app's URL bar when you open the snapshot.
        area = await client.resolve_area(site_ids=["<site_id>"])
        # Publish a viewer-profile pack pointing at the latest snapshot.
        pack = await client.publish({
            "area_id": area.area_id,
            "profile_key": "viewer",
            "produced_at": "2026-05-28T00:00:00Z",
            "layers": [
                {"layer_kind": "manifest", "role": "required"},
            ],
        })
        print("published:", pack.pack_version_id)

asyncio.run(main())

Step 5 — Pull the pack from a robot

Register a robot, issue a device token, then fetch the manifest as that robot:

bash
# 1. Register the robot (admin)
curl -X POST https://api.waveform.vision/v1/robots \
  -H "Authorization: Bearer $WAVEFORM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fleet_id":"demo","display_name":"r1"}'
# → {"data": {"robot_id": "..."}}

# 2. Issue a device token (admin)
curl -X POST https://api.waveform.vision/v1/robots/<robot_id>/tokens \
  -H "Authorization: Bearer $WAVEFORM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"scopes":["nav_pack:read"]}'
# → {"data": {"token": "eyJhbGc...", ...}}

# 3. Use the device token to fetch the manifest (as the robot)
curl https://api.waveform.vision/v1/areas/<area_id>/nav-pack \
  -H "Authorization: Bearer <robot-token>"

The third call returns the signed manifest the robot would consume offline.

Doing this from Swift?
See the Swift SDK page — the client mirrors the Python one and exposes the same six read methods.

What to do next

  • Browse the concepts page if any of the vocabulary felt unfamiliar.
  • Read publishing to understand the signed-manifest contract in depth.
  • For an automated pipeline, set up webhooks so your systems get pinged when a pack is published.
Docs — WaveForm — WaveForm