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

# Intro

> Use the oleander API from Python: query the lake, inspect Spark clusters, and submit Spark jobs.

The [`oleanderhq-sdk`](https://pypi.org/project/oleanderhq-sdk/) package provides an async client for the oleander API. It covers lake queries, Spark job management, Spark cluster lookup, and run polling.

## Installation

```bash theme={null}
pip install oleanderhq-sdk
```

## Authentication

Create an API key in your [oleander settings](https://oleander.dev/app/settings), or run `oleander configure` if you use the CLI.

You can pass the key directly or set the `OLEANDER_API_KEY` environment variable.

```python theme={null}
from oleander_sdk import Oleander

# Option 1: pass the key directly
client = Oleander(api_key="your-api-key")

# Option 2: reads OLEANDER_API_KEY from the environment
client = Oleander()
```

## Quick start

```python theme={null}
import asyncio
from oleander_sdk import Oleander, SubmitSparkJobAndWaitOptions

async def main():
    client = Oleander()

    result = await client.query(
        "SELECT * FROM oleander.default.flowers LIMIT 10"
    )
    for row in result.results.rows:
        sepal_length, sepal_width = row[0], row[1]
        # process each row ...

    jobs = await client.list_spark_jobs()
    print(jobs.scripts)

    run = await client.submit_spark_job_and_wait(
        SubmitSparkJobAndWaitOptions(
            namespace="my-namespace",
            name="daily-etl",
            entrypoint="etl_pipeline.py",
        )
    )

    if run.state != "COMPLETE":
        raise Exception(f"Run {run.run_id} ended with state: {run.state}")

asyncio.run(main())
```

## Working with clusters

Use `cluster="oleander"` for oleander-managed Spark or pass the name of a registered cluster when submitting a job.

```python theme={null}
cluster = await client.get_spark_cluster("emr-prod")
print(cluster.type, cluster.properties)
```

## Constructor options

| Parameter  | Type  | Default                    | Description                                   |
| ---------- | ----- | -------------------------- | --------------------------------------------- |
| `api_key`  | `str` | `OLEANDER_API_KEY` env var | Your oleander API key                         |
| `base_url` | `str` | `https://oleander.dev`     | API base URL. Override for local development. |

## Errors

The SDK raises structured HTTP errors for non-2xx responses.

```python theme={null}
from oleander_sdk import OleanderHttpError, RunNotFoundError

try:
    await client.get_run("run-id")
except RunNotFoundError as error:
    print("Run is not visible yet:", error.run_id)
except OleanderHttpError as error:
    print(error.status, error.path, error.api_error or error.api_details)
```
