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

# Python SDK

> Upload calls, run metrics, and execute simulations using Python

<Note>
  The Python SDK is continually evolving, with new endpoints being added regularly. Stay tuned for updates!
</Note>

### Overview

The Roark Python SDK provides a streamlined way to interact with the Roark API. This guide covers the two most common workflows: uploading calls and running metrics, and executing simulation run plans.

### Prerequisites

Before you begin, ensure you have:

* Python 3.7 or higher - [Download Python](https://www.python.org/downloads/)
* A Roark API Key - [Generate one here](/documentation/getting-started/api-keys)

### Installation

Choose your preferred package manager:

<CodeGroup>
  ```bash pip theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
  pip install roark-analytics
  ```

  ```bash pipenv theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
  pipenv install roark-analytics
  ```

  ```bash poetry theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
  poetry add roark-analytics
  ```
</CodeGroup>

### Initialize the Client

```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
import os
from roark_analytics import Roark

client = Roark(
    bearer_token=os.environ.get("ROARK_API_BEARER_TOKEN"),
)
```

<Note>
  Set `ROARK_API_BEARER_TOKEN` in your environment, or replace with your actual API key from Roark.
</Note>

***

### Upload a Call and Run Metrics

Upload a call recording, then run metric definitions against it using a collection job.

<Steps>
  <Step title="Upload a Call">
    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    call = client.call.create(
        recording_url="https://example.com/recording.mp3",
        started_at="2024-01-15T10:00:00Z",
        interface_type="PHONE",
        call_direction="INBOUND",
        agent={
            "name": "Support Agent",
            "customId": "agent-123",
        },
        customer={
            "phoneNumberE164": "+15551234567",
        },
        # Optional: custom properties for filtering
        properties={
            "department": "sales",
            "campaignId": "summer-2024",
        },
    )
    ```
  </Step>

  <Step title="Get Metric Definitions">
    List available metric definitions to choose which ones to run:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    definitions = client.metric.list_definitions()

    # Find the metrics you want to collect
    task_completion = next(
        m for m in definitions.data if m.metric_id == "task_completion"
    )
    satisfaction = next(
        m for m in definitions.data if m.metric_id == "customer_satisfaction"
    )
    ```
  </Step>

  <Step title="Create a Metric Collection Job">
    Run the selected metrics against your uploaded call:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    job = client.metric_collection_job.create(
        call_ids=[call.data.id],
        metrics=[
            {"id": task_completion.id},
            {"id": satisfaction.id},
        ],
    )
    ```
  </Step>

  <Step title="Poll for Completion">
    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    import time

    status = "PENDING"
    while status not in ("COMPLETED", "FAILED"):
        result = client.metric_collection_job.get_by_id(job.data.id)
        status = result.data.status
        print(f"Progress: {result.data.completed_items}/{result.data.total_items}")
        if status not in ("COMPLETED", "FAILED"):
            time.sleep(2)
    ```
  </Step>

  <Step title="Fetch Results">
    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    metrics = client.call.list_metrics(call.data.id)
    print(metrics.data)
    ```
  </Step>
</Steps>

<Tip>
  If you have [metric collectors](/documentation/metrics/metric-collectors) configured, metrics are collected automatically when calls are uploaded — no collection job needed.
</Tip>

***

### Run a Simulation Run Plan

Create and execute a simulation run plan to systematically test your voice AI agent.

<Steps>
  <Step title="Create the Run Plan">
    Define scenarios, personas, agent endpoints, and metrics to include:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    plan = client.simulation_run_plan.create(
        name="Production Regression Suite",
        direction="INBOUND",
        max_simulation_duration_seconds=300,
        scenarios=[
            {"id": "scenario-uuid-1"},
            {"id": "scenario-uuid-2"},
        ],
        personas=[
            {"id": "persona-uuid-1"},
            {"id": "persona-uuid-2"},
        ],
        agent_endpoints=[
            {"id": "agent-endpoint-uuid"},
        ],
        metrics=[
            {"id": "metric-definition-uuid-1"},
            {"id": "metric-definition-uuid-2"},
        ],
        iteration_count=1,
        max_concurrent_jobs=10,
        auto_run=True,  # Start immediately after creation
    )

    # plan.data.run_plan_job contains the job if auto_run is True
    ```
  </Step>

  <Step title="Or Start an Existing Plan">
    If you already have a run plan, start a new job for it:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    job = client.simulation_run_plan_job.start("plan-uuid")
    ```
  </Step>

  <Step title="Monitor Progress">
    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    job_result = client.simulation_run_plan_job.get_by_id(
        job.data.simulation_run_plan_job_id
    )

    print(f"Status: {job_result.data.status}")
    print(f"Jobs: {len(job_result.data.simulation_jobs)}")
    ```
  </Step>

  <Step title="View Results">
    Results including metric evaluations are available in the Roark dashboard, or you can fetch metrics for individual simulation calls via the API:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    # Get metrics for a specific simulation call
    metrics = client.call.list_metrics("simulation-call-id")
    ```
  </Step>
</Steps>

***

### Additional Examples

<AccordionGroup>
  <Accordion title="Create a call with tool invocations">
    Track function calls and tool usage during the conversation:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    call = client.call.create(
        recording_url="https://example.com/recording.mp3",
        started_at="2024-01-15T10:00:00Z",
        interface_type="PHONE",
        call_direction="INBOUND",
        agent={
            "name": "Booking Agent",
            "customId": "booking-agent-1",
        },
        customer={
            "phoneNumberE164": "+15551234567",
        },
        tool_invocations=[
            {
                "name": "check_availability",
                "description": "Check available appointment slots",
                "startOffsetMs": 5000,
                "endOffsetMs": 5500,
                "parameters": {
                    "date": "2024-01-20",
                    "serviceType": "consultation",
                },
                "result": {"slots": ["9:00 AM", "2:00 PM", "4:00 PM"]},
                "agent": {"customId": "booking-agent-1"},
            },
            {
                "name": "book_appointment",
                "description": "Book an appointment for the customer",
                "startOffsetMs": 15000,
                "endOffsetMs": 15800,
                "parameters": {
                    "date": "2024-01-20",
                    "time": "2:00 PM",
                    "customerName": "John Doe",
                },
                "result": "Appointment confirmed",
                "agent": {"customId": "booking-agent-1"},
            },
        ],
    )
    ```
  </Accordion>

  <Accordion title="Create a call with an existing agent">
    Reference an agent by its Roark ID or custom ID:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    # By Roark ID
    call = client.call.create(
        recording_url="https://example.com/recording.mp3",
        started_at="2024-01-15T10:00:00Z",
        interface_type="WEB",
        call_direction="OUTBOUND",
        agent={
            "roarkId": "550e8400-e29b-41d4-a716-446655440000",
        },
        customer={
            "phoneNumberE164": "+15551234567",
        },
    )

    # By custom ID
    call2 = client.call.create(
        recording_url="https://example.com/recording.mp3",
        started_at="2024-01-15T10:00:00Z",
        interface_type="PHONE",
        call_direction="INBOUND",
        agent={
            "customId": "my-agent-id",
        },
        customer={
            "phoneNumberE164": "+15551234567",
        },
    )
    ```
  </Accordion>

  <Accordion title="Create a metric collection job for multiple calls">
    Run metrics across a batch of existing calls:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    job = client.metric_collection_job.create(
        call_ids=[
            "call-uuid-1",
            "call-uuid-2",
            "call-uuid-3",
        ],
        metrics=[
            {"id": "metric-definition-uuid-1"},
            {"id": "metric-definition-uuid-2"},
        ],
    )

    # total_items = len(call_ids) * len(metrics)
    print(f"Processing {job.data.total_items} items")
    ```
  </Accordion>

  <Accordion title="Async usage">
    For asynchronous operations, use the async client:

    ```python theme={"theme":{"light":"everforest-light","dark":"everforest-dark"}}
    import os
    import asyncio
    from roark_analytics import AsyncRoark

    client = AsyncRoark(
        bearer_token=os.environ.get("ROARK_API_BEARER_TOKEN"),
    )

    async def main():
        call = await client.call.create(
            recording_url="https://example.com/recording.mp3",
            started_at="2024-01-15T10:00:00Z",
            interface_type="PHONE",
            call_direction="INBOUND",
            agent={"name": "Support Agent"},
            customer={"phoneNumberE164": "+15551234567"},
        )

        job = await client.metric_collection_job.create(
            call_ids=[call.data.id],
            metrics=[{"id": "metric-definition-uuid"}],
        )

    asyncio.run(main())
    ```
  </Accordion>
</AccordionGroup>

### Additional Resources

<CardGroup cols={2}>
  <Card title="API Reference" icon="book-open" href="/api-reference/introduction">
    Explore our comprehensive API documentation
  </Card>

  <Card title="Example Repository" icon="github" href="https://github.com/roarkhq/sdk-roark-analytics-python/tree/main/examples">
    View example implementations and use cases
  </Card>

  <Card title="PyPI Package" icon="python" href="https://pypi.org/project/roark-analytics/">
    View package details and stats on PyPI
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/roarkhq/sdk-roark-analytics-python">
    Browse the source code and contribute
  </Card>
</CardGroup>
