Bring your data into E2

Normalize user-owned observations, attach them to a known feature, store them locally, and create a portable data file.

Documentation navigation

Upload a dataset

upload.ts
import { StorageClient } from "@embed-earth/sdk-test/node";

const result = await new StorageClient().upload({
  path: "./observations.csv",
  database: "./e2.db",
  connectTo: "restaurant",
  output: "./observations.geoparquet",
});

console.log(result.rows, result.geoparquetPath);
Every row must resolve to an existing E2 feature. Use feature, connectTo, an explicit featureId, or existing row metadata.

Accepted input and options

InputRequired row dataNotes
GeoJSON / GeoJSON FeatureCollectiongeometry or lat/lngProperties are preserved.
CSVlat + lng, or latitude + longitudeThe first row is treated as headers.
Parquetlat/lng and feature metadataRows are read and normalized before indexing.

Optional upload settings include source, region, and observedAt. An existing valid e2_id is retained when its feature matches; otherwise the SDK creates a cell at spatial resolution 10 and temporal resolution 1d.

Normalized rows

row.json
{
  "feature_id": 101,
  "feature": "restaurant",
  "e2_id": "e2:1:...:1d:...:101",
  "lat": 40.74,
  "lng": -73.99,
  "geometry": { "type": "Point", "coordinates": [-73.99, 40.74] },
  "observed_at": "2026-08-18T09:00:00.000Z",
  "source": "user",
  "properties": {}
}

The result includes the number of imported rows, resolved feature key and ID, database path, and output file path.

Query the database

local.ts
import { LocalDatabase } from "@embed-earth/sdk-test/node";

const db = await LocalDatabase.open("./e2.db");
const rows = db.query({ feature: "restaurant", window: "30d", limit: 100 });
const stats = db.stats();
db.close();