Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions .fern/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cliVersion": "5.51.2",
"cliVersion": "5.112.0",
"generatorName": "fernapi/fern-python-sdk",
"generatorVersion": "5.3.3",
"generatorConfig": {
Expand All @@ -8,6 +8,6 @@
},
"client_class_name": "Vapi"
},
"originGitCommit": "5a015aa01196915bea6110904c69d5804f457ff5",
"sdkVersion": "2.0.0"
"originGitCommit": "406e7e1ea2bdeb0ebcd01252883626f9a240ecf3",
"sdkVersion": "3.0.0"
}
16 changes: 16 additions & 0 deletions .fern/replay.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

.github/workflows/sdk-release-pr-notification.yml
README.md
src/vapi/assistants/types/update_assistant_dto_server_messages_item.py
src/vapi/types/assistant_overrides_server_messages_item.py
src/vapi/types/assistant_server_messages_item.py
src/vapi/types/create_assistant_dto_server_messages_item.py

changelog.md
.fern/replay.lock
.fern/replay.yml
.gitattributes

# Release checks and regression tests maintained in this repository
.github/workflows/ci.yml
tests/custom/test_structured_output_run.py
tests/custom/test_vapi_managed_model.py
tests/custom/test_tool_variants.py
tests/custom/test_model_deprecation_notice.py
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.fern/replay.lock linguist-generated=true
57 changes: 45 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: ci
on: [push]
on: [push, pull_request, workflow_dispatch]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand All @@ -12,7 +12,7 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v4
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v7
with:
python-version: "3.10"
- name: Bootstrap poetry
Expand All @@ -24,27 +24,51 @@ jobs:
run: poetry run mypy .
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
pydantic: [">=2,<3"]
include:
- python: "3.10"
pydantic: ">=1.10.26,<2"
- python: "3.12"
pydantic: ">=1.10.26,<2"
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v7
with:
python-version: "3.10"
- name: Bootstrap poetry
python-version: ${{ matrix.python }}
- name: Build and install wheel
env:
PYDANTIC_REQUIREMENT: ${{ matrix.pydantic }}
run: |
curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1
- name: Install dependencies
run: poetry install
python -m pip wheel --no-deps --wheel-dir dist .
python -m pip install dist/*.whl "pydantic$PYDANTIC_REQUIREMENT" "pytest>=8.2,<9" "pytest-asyncio>=1,<2" "pytest-xdist>=3.6.1,<4" "python-dateutil>=2.9,<3"
python -m pip check

- name: Test
run: poetry run pytest -rP -n auto .
run: python -m pytest -rP -n auto tests

- name: Install aiohttp extra
run: poetry install --extras aiohttp
run: python -m pip install "$(find dist -name '*.whl')[aiohttp]"

- name: Test (aiohttp)
run: poetry run pytest -rP -n auto -m aiohttp .
run: python -m pytest -rP -n auto -m aiohttp tests

- name: Verify installed package version and request headers
run: |
python - <<'PY'
import importlib.metadata
from vapi.core.client_wrapper import BaseClientWrapper

version = importlib.metadata.version("vapi_server_sdk")
headers = BaseClientWrapper(token="ci-test", base_url="https://api.vapi.ai").get_headers()
assert headers["X-Fern-SDK-Version"] == version
assert headers["User-Agent"] == f"vapi_server_sdk/{version}"
PY

publish:
needs: [compile, test]
Expand All @@ -54,14 +78,23 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v4
- name: Set up python
uses: actions/setup-python@v4
uses: actions/setup-python@v7
with:
python-version: "3.10"
- name: Bootstrap poetry
run: |
curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1
- name: Install dependencies
run: poetry install
- name: Verify tag matches package version
env:
RELEASE_TAG: ${{ github.ref_name }}
run: |
version="$(poetry version --short)"
if [ "$RELEASE_TAG" != "$version" ] && [ "$RELEASE_TAG" != "v$version" ]; then
echo "Tag $RELEASE_TAG does not match package version $version"
exit 1
fi
- name: Publish to pypi
run: |
poetry config repositories.remote https://upload.pypi.org/legacy/
Expand Down
131 changes: 62 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,138 +7,131 @@ The Vapi Python library provides convenient access to the Vapi API from Python.

## Installation

```sh
pip install vapi_server_sdk
This release supports Python 3.10 through 3.14.

```bash
python -m pip install vapi_server_sdk
```

Install the optional async transport:

```bash
python -m pip install "vapi_server_sdk[aiohttp]"
```

## Upgrade to 3.0.0

Version 3.0.0 updates the generated types to the current Vapi API definition. Review the [3.0.0 migration notes](./changelog.md) before upgrading from 1.x. Public helper imports, declared model fields, and structured-output run response types have changed.

```bash
python -m pip install --upgrade "vapi_server_sdk>=3.0.0,<4"
```

## Reference

A full reference for this library is available [here](./reference.md).
See the [Python SDK reference](./reference.md) for methods, parameters, and response types.

## Usage

Instantiate and use the client with the following:
Set the `VAPI_API_KEY` environment variable to your Vapi private API key. Create a client and list up to 10 assistants in your organization:

```python
import os

from vapi import Vapi

client = Vapi(
token="YOUR_TOKEN",
)
client.calls.create()
client = Vapi(token=os.environ["VAPI_API_KEY"])
assistants = client.assistants.list(limit=10)
for assistant in assistants:
print(assistant.id)
```

## Async Client

The SDK also exports an `async` client so that you can make non-blocking calls to our API.
Use `AsyncVapi` to await API requests:

```python
import asyncio
import os

from vapi import AsyncVapi

client = AsyncVapi(
token="YOUR_TOKEN",
)


async def main() -> None:
await client.calls.create()
client = AsyncVapi(token=os.environ["VAPI_API_KEY"])
assistants = await client.assistants.list(limit=10)
for assistant in assistants:
print(assistant.id)


asyncio.run(main())
```

## Exception Handling

When the API returns a non-success status code (4xx or 5xx response), a subclass of the following error
will be thrown.
Catch `ApiError` to inspect an unsuccessful API response:

```python
import os

from vapi import Vapi
from vapi.core.api_error import ApiError

client = Vapi(token=os.environ["VAPI_API_KEY"])
try:
client.calls.create(...)
except ApiError as e:
print(e.status_code)
print(e.body)
client.assistants.list(limit=10)
except ApiError as error:
print(error.status_code)
print(error.body)
```

## Pagination
## List Resources

Paginated requests will return a `SyncPager` or `AsyncPager`, which can be used as generators for the underlying object.

```python
from vapi import Vapi

client = Vapi(
token="YOUR_TOKEN",
)
response = client.logs.get()
for item in response:
yield item
# alternatively, you can paginate page-by-page
for page in response.iter_pages():
yield page
```
`client.assistants.list()` returns a Python list. Use its `limit` and timestamp filters to select results. Other endpoints have their own response types and pagination parameters; consult the [SDK reference](./reference.md) for the endpoint you use.

## Advanced

### Retries

The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long
as the request is deemed retriable and the number of retry attempts has not grown larger than the configured
retry limit (default: 2).

A request is deemed retriable when any of the following HTTP status codes is returned:
The SDK retries HTTP 408, 409, 429, and 5xx responses with backoff. The default maximum is two retries. Set `max_retries` for an individual request:

- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)
- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)
- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)
```python
import os

Use the `max_retries` request option to configure this behavior.
from vapi import Vapi

```python
client.calls.create(..., request_options={
"max_retries": 1
})
client = Vapi(token=os.environ["VAPI_API_KEY"])
client.assistants.list(limit=10, request_options={"max_retries": 1})
```

### Timeouts

The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level.
The default client timeout is 60 seconds. Set `timeout` when creating the client or override it with `timeout_in_seconds` for a request. When you supply a custom HTTPX client, its read timeout becomes the default unless you set `timeout` explicitly.

```python
import os

from vapi import Vapi

client = Vapi(
...,
timeout=20.0,
)


# Override timeout for a specific method
client.calls.create(..., request_options={
"timeout_in_seconds": 1
})
client = Vapi(token=os.environ["VAPI_API_KEY"], timeout=20.0)
client.assistants.list(limit=10, request_options={"timeout_in_seconds": 1})
```

### Custom Client

You can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies
and transports.
Pass an HTTPX client to configure its transport. This example sets `HTTPTransport.local_address` and closes the custom client when the block finishes:

```python
import os

import httpx
from vapi import Vapi

client = Vapi(
...,
httpx_client=httpx.Client(
proxies="http://my.test.proxy.example.com",
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
),
)
with httpx.Client(transport=httpx.HTTPTransport(local_address="0.0.0.0")) as http:
client = Vapi(token=os.environ["VAPI_API_KEY"], httpx_client=http)
assistants = client.assistants.list(limit=10)
for assistant in assistants:
print(assistant.id)
```

## Contributing
Expand Down
Loading