Metadata-Version: 2.4
Name: callintel
Version: 0.2.0
Summary: Official Python SDK for the CallIntel voice agent platform.
Project-URL: Homepage, https://callintel.io
Project-URL: Documentation, https://docs.callintel.io
Project-URL: Repository, https://github.com/rejoicehub/callintel
Project-URL: Issues, https://github.com/rejoicehub/callintel/issues
Project-URL: Changelog, https://github.com/rejoicehub/callintel/blob/main/packages/sdk-py/CHANGELOG.md
Author-email: Vedhas AI Technologies <engineering@callintel.io>
License: Apache-2.0
License-File: LICENSE
Keywords: callintel,llm,sdk,stt,telephony,tts,voice-agent,voice-ai
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Telephony
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: typing-extensions>=4.9
Provides-Extra: dev
Requires-Dist: mypy>=1.13.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.3.0; extra == 'dev'
Requires-Dist: respx>=0.21.1; extra == 'dev'
Requires-Dist: ruff>=0.7.0; extra == 'dev'
Description-Content-Type: text/markdown

# callintel — Python SDK

Official Python SDK for the [CallIntel](https://callintel.io) voice agent
platform. A thin, hand-written wrapper around `httpx` that covers the public
org-side API.

## Install

```bash
pip install callintel
# or
uv add callintel
```

Requires Python 3.10+.

## Quickstart

```python
from callintel import CallIntelClient

cli = CallIntelClient(
    api_key="ci_sk_...",           # or token="<jwt>"
    org_id="00000000-0000-...",
    # base_url="https://api.callintel.io",   # optional override
    # timeout=30.0,                          # optional
    # retries=3,                             # optional
)

agents = cli.agents.list()
print(agents)

call = cli.calls.place_phone_call(
    agent_id=agents[0]["id"],
    to_number="+15551234567",
)
print("Started call", call["call_id"])
```

Equivalent curl:

```bash
curl -X POST https://api.callintel.io/api/v1/orgs/$ORG_ID/calls/test-call \
  -H "X-API-Key: $CALLINTEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id":"...","caller_phone":"+15551234567"}'
```

The client is a context manager:

```python
with CallIntelClient(api_key="...", org_id="...") as cli:
    cli.agents.list()
```

## Authentication

Pass exactly one of:

| Option    | Header                          | When to use                                  |
| --------- | ------------------------------- | -------------------------------------------- |
| `api_key` | `X-API-Key: <key>`              | Server-side integrations, Celery, automations. |
| `token`   | `Authorization: Bearer <token>` | Notebooks, Supabase JWTs, browser-relayed sessions. |

`org_id` is required and appears in every URL path.

## Resources

| Attribute         | Methods                                                              |
| ----------------- | -------------------------------------------------------------------- |
| `agents`          | `list`, `get`, `create`, `update`, `delete`                          |
| `calls`           | `list`, `get`, `place_phone_call`, `transcript_url`, `summary`       |
| `campaigns`       | `list`, `get`, `create`, `pause`, `resume`, `cancel`, `recipients`   |
| `webhooks`        | `list`, `create`, `update`, `delete`, `test`, `deliveries`           |
| `knowledge_bases` | `list`, `get`, `create`, `add_document`, `attach_to_agent`           |

## Errors

```python
from callintel import CallIntelAPIError, CallIntelClient

cli = CallIntelClient(api_key="...", org_id="...")
try:
    cli.agents.get("missing")
except CallIntelAPIError as exc:
    print(exc.status, exc.body, exc.request_id)
```

## Retries + timeouts

Transient failures (`408`, `425`, `429`, `5xx`) are retried with exponential
backoff. Defaults: 3 retries, 30 s timeout. Override per-request via
`timeout=` / `retries=` on `client.request(...)` if you need to.

## Async client

```python
import asyncio
from callintel import AsyncCallIntelClient

async def main() -> None:
    async with AsyncCallIntelClient(api_key="...", org_id="...") as c:
        agents = await c.agents.list()
        print(agents)

asyncio.run(main())
```

Mirrors the sync `CallIntelClient` 1:1 — same `Agents`, `Calls`,
`Campaigns`, `Webhooks`, `KnowledgeBases` resources. Built on
`httpx.AsyncClient` so it works inside any asyncio loop (FastAPI,
Quart, Sanic, etc.).

## Streaming live call events

```python
from callintel import AsyncCallIntelClient, stream_call_events

async with AsyncCallIntelClient(api_key="...", org_id="...") as c:
    async for ev in stream_call_events(c, call_id="abc"):
        if ev["event"] == "transcript":
            print(ev["data"])
        if ev["event"] == "end":
            break
```

Wraps `GET /api/v1/orgs/{org}/calls/{id}/live`. Yields parsed
`{"event": str, "data": Any}` dicts. Terminal events (`end`,
`timeout`, `not_found`) close the iterator automatically.

## Verifying webhooks

```python
from fastapi import FastAPI, Request, HTTPException
from callintel import verify_webhook_signature

app = FastAPI()

@app.post("/callintel/webhook")
async def hook(request: Request) -> dict:
    body = await request.body()
    sig = request.headers.get("X-CallIntel-Signature")
    if not verify_webhook_signature(body, sig, "whsec_..."):
        raise HTTPException(status_code=401)
    # Trust the body now.
    return {"ok": True}
```

Constant-time (`hmac.compare_digest`) with 5-minute replay tolerance.
Accepts both `bytes` and `str` payloads.

## Not yet supported

- File-upload helpers for knowledge-base documents.

## License

Apache-2.0
