Metadata-Version: 2.4
Name: vapi-agent
Version: 0.1.0
Summary: A friendly Python wrapper (sync + async) around the Vapi voice AI API.
Project-URL: Homepage, https://github.com/your-name/vapi-agent
Project-URL: Documentation, https://github.com/your-name/vapi-agent#readme
Project-URL: Issues, https://github.com/your-name/vapi-agent/issues
Author-email: Alwin Hemanth K S <alwinhemanth1@gmail.com>
License: MIT
License-File: LICENSE
Keywords: ai,assistant,sdk,telephony,vapi,voice
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.8
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Description-Content-Type: text/markdown

# vapi_agent

A small, friendly Python wrapper around the [Vapi](https://vapi.ai) voice-AI API.
It ships **both a synchronous and an asynchronous client**, covers the full REST
API through a uniform CRUD interface, and returns plain parsed JSON so you're
never fighting the library.

```python
from vapi_agent import VapiAgent

client = VapiAgent(api_key="your-private-key")
for assistant in client.assistants.list(limit=20):
    print(assistant["id"], assistant["name"])
```

## Installation

```bash
pip install vapi-agent
```

Or, from a local checkout:

```bash
pip install -e .
```

Requires Python 3.8+ and depends only on [`httpx`](https://www.python-httpx.org/).

## Authentication

Get your **private** API key from the [Vapi dashboard](https://dashboard.vapi.ai).
Pass it directly or set the `VAPI_API_KEY` environment variable:

```python
client = VapiAgent(api_key="your-private-key")
# ...or, with VAPI_API_KEY set in the environment:
client = VapiAgent()
```

> Use the **private** key server-side only. Never ship it in client-side code.

## Resources

Every resource exposes the same five methods —
`list()`, `get(id)`, `create(**fields)`, `update(id, **fields)`, `delete(id)`:

| Attribute | Vapi endpoint |
|-----------|---------------|
| `client.assistants` | `/assistant` |
| `client.calls` | `/call` |
| `client.phone_numbers` | `/phone-number` |
| `client.tools` | `/tool` |
| `client.squads` | `/squad` |
| `client.workflows` | `/workflow` |
| `client.files` | `/file` |
| `client.knowledge_bases` | `/knowledge-base` |
| `client.test_suites` | `/test-suite` |
| `client.analytics` | `/analytics` (`.query(...)`) |
| `client.logs` | `/logs` (read-only, `.list(...)`) |

Request bodies are passed as keyword arguments and forwarded as JSON, so you can
use anything the Vapi API accepts without waiting for the library to add a field.

## Examples

### Create an assistant

```python
assistant = client.assistants.create(
    name="Support Bot",
    model={
        "provider": "openai",
        "model": "gpt-4o",
        "messages": [{"role": "system", "content": "You are a helpful agent."}],
    },
    voice={"provider": "11labs", "voiceId": "burt"},
    firstMessage="Hi! How can I help you today?",
)
print(assistant["id"])
```

### Make an outbound call

```python
call = client.calls.create(
    assistantId=assistant["id"],
    phoneNumberId="your-phone-number-id",
    customer={"number": "+15551234567"},
)
```

### Paginate with the timestamp filters

Vapi's list endpoints cap results with `limit` and page by `createdAt` rather
than an offset:

```python
def all_assistants(client, page_size=100):
    cursor = None
    while True:
        page = client.assistants.list(limit=page_size, createdAtLt=cursor)
        if not page:
            break
        yield from page
        cursor = page[-1]["createdAt"]
        if len(page) < page_size:
            break
```

### Upload a file

```python
file = client.files.create(path="./knowledge.pdf")
```

### Async client

```python
import asyncio
from vapi_agent import AsyncVapiAgent

async def main():
    async with AsyncVapiAgent(api_key="your-key") as client:
        assistants = await client.assistants.list(limit=20)
        print(len(assistants))

asyncio.run(main())
```

### Analytics

```python
result = client.analytics.query([
    {
        "name": "calls_by_day",
        "table": "call",
        "timeRange": {"step": "day"},
        "operations": [{"operation": "count", "column": "id"}],
    }
])
```

## Error handling

Non-2xx responses raise a typed exception (all subclasses of `VapiAPIError`):

```python
from vapi_agent import NotFoundError, AuthenticationError, VapiAPIError

try:
    client.assistants.get("does-not-exist")
except NotFoundError:
    print("no such assistant")
except AuthenticationError:
    print("check your API key")
except VapiAPIError as e:
    print(e.status_code, e.body)
```

## Configuration

```python
client = VapiAgent(
    api_key="your-key",
    base_url="https://api.vapi.ai",   # override for self-hosted/proxy
    timeout=60.0,
    default_headers={"X-My-Header": "value"},
)
```

Both clients support context managers (`with` / `async with`) and expose
`close()` / `aclose()` for manual cleanup.

## License

MIT
