> This page is for version V1 (default).
> For other versions, use one of these documentation indexes:
> - V1 (default): https://docs.ottimate.com/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ottimate.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ottimate.com/_mcp/server.

# Setup

Install the Ottimate Python SDK, exchange your credentials for an access token, and create an authenticated client.

## Prerequisites

* Python 3.8 or later
* An Ottimate API key, OAuth client ID, and client secret. See [Authentication](/auth) for how to obtain them.

## Install the package

The SDK is published to PyPI as `ottimate-sdk`. Install it into a virtual environment:

```bash
python3 -m venv venv
source venv/bin/activate
pip install ottimate-sdk==0.1.7
```

> **Note**
>
> The distribution is named `ottimate-sdk`, but the import name is `ottimate`:
>
> ```python
> from ottimate import Ottimate
> ```

## Configure your credentials

Keep credentials out of source control. Create a `.env` file alongside your script:

```
OTTIMATE_API_KEY="your_api_key"
OTTIMATE_CLIENT_ID="your_client_id"
OTTIMATE_CLIENT_SECRET="your_client_secret"
OTTIMATE_ACCOUNT_ID="racc_..."
OTTIMATE_COMPANY_ID="your_company_id"
OTTIMATE_LOCATION_ID="your_location_id"
```

Load them with any loader you prefer. The examples below use [`python-dotenv`](https://pypi.org/project/python-dotenv/), which you can add with `pip install python-dotenv`:

```python
import os
from dotenv import load_dotenv

load_dotenv()

api_key = os.environ["OTTIMATE_API_KEY"]
client_id = os.environ["OTTIMATE_CLIENT_ID"]
client_secret = os.environ["OTTIMATE_CLIENT_SECRET"]

# Account IDs are strings prefixed with `racc_`; company and location IDs are integers
ottimate_account_id = os.environ["OTTIMATE_ACCOUNT_ID"]
ottimate_company_id = int(os.environ["OTTIMATE_COMPANY_ID"])
ottimate_location_id = int(os.environ["OTTIMATE_LOCATION_ID"])
```

These variable names are the ones used by the rest of the pages in this section.

## Choose an environment

Select the target environment with the `OttimateEnvironment` enum rather than hardcoding a URL. Both values already include the required `/v1` path segment.

| Value                            | Base URL                              |
| -------------------------------- | ------------------------------------- |
| `OttimateEnvironment.SANDBOX`    | `https://sandbox-api.ottimate.com/v1` |
| `OttimateEnvironment.PRODUCTION` | `https://api.ottimate.com/v1`         |

`PRODUCTION` is the default. Start against `SANDBOX` while you build — see [Sandbox Environment](/sandbox).

## Authenticate and create the client

Authentication is a two-step exchange. First create a short-lived client that carries only your API key and call the OAuth endpoint. Then create the client you will actually use, passing the returned access token as a bearer token.

```python
from ottimate import Ottimate, OttimateEnvironment

ENVIRONMENT = OttimateEnvironment.SANDBOX

# 1. Exchange client credentials for an access token
auth_client = Ottimate(environment=ENVIRONMENT, api_key=api_key)

token_response = auth_client.oauth.post_oauth_token(
    client_id=client_id,
    client_secret=client_secret,
    scope="accounts.can_access_dashboard",
)
access_token = token_response.access_token

# 2. Create the authenticated client
client = Ottimate(
    environment=ENVIRONMENT,
    api_key=api_key,
    api_version="1.0.0",
    headers={"Authorization": f"Bearer {access_token}"},
)
```

The token response also exposes `token_type`, `expires_in`, and `scope`. Tokens expire, so cache the token and repeat step 1 when `expires_in` elapses or a request returns `401`. See [Authentication](/auth) for details.

## Verify the client works

Fetch the companies on your account as a smoke test:

```python
companies = client.accounts.get_accounts_id_companies(id=ottimate_account_id)
print(companies)
```

The `client` object created here is the one used by every other page in this section.

## Optional settings

| Parameter      | Purpose                                                                             |
| -------------- | ----------------------------------------------------------------------------------- |
| `base_url`     | Override the environment with an explicit URL. Takes precedence over `environment`. |
| `api_version`  | Pin the API version header. Defaults to the latest supported version.               |
| `timeout`      | Per-request timeout in seconds. Defaults to 60.                                     |
| `headers`      | Additional headers sent with every request.                                         |
| `httpx_client` | Supply your own configured `httpx.Client`.                                          |

## Async usage

For asyncio applications, import `AsyncOttimate` instead. It takes the same arguments and exposes the same methods as coroutines:

```python
from ottimate import AsyncOttimate, OttimateEnvironment

client = AsyncOttimate(
    environment=OttimateEnvironment.SANDBOX,
    api_key=api_key,
    headers={"Authorization": f"Bearer {access_token}"},
)

companies = await client.accounts.get_accounts_id_companies(id=ottimate_account_id)
```