API Referencev1

Python SDK

The official Odento Python SDK provides both synchronous and asynchronous interfaces with full type hints and Pydantic models. Requires Python 3.9 or later.

Installation

Requestbash
pip install odento-sdk

# or with poetry
poetry add odento-sdk

# or with pipenv
pipenv install odento-sdk

Initialization

Initialize the client with your API key credentials. Load keys from environment variables — never hardcode them in your source.

Requestpython
import os
from odento import Odento

client = Odento(
    key_id=os.environ["ODENTO_API_KEY_ID"],        # ok_live_...
    key_secret=os.environ["ODENTO_API_KEY_SECRET"], # os_...
)

# Optionally override the base URL (for staging)
staging_client = Odento(
    key_id=os.environ["ODENTO_API_KEY_ID"],
    key_secret=os.environ["ODENTO_API_KEY_SECRET"],
    base_url="https://staging-api.odento.app",
)

JWT Authentication

For user-facing applications, authenticate with email and password. The SDK automatically manages token storage and refresh:

Requestpython
from odento import Odento

client = Odento()

# Login — SDK stores tokens internally
client.auth.login(
    email="dr.sharma@dentalkare.in",
    password="your-secure-password",
)

# All subsequent calls use the stored access token
# The SDK automatically refreshes when the token expires

Usage Examples

List Patients

Requestpython
# List patients with pagination
result = client.patients.list(limit=10, status="active")

for patient in result.items:
    print(patient.id, patient.first_name, patient.last_name)

print(result.pagination.has_more)

# Iterate through all pages
cursor = result.pagination.next_cursor
while result.pagination.has_more:
    result = client.patients.list(limit=10, cursor=cursor)
    for patient in result.items:
        print(patient.id, patient.first_name)
    cursor = result.pagination.next_cursor

Create a Patient

Requestpython
patient = client.patients.create(
    first_name="Priya",
    last_name="Sharma",
    email="priya.sharma@example.com",
    phone="+919876543210",
    date_of_birth="1990-05-15",
    gender="female",
    address={
        "street": "12 MG Road",
        "city": "Bengaluru",
        "state": "Karnataka",
        "postal_code": "560001",
        "country": "India",
    },
)

print(patient.id)  # pat_5f8d3a2b1c9e4a7b

Create an Appointment

Requestpython
appointment = client.appointments.create(
    patient_id="pat_5f8d3a2b1c9e4a7b",
    dentist_id="usr_abc123",
    start_time="2025-01-22T10:00:00Z",
    end_time="2025-01-22T11:00:00Z",
    type="consultation",
    location_id="loc_xyz789",
    notes="Routine checkup",
)

print(appointment.id)  # apt_7a3b9c1d2e5f8a4b

Create an Invoice

Requestpython
invoice = client.billing.invoices.create(
    patient_id="pat_5f8d3a2b1c9e4a7b",
    items=[
        {"description": "Dental consultation", "quantity": 1, "unit_price": 50000},
        {"description": "Scaling and polishing", "quantity": 1, "unit_price": 150000},
    ],
    due_date="2025-02-01",
)

print(invoice.id, invoice.number, invoice.total)  # inv_... INV-2025-0042 236000

Async Usage

The SDK provides a fully async interface via AsyncOdento. Use it with asyncio for concurrent applications:

Requestpython
import asyncio
import os
from odento import AsyncOdento

async def main():
    client = AsyncOdento(
        key_id=os.environ["ODENTO_API_KEY_ID"],
        key_secret=os.environ["ODENTO_API_KEY_SECRET"],
    )

    # Concurrent requests
    patients, appointments = await asyncio.gather(
        client.patients.list(limit=10),
        client.appointments.list(status="scheduled"),
    )

    print(f"{len(patients.items)} patients, {len(appointments.items)} appointments")

asyncio.run(main())

Error Handling

The SDK raises typed exceptions. Catch them by error code to handle specific cases:

Requestpython
from odento import Odento
from odento.exceptions import OdentoError, RateLimitError, ValidationError

try:
    patient = client.patients.create(
        first_name="Priya",
        # missing required fields...
    )
except ValidationError as e:
    print(f"Validation failed: {e.message}")
    for detail in e.details:
        print(f"  {detail['field']}: {detail['message']}")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except OdentoError as e:
    print(f"API error ({e.code}): {e.message}")

Configuration Options

OptionTypeDefaultDescription
key_idstr—API key ID (ok_live_*)
key_secretstr—API key secret (os_*)
base_urlstrapi.odento.appBase URL for API requests
timeoutint30Request timeout in seconds
max_retriesint3Max retries for 5xx and 429 errors
auto_refreshboolTrueAuto-refresh JWT tokens before expiry

Was this page helpful?

Help us improve our documentation