Skip to main content

Async-first Zoho Python SDK focused on DX and performance

Project description

zoho

Async-first Python SDK for Zoho, designed for developer experience and performance.

Highlights

  • Async-first transport built on httpx
  • Explicit credential-first initialization (from_credentials)
  • Strong typing with pydantic / pydantic-settings
  • Pluggable token stores (memory, SQLite, Redis)
  • Structlog-powered logging (pretty or json)
  • Multi-account connection manager (client.connections)
  • Product clients:
    • CRM (records, modules, org, users, dynamic)
    • Creator (meta, data, publish)
    • Projects V3 (portals, projects, tasks)
    • People (forms, employees, files)
    • Sheet (workbooks, worksheets, tabular)
    • WorkDrive (files, folders, search, changes, admin)
  • Ingestion iterators for connector workloads (zoho.ingestion)
  • Codegen tooling + golden tests for spec drift

Installation

uv add zoho

Optional extras:

uv add "zoho[redis]"      # Redis token store
uv add "zoho[orjson]"     # Faster JSON usage patterns

Quick Start (Explicit Credentials)

from zoho import Zoho

async def main() -> None:
    async with Zoho.from_credentials(
        client_id="your_client_id",
        client_secret="your_client_secret",
        refresh_token="your_refresh_token",
        dc="US",
        environment="production",
    ) as client:
        lead = await client.crm.records.get(module="Leads", record_id="123456789")
        print(lead.id)

Client Lifecycle: Context Manager vs Singleton

Both patterns are supported.

Use async with for one-shot scripts/jobs:

async with Zoho.from_credentials(
    client_id="...",
    client_secret="...",
    refresh_token="...",
) as client:
    org = await client.crm.org.get()

Use a long-lived singleton for web apps/workers and close on shutdown:

zoho_client = Zoho.from_credentials(
    client_id="...",
    client_secret="...",
    refresh_token="...",
)

project_rows = await zoho_client.projects.projects.list(portal_id="12345678")

# shutdown hook
await zoho_client.close()

After close(), zoho_client.closed is True and that instance must not be reused.

Multi-Account Connections

from zoho import Zoho, ZohoConnectionProfile

client = Zoho.from_credentials(
    client_id="primary_client_id",
    client_secret="primary_client_secret",
    refresh_token="primary_refresh_token",
)

client.register_connection(
    ZohoConnectionProfile(
        name="tenant_b",
        client_id="tenant_b_client_id",
        client_secret="tenant_b_client_secret",
        refresh_token="tenant_b_refresh_token",
        dc="EU",
        token_store_backend="sqlite",
    )
)

tenant_b = client.for_connection("tenant_b")
forms = await tenant_b.people.forms.list_forms()
print(forms.result_rows)

Product Usage Examples

People

records = await client.people.forms.list_records(
    form_link_name="employee",
    limit=200,
)
print(records.result_rows)

Sheet

rows = await client.sheet.tabular.fetch_worksheet_records(
    workbook_id="workbook_123",
    worksheet_name="Data",
    limit=500,
)
print(rows.records)

WorkDrive

changes = await client.workdrive.changes.list_recent(
    folder_id="folder_123",
    limit=200,
)
print(changes.resources)

CRM Dynamic Discovery

if await client.crm.dynamic.has_module("Leads"):
    leads = client.crm.dynamic.Leads
    rows = await leads.list(page=1, per_page=200)
    print(rows.data)

Ingestion Helpers (pipeshub-ai-friendly)

from zoho.ingestion import iter_people_form_documents

async for batch in iter_people_form_documents(
    client,
    form_link_name="employee",
    connection_name="tenant_b",
    page_size=200,
):
    for doc in batch.documents:
        print(doc.id, doc.title)
    print(batch.checkpoint)

Additional iterators:

  • iter_crm_module_documents(...)
  • iter_crm_documents(...)
  • iter_sheet_worksheet_documents(...)
  • iter_workdrive_recent_documents(...)

Getting OAuth Credentials

If you still need OAuth credentials, follow:

  • docs/auth-credentials.md
  • docs/scopes.md

At a high level:

  1. Create a client in Zoho API Console.
  2. Generate grant code(s) with required product scopes.
  3. Exchange grant code for access/refresh tokens.
  4. Use matching dc and accounts domain.

Auth Helper CLI

Use the helper command for token exchange and self-client payload generation:

export ZOHO_CREDENTIALS_FILE=refs/notes/zoho-live.env
uv run zoho-auth exchange-token --grant-code "<grant-code>"

uv run zoho-auth grant-code \
  --self-client-id "1000..." \
  --scopes "ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.users.ALL,ZohoCRM.org.ALL"

uv run zoho-auth scope-builder \
  --product CRM \
  --product WorkDrive \
  --access read \
  --format env

See docs/auth-cli.md for execute mode and header/cookie options.

Environment-Based Setup (Convenience)

export ZOHO_CLIENT_ID="..."
export ZOHO_CLIENT_SECRET="..."
export ZOHO_REFRESH_TOKEN="..."
export ZOHO_DC="US"
export ZOHO_ENVIRONMENT="production"
from zoho import Zoho

async with Zoho.from_env() as client:
    org = await client.crm.org.get()
    print(org)

Live Credential Validation (Admin)

Use the read-only validator before production rollout:

export ZOHO_CREDENTIALS_FILE=refs/notes/zoho-live.env
uv sync --group dev
uv run python tools/admin_validate_live.py

The script only runs read-oriented product checks and prints non-sensitive summaries (counts/status only). See docs/admin-live-validation.md for required/optional vars.

Development

uv sync --group dev
uv run ruff format .
uv run ruff check .
uv run mypy
uv run pytest
uv run mkdocs build --strict

Codegen Workflows

CRM summary

uv run python tools/codegen/main.py \
  --json-details tests/fixtures/json_details_minimal.json \
  --openapi tests/fixtures/openapi_minimal.json \
  --output /tmp/zoho_ir_summary.json

Creator summary

uv run python tools/codegen/creator_summary.py \
  --openapi tests/fixtures/creator_openapi_minimal.json \
  --output /tmp/creator_summary.json

Projects extraction

uv run python tools/codegen/projects_extract.py \
  --html tests/fixtures/projects/api_docs_sample.html \
  --output /tmp/projects_mvp.json

Curated product specs summary (People/Sheet/WorkDrive)

uv run python tools/codegen/curated_summary.py \
  --spec tools/specs/people_v1_curated.json \
  --spec tools/specs/sheet_v2_curated.json \
  --spec tools/specs/workdrive_v1_curated.json \
  --output /tmp/curated_summary.json

Repository Docs

  • Product docs: docs/
  • API research notes: refs/apis/
  • Design specs: refs/docs/specs/
  • Contributor guide: AGENTS.md

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zoho-0.1.1.tar.gz (44.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zoho-0.1.1-py3-none-any.whl (65.8 kB view details)

Uploaded Python 3

File details

Details for the file zoho-0.1.1.tar.gz.

File metadata

  • Download URL: zoho-0.1.1.tar.gz
  • Upload date:
  • Size: 44.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for zoho-0.1.1.tar.gz
Algorithm Hash digest
SHA256 34039cc1a9adb12fde6a6611fc0e104658c936ad5d08985d19030656b0684d2e
MD5 c0af64352842a5116d0793b136270a71
BLAKE2b-256 b2071114ba79fb4bdde28b36658a3b6d67d472eaa717bfbd7a2ebca013902b3d

See more details on using hashes here.

File details

Details for the file zoho-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: zoho-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 65.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.4 {"installer":{"name":"uv","version":"0.10.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for zoho-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dcb79e77c654f96ad3ae7b05a50dfbfcb56d63c9685ff8f00dd92440511d4f0c
MD5 93b9561d3fe4c98c4bafb5d9599f015c
BLAKE2b-256 94e7de3f3d1ff25e1691685d8fb1687787625a13298b7f2040ebc293aeb6b765

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page