> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wherobots.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bring Your Own Spark (Databricks)

> Install and run the WherobotsDB JAR on your own Databricks cluster as a drop-in replacement for Apache Sedona, so your data never leaves your Databricks workspace.

**Bring Your Own Spark (BYOS)** lets you run WherobotsDB on a Spark cluster you own and operate. WherobotsDB is a drop-in replacement for Apache Sedona: you install its JAR on your existing cluster, and your existing code, SQL, and configuration continue to work unchanged.

Your data never leaves your Databricks workspace. Wherobots does not run, manage, or connect to your cluster — the only outbound traffic is a lightweight authenticated call from the JAR to Wherobots Cloud for license metering.

This guide covers Databricks. The WherobotsDB DBR JAR is fully compatible with Databricks Runtime, including **Photon-enabled** clusters.

<Note>
  BYOS is distinct from [Bring Your Own Cloud (BYOC)](/develop/storage-management/byoc). Under BYOC, Wherobots runs its own managed compute inside your cloud account. Under BYOS, you run your own Spark cluster and Wherobots supplies only the engine.

  For Amazon EMR clusters, see [Bring Your Own Spark (AWS EMR)](/develop/deployment-options/byos-aws-emr) instead.
</Note>

## For existing Apache Sedona users

If you already run Apache Sedona on Databricks, migrating to WherobotsDB takes two required changes, plus one optional improvement.

<Steps>
  <Step title="Replace the JAR">
    Swap the public Apache Sedona JAR for the WherobotsDB DBR JAR that Wherobots supplies, and update your init script to copy the new file.

    | Old JAR                              | New JAR                                  |
    | ------------------------------------ | ---------------------------------------- |
    | `sedona-spark-shaded-3.5_2.12-*.jar` | `sedona-dbr-spark-shaded-3.5_2.12-*.jar` |
    | `sedona-spark-shaded-4.0_2.13-*.jar` | `sedona-dbr-spark-shaded-4.0_2.13-*.jar` |

    The WherobotsDB build adds the enterprise functions, Wherobots Cloud authentication, and the metering client.
  </Step>

  <Step title="Add your Wherobots API key">
    Add one Spark configuration entry to your cluster:

    ```text theme={"system"}
    spark.wherobots.api.key {{secrets/YOUR_SCOPE/wherobots-api-key}}
    ```

    See [How Wherobots authentication works](#how-wherobots-authentication-works).
  </Step>

  <Step title="Optionally switch the Python client">
    `wherobots-sedona` provides the fullest Python support for the WherobotsDB JARs, but `apache-sedona` continues to work. See [Install the Python client](#install-the-python-client).
  </Step>
</Steps>

All existing code, SQL queries, and cluster configuration continue to work. No code changes are required.

## Before you start

The following requirements must be met within both your Wherobots Organization and your Databricks workspace:

<AccordionGroup cols={2}>
  <Accordion title="Wherobots Requirements" icon="cloud">
    * An **Admin** account within a **Professional**, **Innovation**, or **Enterprise** Edition Organization.
          <Note>
            Wherobots Organization members with the **User** role can use a cluster an Admin has already set up, but cannot create the API key this deployment requires. See [Organization Roles](/get-started/organization-info/organization-roles/).
          </Note>
    * Community Edition is not supported. See [Organization Editions](/get-started/organization-management/organization-editions) or [Upgrade Organization](/get-started/upgrade-organization/).
    * The **BYOS feature enabled on your Organization**. Contact Wherobots to enable it. BYOS unlocks both halves of this deployment: read access to the WherobotsDB release artifacts, and the runtime authentication and usage-reporting endpoints the JAR calls. Without it, those endpoints return `403` and cluster initialization fails.
    * A **Wherobots API key**. See [How Wherobots authentication works](#how-wherobots-authentication-works).
  </Accordion>

  <Accordion title="Databricks Requirements" icon="server">
    * A Databricks workspace with **admin permissions**.
    * Permission to create clusters, add init scripts, and install cluster libraries.
    * A supported **Databricks Runtime** — see [Version compatibility](#version-compatibility).
    * A **Unity Catalog volume** if you plan to use Shared access mode clusters. Init scripts and JARs for Shared clusters must live in a volume, not in the workspace file system.
    * **Outbound HTTPS (port 443)** from the cluster to Wherobots Cloud, for license metering. A workspace with restricted egress needs Wherobots Cloud allowed; without it, `SedonaContext.create` fails to authenticate.
    * The WherobotsDB release artifacts from Wherobots: the `sedona-dbr-spark-shaded-*` JAR, the `geotools-wrapper` JAR, and the `wherobots_sedona` Python wheel. These are not published to Maven Central or PyPI.
  </Accordion>
</AccordionGroup>

<Note>
  Once BYOS is enabled for your Organization, a read-only **WherobotsDB Releases** storage source appears automatically in your Wherobots Cloud storage list. Go to **Storage**, open that source, and download the JARs and wheel from the release folder. If the source does not appear, BYOS is not yet enabled — contact Wherobots.
</Note>

## Version compatibility

Choose the JAR and Python wheel that match your Databricks Runtime. Wherobots recommends **Long-Term Support (LTS)** runtimes for production stability.

| Databricks Runtime        | Spark | Scala | Python | JDK                                  | JAR artifact                                   | Wheel tag |
| ------------------------- | ----- | ----- | ------ | ------------------------------------ | ---------------------------------------------- | --------- |
| **14.3 LTS**              | 3.5.0 | 2.12  | 3.10   | 8 by default — see the warning below | `sedona-dbr-spark-shaded-3.5_2.12-VERSION.jar` | `cp310`   |
| **16.4 LTS** (Scala 2.12) | 3.5.2 | 2.12  | 3.12   | 17                                   | `sedona-dbr-spark-shaded-3.5_2.12-VERSION.jar` | `cp312`   |
| **16.4 LTS** (Scala 2.13) | 3.5.2 | 2.13  | 3.12   | 17                                   | `sedona-dbr-spark-shaded-3.5_2.13-VERSION.jar` | `cp312`   |
| **17.3 LTS**              | 4.0.0 | 2.13  | 3.12   | 17                                   | `sedona-dbr-spark-shaded-4.0_2.13-VERSION.jar` | `cp312`   |

A Spark or Scala mismatch surfaces at runtime as `NoSuchMethodError` or `ClassNotFoundException`.

<Warning>
  DBR 16.4 LTS ships in **two variants**, one built against Scala 2.12 and one against Scala 2.13. They are separate runtime selections in the Databricks UI, and they need different JARs. Confirm which one your cluster uses before choosing — the release bundle contains both.
</Warning>

<Warning>
  **DBR 14.3 requires a JDK change.** WherobotsDB JARs are compiled against JDK 17, and DBR 14.3 defaults to JDK 8. The cluster will fail with `UnsupportedClassVersionError` unless you switch it: add the Spark environment variable `JNAME=zulu17-ca-amd64` under **Advanced options → Spark → Environment variables**. DBR 15.0 and later run on JDK 17 by default, so this applies only to 14.3.
</Warning>

<Warning>
  Use the `sedona-dbr-spark-shaded-*` JAR. The `sedona-emr-spark-shaded-*` JAR in the same bundle is built for Amazon EMR and other vanilla Spark environments and will not work on Databricks Runtime, and the public `sedona-spark-shaded-*` JAR on Maven Central is the open-source Apache Sedona build without the WherobotsDB enterprise features.
</Warning>

WherobotsDB is versioned independently of Apache Sedona. Each WherobotsDB release is API-compatible with a specific Apache Sedona version, and the GeoTools wrapper version follows the Sedona version — so `VERSION` and `GEOTOOLS_VERSION` are different values. For example:

| WherobotsDB (`VERSION`) | Compatible Apache Sedona | GeoTools wrapper (`GEOTOOLS_VERSION`) |
| ----------------------- | ------------------------ | ------------------------------------- |
| `1.28.0`                | `1.9.0`                  | `1.9.0-33.5`                          |

Always use the exact filenames Wherobots delivered to you.

## Install WherobotsDB on a Databricks cluster

Installing WherobotsDB involves staging its artifacts where the cluster can read them, adding an init script that copies the JARs into place at startup, and configuring the cluster to load them. Complete the sections in order.

| # | Section                                                 | Purpose                                                                                                |
| - | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| 1 | [Choose a storage location](#choose-a-storage-location) | Decide between Unity Catalog volumes and the workspace file system, based on your cluster access mode. |
| 2 | [Stage the JARs](#stage-the-jars)                       | Upload the WherobotsDB and GeoTools JARs.                                                              |
| 3 | [Create the init script](#create-the-init-script)       | Write the script that copies the JARs into the cluster's JAR directory at startup.                     |
| 4 | [Configure the cluster](#configure-the-cluster)         | Set the Spark properties, attach the init script, and set the JDK on DBR 14.3.                         |
| 5 | [Install the Python client](#install-the-python-client) | Add `wherobots-sedona` as a cluster library.                                                           |
| 6 | [Validate the installation](#validate-the-installation) | Confirm WherobotsDB is installed, licensed, and running.                                               |

### Choose a storage location

Databricks offers two places to keep the JARs and init script. Your cluster's access mode determines which one you can use.

| Storage                  | Path form                      | Use when                                                                  |
| ------------------------ | ------------------------------ | ------------------------------------------------------------------------- |
| **Unity Catalog volume** | `/Volumes/CATALOG/SCHEMA/NAME` | Required for **Shared** access mode clusters. Works for all access modes. |
| **Workspace files**      | `/Workspace/Shared/...`        | **Single user** access mode clusters only.                                |

<Warning>
  Shared access mode clusters cannot read init scripts or JARs from the workspace file system. If you plan to use Shared clusters — or expect to later — stage everything in a Unity Catalog volume from the start. Moving an init script after the fact means editing every cluster that references it.
</Warning>

This guide uses `/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots` as the example volume path. Substitute your own throughout.

### Stage the JARs

<Tabs>
  <Tab title="Unity Catalog volume">
    <Steps>
      <Step title="Create the volume">
        In a Databricks notebook or the SQL editor, run:

        ```sql theme={"system"}
        CREATE VOLUME IF NOT EXISTS YOUR_CATALOG.YOUR_SCHEMA.wherobots;
        ```

        You need `CREATE VOLUME` on the schema. See [Create and manage volumes](https://docs.databricks.com/aws/en/volumes/utility-commands) in the Databricks documentation.
      </Step>

      <Step title="Create the jars subdirectory">
        ```python theme={"system"}
        dbutils.fs.mkdirs("/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/jars")
        ```
      </Step>

      <Step title="Upload both JARs">
        Using the Databricks CLI from your local machine:

        ```bash wrap theme={"system"}
        VOLUME=/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/jars

        databricks fs cp sedona-dbr-spark-shaded-3.5_2.12-VERSION.jar dbfs:$VOLUME/
        databricks fs cp geotools-wrapper-GEOTOOLS_VERSION.jar        dbfs:$VOLUME/
        ```

        You can also upload through the Catalog Explorer UI: open the volume, then select **Upload to this volume**.
      </Step>

      <Step title="Verify">
        ```python theme={"system"}
        display(dbutils.fs.ls("/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/jars"))
        ```

        Both JARs must appear with a non-zero size.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Workspace files">
    <Steps>
      <Step title="Create the directory">
        In a Databricks notebook:

        ```bash theme={"system"}
        %sh
        mkdir -p /Workspace/Shared/wherobots/jars
        ```
      </Step>

      <Step title="Upload both JARs">
        In the Databricks UI, navigate to **Workspace → Shared → wherobots → jars**, then select **Import** and upload both JAR files.
      </Step>

      <Step title="Verify">
        ```bash theme={"system"}
        %sh
        ls -la /Workspace/Shared/wherobots/jars/
        ```
      </Step>
    </Steps>

    <Warning>
      This path works only for Single user access mode clusters. See [Choose a storage location](#choose-a-storage-location).
    </Warning>
  </Tab>
</Tabs>

### Create the init script

An init script runs on every node of the cluster during startup, before Spark begins accepting work. This one copies the WherobotsDB JARs into `/databricks/jars`, the directory Databricks adds to the Spark classpath.

Write the script to the same place you staged the JARs in [Stage the JARs](#stage-the-jars). Use the tab matching that choice.

<Tabs>
  <Tab title="Unity Catalog volume">
    <Steps>
      <Step title="Write the script">
        Run this cell in a notebook, substituting your volume path in **both** the `cat >` destination and `JARS_SRC`.

        ```bash wrap theme={"system"}
        %sh
        mkdir -p /Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/init

        cat > /Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/init/wherobots-init.sh <<'EOF'
        #!/bin/bash
        set -euo pipefail

        JARS_SRC="/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/jars"

        echo "[wherobots-init] Copying WherobotsDB JARs from ${JARS_SRC} ..."
        cp "${JARS_SRC}"/*.jar /databricks/jars/

        echo "[wherobots-init] Verifying:"
        ls -la /databricks/jars/sedona-dbr*.jar /databricks/jars/geotools-wrapper*.jar

        echo "[wherobots-init] Done."
        EOF
        ```
      </Step>

      <Step title="Confirm it was written">
        ```bash theme={"system"}
        %sh
        cat /Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/init/wherobots-init.sh
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Workspace files">
    <Steps>
      <Step title="Write the script">
        Run this cell in a notebook, substituting your path in **both** the `cat >` destination and `JARS_SRC` if you did not use the default.

        ```bash wrap theme={"system"}
        %sh
        mkdir -p /Workspace/Shared/wherobots/init

        cat > /Workspace/Shared/wherobots/init/wherobots-init.sh <<'EOF'
        #!/bin/bash
        set -euo pipefail

        JARS_SRC="/Workspace/Shared/wherobots/jars"

        echo "[wherobots-init] Copying WherobotsDB JARs from ${JARS_SRC} ..."
        cp "${JARS_SRC}"/*.jar /databricks/jars/

        echo "[wherobots-init] Verifying:"
        ls -la /databricks/jars/sedona-dbr*.jar /databricks/jars/geotools-wrapper*.jar

        echo "[wherobots-init] Done."
        EOF
        ```
      </Step>

      <Step title="Confirm it was written">
        ```bash theme={"system"}
        %sh
        cat /Workspace/Shared/wherobots/init/wherobots-init.sh
        ```
      </Step>
    </Steps>

    <Warning>
      This path works only for Single user access mode clusters. See [Choose a storage location](#choose-a-storage-location).
    </Warning>
  </Tab>
</Tabs>

<Note>
  The placeholders inside the heredoc are **not** substituted for you. `<<'EOF'` is quoted, so the shell writes the script verbatim — including a literal `YOUR_CATALOG` if you forget to replace it. Edit the cell before running it.
</Note>

<Warning>
  The init script fails the cluster if the JARs are missing, because `set -euo pipefail` makes the failed `cp` fatal. That is deliberate: a cluster that starts without the JARs looks healthy and fails every spatial query later.
</Warning>

### Configure the cluster

<Steps>
  <Step title="Create the cluster">
    Go to **Compute → Create compute**, then choose:

    * A **Databricks Runtime** from [Version compatibility](#version-compatibility).
    * An **access mode** consistent with your storage choice — Shared requires a Unity Catalog volume.
    * Either the **Standard** or **Photon** runtime engine. Both are supported.
  </Step>

  <Step title="Add the Spark configuration">
    Under **Advanced options → Spark → Spark config**, add these lines:

    ```text wrap theme={"system"}
    spark.serializer org.apache.spark.serializer.KryoSerializer
    spark.kryo.registrator org.apache.sedona.core.serde.SedonaKryoRegistrator
    spark.sedona.enableParserExtension false
    spark.sql.extensions org.apache.sedona.viz.sql.SedonaVizExtensions,org.apache.sedona.sql.SedonaSqlExtensions
    spark.wherobots.api.key {{secrets/YOUR_SCOPE/wherobots-api-key}}
    ```

    | Property                                     | Purpose                                               |
    | -------------------------------------------- | ----------------------------------------------------- |
    | `spark.serializer`, `spark.kryo.registrator` | Configure Kryo serialization for geometry types       |
    | `spark.sedona.enableParserExtension`         | Must remain `false`                                   |
    | `spark.sql.extensions`                       | Registers the `ST_*` SQL functions                    |
    | `spark.wherobots.api.key`                    | Your Wherobots API key, read from a Databricks secret |

    <Warning>
      `spark.sql.extensions` must be a single line, and the value you set here **replaces** any value already in effect. If your cluster registers other extensions, append the two Sedona entries to your existing list rather than pasting this line verbatim.
    </Warning>

    <Warning>
      Do not paste the API key itself into the Spark config. Values there are visible to anyone who can view the cluster. Use the `{{secrets/SCOPE/KEY}}` syntax shown above — Databricks resolves it at startup and redacts it from the UI. See [How Wherobots authentication works](#how-wherobots-authentication-works).
    </Warning>
  </Step>

  <Step title="Set the JDK on DBR 14.3">
    Only required on DBR 14.3. Under **Advanced options → Spark → Environment variables**, add:

    ```text theme={"system"}
    JNAME=zulu17-ca-amd64
    ```

    Skip this step on DBR 15.0 and later, which already run JDK 17.
  </Step>

  <Step title="Attach the init script">
    Under **Advanced options → Init scripts**, add the path you created:

    | Storage              | Path to enter                                                        |
    | -------------------- | -------------------------------------------------------------------- |
    | Unity Catalog volume | `/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/init/wherobots-init.sh` |
    | Workspace files      | `/Workspace/Shared/wherobots/init/wherobots-init.sh`                 |

    Select the matching source type (**Volumes** or **Workspace**) in the dropdown beside the path.
  </Step>
</Steps>

### Install the Python client

The `wherobots-sedona` Python client ships as prebuilt wheels in the WherobotsDB release bundle.

<Warning>
  `wherobots-sedona` is **not published to PyPI**. Choosing **PyPI** as the library source and entering the package name fails to resolve, because there is no index to resolve it from. Install it from the wheel file instead, as below — the **Python whl** source does this for you, and a manual `pip install /Volumes/.../wherobots_sedona-....whl` works the same way.
</Warning>

The wheels contain compiled components, so there is no universal `py3-none-any` build. Each filename encodes a Python version tag and a platform tag, and both must match your cluster:

```text theme={"system"}
wherobots_sedona-VERSION-PYTAG-PYTAG-PLATFORM.whl
```

| Component  | Value for Databricks                                                                                                                        |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `PYTAG`    | From the **Wheel tag** column in [Version compatibility](#version-compatibility) — `cp310` on DBR 14.3, `cp312` on 16.4 and 17.3            |
| `PLATFORM` | `manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64` on Intel or AMD workers, or the `aarch64` equivalent on Graviton workers |

Ignore the `macosx_*` and `win_*` wheels in the bundle. Those are for local development, not cluster nodes.

Stage the wheel alongside the JARs, using the same storage you chose in [Choose a storage location](#choose-a-storage-location). The examples below are for DBR 17.3 LTS on x86\_64 workers — substitute the tags for your cluster.

<Tabs>
  <Tab title="Unity Catalog volume">
    <Steps>
      <Step title="Upload the wheel">
        ```bash wrap theme={"system"}
        VOLUME=/Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/wheels
        databricks fs mkdirs dbfs:$VOLUME

        databricks fs cp \
          wherobots_sedona-VERSION-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl \
          dbfs:$VOLUME/
        ```
      </Step>

      <Step title="Install it as a cluster library">
        On the cluster page, open the **Libraries** tab and select **Install new → Python whl → Volumes**, then enter the full wheel path:

        ```text wrap theme={"system"}
        /Volumes/YOUR_CATALOG/YOUR_SCHEMA/wherobots/wheels/wherobots_sedona-VERSION-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Workspace files">
    <Steps>
      <Step title="Upload the wheel">
        In the Databricks UI, navigate to **Workspace → Shared → wherobots**, create a `wheels` folder, then select **Import** and upload the wheel file.
      </Step>

      <Step title="Install it as a cluster library">
        On the cluster page, open the **Libraries** tab and select **Install new → Python whl → Workspace**, then enter the full wheel path:

        ```text wrap theme={"system"}
        /Workspace/Shared/wherobots/wheels/wherobots_sedona-VERSION-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
        ```
      </Step>
    </Steps>

    <Warning>
      This path works only for Single user access mode clusters, the same constraint that applies to the JARs and the init script.
    </Warning>
  </Tab>
</Tabs>

Install at the **cluster** level, not with a notebook-scoped `%pip`. Spatial functions that run on executors need the client present on every node.

<Warning>
  A wheel built for the wrong Python version fails to install with `not a supported wheel on this platform`, as does the wrong architecture. If you change the cluster's Databricks Runtime later, revisit the wheel — DBR 14.3 uses Python 3.10 while 16.4 and 17.3 use 3.12.
</Warning>

<Note>
  `apache-sedona` from PyPI also works and can be installed as an ordinary PyPI library. Use the version matching your JAR's Apache Sedona compatibility, from the table in [Version compatibility](#version-compatibility). `wherobots-sedona` is preferred because it tracks the WherobotsDB JARs directly.
</Note>

### Validate the installation

Start the cluster, attach a notebook to it, and run the following cells in order.

<Steps>
  <Step title="Confirm the JARs were copied">
    ```bash theme={"system"}
    %sh
    ls -la /databricks/jars/sedona-dbr*.jar /databricks/jars/geotools-wrapper*.jar
    ```

    If this returns nothing, the init script did not run or could not read the JARs. Check the cluster's init script logs — see [Troubleshooting](#troubleshooting).
  </Step>

  <Step title="Initialize Sedona">
    ```python theme={"system"}
    from sedona.spark import *

    sedona = SedonaContext.create(spark)
    ```

    An authentication error here means the API key was not picked up. See [How Wherobots authentication works](#how-wherobots-authentication-works).
  </Step>

  <Step title="Run the validation query">
    ```python wrap theme={"system"}
    sedona.sql("""
        SELECT
            ST_AsText(ST_Point(1.0, 2.0)) AS point,
            ST_Distance(ST_Point(0.0, 0.0), ST_Point(3.0, 4.0)) AS distance,
            ST_Area(ST_GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))')) AS area
    """).show()
    ```

    ```text theme={"system"}
    +-----------+--------+----+
    |      point|distance|area|
    +-----------+--------+----+
    |POINT (1 2)|     5.0|25.0|
    +-----------+--------+----+
    ```

    <Note>
      Because `spark.sql.extensions` is set, `ST_*` functions are also available through plain `spark.sql(...)` and in SQL cells without calling `SedonaContext.create` first.
    </Note>
  </Step>

  <Step title="Confirm geometries reach Python">
    This exercises the Python client rather than the JAR alone — the returned value is a Shapely object, not text.

    ```python theme={"system"}
    spark.sql("SELECT ST_Point(1.0, 2.0) AS geom").collect()
    ```

    ```text theme={"system"}
    [Row(geom=<POINT (1 2)>)]
    ```
  </Step>

  <Step title="Confirm spatial functions run on executors">
    This requires the client to be installed on every node, not just the driver.

    ```python wrap theme={"system"}
    df = spark.sql("SELECT ST_Point(CAST(id AS DOUBLE), CAST(id AS DOUBLE)) AS geom FROM range(0, 1000)")
    df.rdd.map(lambda r: r.geom.wkt).take(2)
    ```

    ```text theme={"system"}
    ['POINT (0 0)', 'POINT (1 1)']
    ```
  </Step>
</Steps>

### Scala

WherobotsDB works the same way from Scala:

```scala theme={"system"}
import org.apache.sedona.spark.SedonaContext

val sedona = SedonaContext.create(spark)
sedona.sql("SELECT ST_AsText(ST_Point(1.0, 2.0)) AS point").show()
```

## How Wherobots authentication works

WherobotsDB validates your API key at startup and uses it for usage-based billing. Both operations call Wherobots Cloud endpoints that are part of the BYOS feature:

1. At startup, the JAR authenticates against `POST /apps/authenticate`, which returns a workload ID.
2. While the workload runs, the JAR periodically reports usage heartbeats to `POST /apps/report/{workload_id}`.

If BYOS is not enabled for your Organization, both endpoints return `403` and initialization fails. The same feature grants access to the release artifacts. See [Before you start](#before-you-start).

### Create an API key

<Steps>
  <Step title="Open the API Keys page">
    Log in to [Wherobots Cloud](https://cloud.wherobots.com) and go to **Settings → API Keys**.
  </Step>

  <Step title="Create the key">
    Select **Create new key**, name it, and choose an expiration date. The default is one year. Select **Submit**.
  </Step>

  <Step title="Copy it immediately">
    <Warning>
      The key is shown only once. Copy it before leaving the page.
    </Warning>
  </Step>
</Steps>

For details on managing and rotating keys, see the [Wherobots API Keys documentation](/get-started/wherobots-cloud/api-keys).

### Supply the key to the cluster

Databricks secrets are the recommended method, and the only one that keeps the key out of the cluster configuration.

<Steps>
  <Step title="Store the key in a secret scope">
    Using the Databricks CLI:

    ```bash wrap theme={"system"}
    databricks secrets create-scope YOUR_SCOPE

    databricks secrets put-secret YOUR_SCOPE wherobots-api-key \
      --string-value "YOUR_WHEROBOTS_API_KEY"
    ```
  </Step>

  <Step title="Reference it from the Spark config">
    ```text theme={"system"}
    spark.wherobots.api.key {{secrets/YOUR_SCOPE/wherobots-api-key}}
    ```

    Databricks resolves the reference when the cluster starts and displays `[REDACTED]` in the UI.
  </Step>
</Steps>

The key can also be supplied as the `WHEROBOTS_API_KEY` environment variable under **Advanced options → Spark → Environment variables**, which accepts the same `{{secrets/...}}` syntax.

<Warning>
  Do not paste a raw API key into either the Spark config or an environment variable. Both are readable by anyone with view access to the cluster, and both are captured in cluster event logs.
</Warning>

If authentication fails, you will see an error when calling `SedonaContext.create(spark)`. Confirm the key is correct and unexpired, that BYOS is enabled for your Organization, and that the cluster has outbound HTTPS to Wherobots Cloud.

## Best practices

**Runtime selection**

* Use an LTS runtime — 16.4 LTS or 17.3 LTS — for production.
* Both Standard and Photon engines are supported.
* Match the JAR's Scala version to the runtime's Scala version.

**Cluster configuration**

* For large datasets, raise `spark.driver.memory` to accommodate global index building.
* Raise `spark.driver.maxResultSize` — for example to `2g` or `5g` — if you hit out-of-memory errors when collecting results.

**Storage**

* Use Unity Catalog volumes for Shared clusters, and for anything you expect to share across clusters.
* Use workspace files only for single-user clusters.

## Feature differences from Wherobots Cloud

BYOS provides the WherobotsDB engine on your cluster. Features of the managed Wherobots Cloud platform are not included:

* The **Wherobots managed catalogs** — `wherobots`, `wherobots_open_data`, `wherobots_pro_data`, and the tutorial `examples_temp` catalog — are not available. Notebooks or jobs that reference them must be pointed at your own catalogs, including Unity Catalog, or read public data directly.
* Runtime conveniences that Wherobots Cloud preconfigures — the Spark checkpoint directory, visualization packages such as SedonaKepler, and pre-installed Python dependencies — must be set up on your cluster yourself.

## Troubleshooting

**`ClassNotFoundException`, `UNRESOLVED_ROUTINE`, `ST_*` functions not recognized, or `'JavaPackage' object is not callable` in PySpark**

* Confirm the JARs reached the cluster: `ls -la /databricks/jars/sedona-dbr*.jar`. If they are absent, the init script did not run or could not read the source path.
* Check the init script output. Databricks writes it to the cluster log destination under `init_scripts/`, or to **Driver logs** on the cluster page.
* Confirm the init script path and its source type — **Volumes** or **Workspace** — match where you actually stored it.
* On Shared access mode clusters, confirm the init script and JARs are in a Unity Catalog volume. Shared clusters cannot read them from the workspace file system.

**`UnsupportedClassVersionError`** — the cluster is running JDK 8. On DBR 14.3, set the Spark environment variable `JNAME=zulu17-ca-amd64`. DBR 15.0 and later use JDK 17 by default. See [Version compatibility](#version-compatibility).

**`NoSuchMethodError` at query time** — a Spark or Scala mismatch between the JAR and the runtime. DBR 14.3 and 16.4 LTS use Scala 2.12; DBR 17.3 LTS uses Scala 2.13. See [Version compatibility](#version-compatibility).

**`ModuleNotFoundError: No module named 'sedona'`** — the Python client is not installed, or was installed on the notebook rather than the cluster. Install the wheel as a **cluster** library so it reaches every node. If you are installing by hand, give pip the wheel's path — `wherobots-sedona` by name cannot resolve, since the package ships only in the release bundle and not on PyPI.

**Spatial functions work on the driver but fail inside `rdd.map` or a UDF** — the Python client is installed on the driver only. Reinstall it as a cluster library and restart the cluster.

**Authentication errors from `SedonaContext.create`** — confirm `spark.wherobots.api.key` resolves. A common cause is a secret scope or key name that does not match the `{{secrets/SCOPE/KEY}}` reference, which leaves the property set to the literal placeholder text. Also confirm the key has not expired, that BYOS is enabled for your Organization, and that the cluster has outbound HTTPS to Wherobots Cloud.

## Appendix: Supported CRS transformations

WherobotsDB performs coordinate reference system transformations through `ST_Transform`, which accepts three CRS formats for both source and target.

### Authority codes

WherobotsDB uses [spatialreference.org](https://spatialreference.org/) as its CRS database, which covers several authorities:

| Authority | Description                                      | Example                     |
| --------- | ------------------------------------------------ | --------------------------- |
| EPSG      | European Petroleum Survey Group                  | `EPSG:4326`, `EPSG:3857`    |
| ESRI      | Esri coordinate systems                          | `ESRI:102008`, `ESRI:54012` |
| IAU       | International Astronomical Union (planetary CRS) | `IAU:30100`                 |
| SR-ORG    | User-contributed definitions                     | `SR-ORG:6864`               |

```sql theme={"system"}
-- EPSG code, the most common form
SELECT ST_Transform(geometry, 'EPSG:4326', 'EPSG:3857')

-- ESRI code, North America Albers Equal Area Conic
SELECT ST_Transform(geometry, 'EPSG:4326', 'ESRI:102008')
```

Browse the available codes at [spatialreference.org](https://spatialreference.org/) or [epsg.io](https://epsg.io/).

### PROJ strings

Use PROJ.4 format for custom projections.

```sql wrap theme={"system"}
SELECT ST_Transform(geometry, '+proj=longlat +datum=WGS84', '+proj=utm +zone=32 +datum=WGS84')
```

### OGC WKT

Use OGC Well-Known Text v1 for a full CRS definition:

```sql wrap theme={"system"}
SELECT ST_Transform(
    geometry,
    'EPSG:4326',
    'PROJCS["WGS 84 / Pseudo-Mercator",
        GEOGCS["WGS 84",
            DATUM["WGS_1984",
                SPHEROID["WGS 84",6378137,298.257223563]],
            PRIMEM["Greenwich",0],
            UNIT["degree",0.0174532925199433]],
        PROJECTION["Mercator_1SP"],
        UNIT["metre",1]]'
)
```

### Behavior worth knowing

* **Coordinate order is lon/lat.** If your data is stored lat/lon, apply `ST_FlipCoordinates` first.
* **Transformations run in strict mode.** An invalid transformation raises an error rather than returning an approximation.
* **The source CRS can be inferred.** If you omit it, WherobotsDB reads the geometry's SRID, which you can set with `ST_SetSRID`:

  ```sql theme={"system"}
  SELECT ST_Transform(ST_SetSRID(geometry, 4326), 'EPSG:3857')
  ```

For the full function reference, see the [CRS transformation documentation](https://sedona.apache.org/latest/api/sql/CRS-Transformation/).

## Support

For issues or questions, contact Wherobots support.
