# Python SDK

> morevoice for Python 3.9 and later: install it, connect with an API key, call the API from sync or async code, and find every resource and helper.

`morevoice` is the Python client for the MoreVoice API. It runs on Python 3.9 and later and has a sync client, `MoreVoice`, and an async one, `AsyncMoreVoice`, with the same methods. Its core is generated from the [OpenAPI document](https://docs.morevoice.ai/api/), so every operation of the API has a typed method, named like the [Node.js SDK](https://docs.morevoice.ai/sdk/node/)'s in snake_case: `mv.calls.sendDtmf()` there is `client.calls.send_dtmf()` here. Hand-written helpers cover the rest: verifying webhooks, serving custom tools from FastAPI or Flask, event streams and pagination.

## Install

```sh
pip install morevoice
```

The package is `morevoice` on PyPI. It depends only on `httpx`, `attrs` and `python-dateutil`.

## Connect

Create an API key in **Developers › API keys** and keep it in an environment variable, `MOREVOICE_API_KEY`. Use a test-mode key (`mv_test_…`) while you build: test mode never reaches a real phone. Keys are for your server only.

```python title="main.py"

```

Every method raises an exception when the API answers with an error: the exception carries the error's `type`, `code`, `message` and the `request_id`. See [errors, rate limits and concurrency](https://docs.morevoice.ai/guides/errors-and-limits/).

## Resources

Each method takes its path parameters first, then the request body or the query. Each page lists the parameters, the body fields, the response and an example.

| Resource | Methods |
| --- | --- |
| [`client.agents`](https://docs.morevoice.ai/sdk/python/agents/) | `retrieve_status()` |
| [`client.assistants`](https://docs.morevoice.ai/sdk/python/assistants/) | `create()`, `delete()`, `duplicate()`, `list()`, `retrieve()`, `update()` |
| [`client.audio_assets`](https://docs.morevoice.ai/sdk/python/audio-assets/) | `create()`, `delete()`, `list()`, `retrieve()`, `retrieve_content()`, `update()` |
| [`client.callbacks`](https://docs.morevoice.ai/sdk/python/callbacks/) | `add_note()`, `cancel()`, `complete()`, `create()`, `list()`, `retrieve()`, `stats()`, `update()` |
| [`client.calls`](https://docs.morevoice.ai/sdk/python/calls/) | `add_participant()`, `consult()`, `create()`, `create_stream()`, `create_summary()`, `delete()`, `delete_stream()`, `download_recording()`, `hangup()`, `hold()`, `list()`, `list_copilot_events()`, `pci()`, `remove_participant()`, `retrieve()`, `retrieve_control()`, `retrieve_flow_path()`, `retrieve_pci()`, `retrieve_recording()`, `retrieve_summary()`, `retrieve_transcript()`, `send_dtmf()`, `stream()`, `transcript_stream()`, `transfer()`, `update_participant()` |
| [`client.campaigns`](https://docs.morevoice.ai/sdk/python/campaigns/) | `cancel()`, `contacts.create()`, `contacts.import_()`, `contacts.list()`, `contacts.list_attempts()`, `contacts.retrieve()`, `contacts.update()`, `create()`, `delete()`, `export()`, `list()`, `pause()`, `preflight()`, `resume()`, `retrieve()`, `start()`, `stats()`, `update()` |
| [`client.cli`](https://docs.morevoice.ai/sdk/python/cli/) | `submit_tool_result()` |
| [`client.cli_listen`](https://docs.morevoice.ai/sdk/python/cli-listen/) | `stream()` |
| [`client.client_tokens`](https://docs.morevoice.ai/sdk/python/client-tokens/) | `create()` |
| [`client.conference_rooms`](https://docs.morevoice.ai/sdk/python/conference-rooms/) | `create()`, `create_link()`, `delete()`, `invite()`, `list()`, `list_sessions()`, `moderate()`, `retrieve()`, `retrieve_ics()`, `retrieve_live()`, `update()` |
| [`client.connections`](https://docs.morevoice.ai/sdk/python/connections/) | `create()`, `delete()`, `list()`, `register()`, `retrieve()`, `update()` |
| [`client.consents`](https://docs.morevoice.ai/sdk/python/consents/) | `create()`, `delete()`, `list()` |
| [`client.copilot_profiles`](https://docs.morevoice.ai/sdk/python/copilot-profiles/) | `create()`, `delete()`, `duplicate()`, `list()`, `list_templates()`, `retrieve()`, `update()` |
| [`client.dnc`](https://docs.morevoice.ai/sdk/python/dnc/) | `check()`, `create()`, `delete()`, `list()`, `retrieve()` |
| [`client.events`](https://docs.morevoice.ai/sdk/python/events/) | `list()`, `retrieve()`, `stream()` |
| [`client.flow_templates`](https://docs.morevoice.ai/sdk/python/flow-templates/) | `list()`, `retrieve()` |
| [`client.flows`](https://docs.morevoice.ai/sdk/python/flows/) | `create()`, `delete()`, `duplicate()`, `list()`, `list_versions()`, `publish()`, `restore.version()`, `retrieve()`, `retrieve_analytics()`, `retrieve_draft()`, `retrieve_usage()`, `retrieve_version()`, `simulate()`, `update()`, `update_draft()`, `validate()` |
| [`client.imports`](https://docs.morevoice.ai/sdk/python/imports/) | `retrieve()` |
| [`client.inbound_routes`](https://docs.morevoice.ai/sdk/python/inbound-routes/) | `create()`, `delete()`, `list()`, `retrieve()`, `update()` |
| [`client.insights`](https://docs.morevoice.ai/sdk/python/insights/) | `retrieve()` |
| [`client.invitations`](https://docs.morevoice.ai/sdk/python/invitations/) | `create()`, `delete()`, `list()`, `resend()`, `retrieve()` |
| [`client.kb`](https://docs.morevoice.ai/sdk/python/kb/) | `documents_search()` |
| [`client.kb_documents`](https://docs.morevoice.ai/sdk/python/kb-documents/) | `create()`, `delete()`, `list()`, `reingest()`, `retrieve()`, `retrieve_content()` |
| [`client.openapi`](https://docs.morevoice.ai/sdk/python/openapi/) | `postman()` |
| [`client.organizations`](https://docs.morevoice.ai/sdk/python/organizations/) | `create()`, `list()`, `retrieve()`, `usage.retrieve()` |
| [`client.phone_numbers`](https://docs.morevoice.ai/sdk/python/phone-numbers/) | `create()`, `delete()`, `list()`, `retrieve()` |
| [`client.qa`](https://docs.morevoice.ai/sdk/python/qa/) | `override_scorecard_item()`, `retrieve_rubric()`, `retrieve_scorecard()`, `run.scorecard()`, `update_rubric()` |
| [`client.queues`](https://docs.morevoice.ai/sdk/python/queues/) | `create()`, `delete()`, `list()`, `retrieve()`, `retrieve_live()`, `update()` |
| [`client.reports`](https://docs.morevoice.ai/sdk/python/reports/) | `catalog()`, `create()`, `delete()`, `download_run_csv()`, `download_run_pdf()`, `list()`, `list_runs()`, `preview()`, `retrieve()`, `send()`, `update()` |
| [`client.request_logs`](https://docs.morevoice.ai/sdk/python/request-logs/) | `list()`, `retrieve()`, `stream()` |
| [`client.secrets`](https://docs.morevoice.ai/sdk/python/secrets/) | `delete()`, `list()`, `set()` |
| [`client.teams`](https://docs.morevoice.ai/sdk/python/teams/) | `create()`, `delete()`, `list()`, `retrieve()`, `update()` |
| [`client.test_helpers_events`](https://docs.morevoice.ai/sdk/python/test-helpers-events/) | `create()` |
| [`client.test_helpers_inbound_calls`](https://docs.morevoice.ai/sdk/python/test-helpers-inbound-calls/) | `create()` |
| [`client.tools`](https://docs.morevoice.ai/sdk/python/tools/) | `test()` |
| [`client.usage`](https://docs.morevoice.ai/sdk/python/usage/) | `retrieve()` |
| [`client.users`](https://docs.morevoice.ai/sdk/python/users/) | `delete()`, `list()`, `reactivate()`, `retrieve()`, `update()` |
| [`client.voices`](https://docs.morevoice.ai/sdk/python/voices/) | `list()`, `preview()` |
| [`client.web_calls`](https://docs.morevoice.ai/sdk/python/web-calls/) | `create()` |
| [`client.webhook_deliveries`](https://docs.morevoice.ai/sdk/python/webhook-deliveries/) | `list()`, `retrieve()`, `retry()` |
| [`client.webhook_endpoints`](https://docs.morevoice.ai/sdk/python/webhook-endpoints/) | `create()`, `delete()`, `list()`, `replay()`, `retrieve()`, `retrieve_public_key()`, `rotate_secret()`, `test()`, `update()` |
| [`client.whoami`](https://docs.morevoice.ai/sdk/python/whoami/) | `retrieve()` |

## Helpers

The helpers (webhook verification, tool handlers for FastAPI and Flask, event streams, pagination, `wait_until_ended`, `import_csv`) ship with the package.

## Webhooks and custom tools without the SDK

Verifying a webhook or a tool call takes a few lines of the standard library: see [verifying signatures](https://docs.morevoice.ai/webhooks/verify/#without-the-sdk) and [custom tools](https://docs.morevoice.ai/guides/custom-tools/#check-the-signature), which show the same checks in Python.
