Metadata-Version: 2.4
Name: liveramp-cleanroom-sdk
Version: 1.0.0
Summary: Comprehensive Python SDK for LiveRamp Clean Room operations
Project-URL: Homepage, https://pypi.org/project/liveramp-cleanroom-sdk/
Project-URL: Documentation, https://pypi.org/project/liveramp-cleanroom-sdk/
Author-email: LiveRamp Clean Room Delta Team <integration@liveramp.com>
License: MIT
License-File: LICENSE
Keywords: api,cleanroom,client,flows,liveramp,questions,sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8.1
Requires-Dist: pyyaml>=6.0
Requires-Dist: requests>=2.25.0
Provides-Extra: dev
Requires-Dist: assertpy>=1.1.0; extra == 'dev'
Requires-Dist: bandit>=1.7.0; extra == 'dev'
Requires-Dist: black>=23.0.0; extra == 'dev'
Requires-Dist: coverage[toml]>=7.0.0; extra == 'dev'
Requires-Dist: factory-boy>=3.2.0; extra == 'dev'
Requires-Dist: flake8-pyproject>=1.2.0; extra == 'dev'
Requires-Dist: flake8>=6.0.0; extra == 'dev'
Requires-Dist: freezegun>=1.2.0; extra == 'dev'
Requires-Dist: httpretty>=1.1.0; extra == 'dev'
Requires-Dist: ipdb>=0.13.0; extra == 'dev'
Requires-Dist: isort>=5.12.0; extra == 'dev'
Requires-Dist: locust>=2.14.0; extra == 'dev'
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pdbpp>=0.10.0; extra == 'dev'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
Requires-Dist: pytest-click>=1.1.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest-html>=3.1.0; extra == 'dev'
Requires-Dist: pytest-json-report>=1.5.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.10.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.1.0; extra == 'dev'
Requires-Dist: pytest-xdist>=3.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: python-dotenv>=1.0.0; extra == 'dev'
Requires-Dist: requests-mock>=1.10.0; extra == 'dev'
Requires-Dist: responses>=0.23.0; extra == 'dev'
Requires-Dist: safety>=2.3.0; extra == 'dev'
Requires-Dist: sphinx-rtd-theme>=1.2.0; extra == 'dev'
Requires-Dist: sphinx>=5.0.0; extra == 'dev'
Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
Requires-Dist: types-requests>=2.28.0; extra == 'dev'
Description-Content-Type: text/markdown

# liveramp-cleanroom-sdk

Python SDK for interacting with the LiveRamp Clean Room platform. It lets you programmatically manage cleanroom questions, run analyses, and orchestrate data flows — without using the LiveRamp UI.

## Prerequisites

- Python 3.8.1+
- A service account JSON file with valid LiveRamp credentials
- Your `lr_org_id` and `cleanroom_id`

---

## Installation

```bash
pip install liveramp-cleanroom-sdk
```

---

## Verify Installation

```bash
python -c "import liveramp_cleanroom_sdk; print(liveramp_cleanroom_sdk.__version__)"

liveramp-cleanroom --help
```

---

## Quickstart

```python
from liveramp_cleanroom_sdk import LiveRampCleanroomAPI
from liveramp_cleanroom_sdk.config import (
    Config, CreateQuestionConfig, CreateQuestionSettings,
    QuestionDetails, QueryDetail, QuestionDataType,
)

with LiveRampCleanroomAPI(Config(
    service_account_file="/path/to/service_account.json",
    lr_org_id="your-lr-org-id",
    cleanroom_id="your-cleanroom-id",
)) as client:
    config = CreateQuestionConfig(
        question_details=QuestionDetails(
            title="My Question",
            description="My Question description",
            category="my-category",
            query_details=[
                QueryDetail(
                    query="SELECT @my_dataset.customer_id, @my_dataset.event_date FROM @my_dataset",
                    query_language="SQL",
                    clean_room_type="Hybrid",
                )
            ],
            data_types=[
                QuestionDataType(import_data_type="Generic", macro="my_dataset")
            ],
        ),
        settings=CreateQuestionSettings(query_validation=False),
    )

    response = client.questions.create_question(config)
    print("Created question ID:", response["questionID"])
```

---

## Authentication & Configuration

Authenticate using a service account JSON file and your LiveRamp Org ID.

### Via code

```python
from liveramp_cleanroom_sdk import LiveRampCleanroomAPI
from liveramp_cleanroom_sdk.config import Config

client = LiveRampCleanroomAPI(Config(
    service_account_file="/path/to/service_account.json",
    lr_org_id="your-lr-org-id",
    cleanroom_id="your-cleanroom-id",
))
```

### Via environment variables

```bash
export LIVERAMP_SERVICE_ACCOUNT_FILE=/path/to/service_account.json
export LIVERAMP_LR_ORG_ID=your-lr-org-id
export LIVERAMP_CLEANROOM_ID=your-cleanroom-id
```

```python
client = LiveRampCleanroomAPI(Config())
```

---

## Usage

### Context Manager (Recommended)

Using a context manager ensures HTTP connections are closed automatically when the block exits, even if an error occurs.

```python
with LiveRampCleanroomAPI(Config(...)) as client:
    # all calls here
```

---

## Questions (Org-level)

Org-level questions are question templates owned by your organization.

```python
from liveramp_cleanroom_sdk.config import (
    CreateQuestionConfig, CreateQuestionSettings,
    QuestionDetails, QueryDetail, QuestionDataType,
)

# Create a question
config = CreateQuestionConfig(
    question_details=QuestionDetails(
        title="My Question",
        description="My Question description",
        category="my-category",
        query_details=[
            QueryDetail(
                query="SELECT @my_dataset.partner_id, COUNT(*) as count FROM @my_dataset GROUP BY partner_id",
                query_language="SQL",
                clean_room_type="Hybrid",  # required: Hybrid, Snowflake, Databricks, Google, AWS, Facebook, AMC, ADH, LinkedIn, HabuConfidentialComputing
            )
        ],
        data_types=[
            QuestionDataType(import_data_type="Generic", macro="my_dataset")
        ],
    ),
    settings=CreateQuestionSettings(query_validation=False),
)
response = client.questions.create_question(config)
question_id = response["questionID"]

# Get a question
question = client.questions.get_question(question_id)

# Update a question
from liveramp_cleanroom_sdk.config import UpdateQuestionConfig
client.questions.update_question(UpdateQuestionConfig(question_id=question_id, ...))

# Delete a question
client.questions.delete_question(question_id)
```

> For the full list of available properties (dimensions, measures, parameters, data_types, flags etc.),
> generate and refer to the sample config:
> ```bash
> liveramp-cleanroom create-sample-configs
> # Files are generated in your current directory:
> # sample_configs/questions/create_question_config.yaml       — create_question
> # sample_configs/questions/update_question_config.yaml       — update_question
> ```

---

## CR Questions (Cleanroom-level)

CR Questions attach org-level questions to a specific cleanroom and assign datasets.

```python
from liveramp_cleanroom_sdk.config import QuestionDatasetAssignment, QuestionDatasetField

# Add question to cleanroom
response = client.cr_questions.add_question_to_cleanroom(question_id)
cleanroom_question_id = response["id"]

# List all cleanroom questions
questions = client.cr_questions.get_cleanroom_questions()

# Get a specific cleanroom question
question = client.cr_questions.get_cleanroom_question_by_id(cleanroom_question_id)

# Assign datasets to a cleanroom question
assignments = [
    QuestionDatasetAssignment(
        node_name="input_node",
        dataset_id="dataset-id",
        fields=[QuestionDatasetField(name="field1", question_field_name="q_field1")]
    )
]
client.cr_questions.assign_cleanroom_question_datasets(
    cleanroom_question_id=cleanroom_question_id,
    dataset_assignments=assignments,
)

# Get datasets assigned to a cleanroom question
client.cr_questions.get_cleanroom_question_datasets(cleanroom_question_id)

# Remove question from cleanroom
client.cr_questions.delete_question_from_cleanroom(cleanroom_question_id)
```

> For the full list of available properties:
> ```bash
> liveramp-cleanroom create-sample-configs
> # Files are generated in your current directory:
> # sample_configs/cr_questions/add_question_config.yaml                          — add_question_to_cleanroom
> # sample_configs/cr_questions/assign_cleanroom_question_datasets_config.yaml    — assign_cleanroom_question_datasets
> ```

---

## Question Runs

Execute a cleanroom question and retrieve results.

```python
from liveramp_cleanroom_sdk.config import QuestionRunConfig

run_config = QuestionRunConfig(
    name="my-run",
    parameters={"param1": "value1"},
)

# Create a run
run = client.cr_question_runs.create_cr_question_run(
    cleanroom_question_id=cleanroom_question_id,
    question_run_config=run_config,
)
run_id = run["id"]

# Get run status
status = client.cr_question_runs.get_cr_question_run_by_id(run_id)

# Get all runs for a question
runs = client.cr_question_runs.get_cr_question_runs(cleanroom_question_id)

# Get run results
data = client.cr_question_runs.get_cr_question_run_data(run_id)

# Create and poll until complete (blocks until done)
result = client.cr_question_runs.create_and_poll_cr_question_run(
    cleanroom_question_id=cleanroom_question_id,
    question_run_config=run_config,
)

# Poll an existing run until complete
result = client.cr_question_runs.poll_cr_question_run_until_complete(run_id)
```

> For the full list of available properties:
> ```bash
> liveramp-cleanroom create-sample-configs
> # Files are generated in your current directory:
> # sample_configs/cr_question_runs/cr_question_run_config.yaml               — create_cr_question_run / poll
> # sample_configs/cr_question_runs/multiple_cr_question_runs_config.yaml     — create multiple runs
> ```

---

## Assets

```python
# Get all cleanroom assets
assets = client.assets.get_cleanroom_assets()

# Get dataset organizations
orgs = client.assets.get_dataset_organizations()
```

---

## Flows

```python
from liveramp_cleanroom_sdk.config import FlowConfig, NodeDatasetAssignment, DatasetAssignment

# Create or update a flow
flow_config = FlowConfig(
    name="My Flow",
    flow_id="flow-id",           # omit to create new
    template_id="template-id",
)
response = client.flows.create_or_update_flow(flow_config)
flow_id = response["id"]

# Get a flow
flow = client.flows.get_flow_by_id(flow_id)

# List all flows
flows = client.flows.get_all_flows()

# Get flow run parameters
params = client.flows.get_flow_run_parameters(flow_id)

# Assign datasets to flow nodes
assignments = [
    NodeDatasetAssignment(
        node_name="input_node",
        dataset_assignments=[DatasetAssignment(dataset_id="dataset-id")]
    )
]
client.flows.assign_flow_datasets(flow_id=flow_id, dataset_assignments=assignments)

# Get flow node details
client.flows.get_flow_node_details(flow_id)
```

> For the full list of available properties:
> ```bash
> liveramp-cleanroom create-sample-configs
> # Files are generated in your current directory:
> # sample_configs/flows/create_or_update_flow_config.yaml    — create_or_update_flow
> # sample_configs/flows/assign_datasets_config.yaml          — assign_flow_datasets
> # sample_configs/flows/node_details_config.yaml             — get_flow_node_details
> ```

---

## Flow Runs

```python
from liveramp_cleanroom_sdk.config import FlowRunConfig, ReplayConfig

run_config = FlowRunConfig(
    name="my-run",
    parameters={"param1": {"value": "val1"}},
)

# Create a flow run
run = client.flow_runs.create_flow_run(flow_run_config=run_config, flow_id=flow_id)
run_id = run["id"]

# Get flow run status
status = client.flow_runs.get_flow_run_status(run_id)

# Get flow run details
run = client.flow_runs.get_flow_run_by_id(run_id)

# Poll until complete (blocks)
result = client.flow_runs.poll_flow_run_until_complete(run_id)

# Create multiple flow runs
runs = client.flow_runs.create_multiple_flow_runs(
    flow_runs=[run_config, run_config],
    flow_id=flow_id,
)

# Replay a flow run
replay_config = ReplayConfig(
    name="replay-run",
    flow_run_id=run_id,
    start_level_id="Level-1",
)
client.flow_runs.replay_flow_run(flow_run_id=run_id, replay_config=replay_config)

# Resume a paused flow run
client.flow_runs.resume_flow_run(run_id)
```

> For the full list of available properties:
> ```bash
> liveramp-cleanroom create-sample-configs
> # Files are generated in your current directory:
> # sample_configs/flow_runs/flow_run_config.yaml              — create_flow_run
> # sample_configs/flow_runs/multiple_flow_runs_config.yaml    — create_multiple_flow_runs
> # sample_configs/flow_runs/replay_config.yaml                — replay_flow_run
> # sample_configs/flow_runs/resume_config.yaml                — resume_flow_run
> # sample_configs/flow_runs/polling_config.yaml               — poll_flow_run_until_complete
> ```

---

## Environment Variables Reference

| Variable | Description |
|----------|-------------|
| `LIVERAMP_SERVICE_ACCOUNT_FILE` | Path to service account JSON file |
| `LIVERAMP_LR_ORG_ID` | LiveRamp Org ID |
| `LIVERAMP_CLEANROOM_ID` | Cleanroom ID |
| `LIVERAMP_LOG_LEVEL` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR` (default: `INFO`) |

---
