{"id":16961871,"url":"https://github.com/vonage/vonage-python-sdk","last_synced_at":"2025-05-14T16:15:15.446Z","repository":{"id":31302233,"uuid":"34864460","full_name":"Vonage/vonage-python-sdk","owner":"Vonage","description":"Vonage Server SDK for Python. API support for Voice, SMS, WhatsApp, Verify (2FA), Video Meetings and more.","archived":false,"fork":false,"pushed_at":"2025-05-09T15:21:19.000Z","size":1198,"stargazers_count":201,"open_issues_count":1,"forks_count":117,"subscribers_count":23,"default_branch":"main","last_synced_at":"2025-05-09T15:40:02.346Z","etag":null,"topics":["meetings","messaging","messenger","nexmo","phone","python","sdk","server-sdk","silent-authentication","sms","text-message","two-factor-authentication","verification","verification-code","video","voice","vonage","whatsapp"],"latest_commit_sha":null,"homepage":"https://developer.vonage.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Vonage.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-04-30T16:22:31.000Z","updated_at":"2025-05-09T15:18:36.000Z","dependencies_parsed_at":"2023-02-16T12:40:13.777Z","dependency_job_id":"a764e682-d8d1-4fc9-a384-9734342b0767","html_url":"https://github.com/Vonage/vonage-python-sdk","commit_stats":{"total_commits":458,"total_committers":52,"mean_commits":8.807692307692308,"dds":0.6091703056768558,"last_synced_commit":"e853222c1d8d39ca25dab96b538ec9c5a2f1ce3c"},"previous_names":[],"tags_count":83,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vonage%2Fvonage-python-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vonage%2Fvonage-python-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vonage%2Fvonage-python-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Vonage%2Fvonage-python-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Vonage","download_url":"https://codeload.github.com/Vonage/vonage-python-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254179905,"owners_count":22027884,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["meetings","messaging","messenger","nexmo","phone","python","sdk","server-sdk","silent-authentication","sms","text-message","two-factor-authentication","verification","verification-code","video","voice","vonage","whatsapp"],"created_at":"2024-10-13T23:04:29.308Z","updated_at":"2025-05-14T16:15:15.407Z","avatar_url":"https://github.com/Vonage.png","language":"Python","readme":"# Vonage Server SDK for Python\n\n\u003cimg src=\"https://developer.nexmo.com/images/logos/vbc-logo.svg\" height=\"48px\" alt=\"Vonage\" /\u003e\n\n[![PyPI version](https://badge.fury.io/py/vonage.svg)](https://badge.fury.io/py/vonage)\n[![Build Status](https://github.com/Vonage/vonage-python-sdk/workflows/Build/badge.svg)](https://github.com/Vonage/vonage-python-sdk/actions)\n[![Python versions supported](https://img.shields.io/pypi/pyversions/vonage.svg)](https://pypi.python.org/pypi/vonage)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n![Total lines](https://sloc.xyz/github/vonage/vonage-python-sdk)\n\nThis is the Python server SDK to help you use Vonage APIs in your Python application. To use it you'll need a Vonage account. [Sign up for free on the Vonage site](https://ui.idp.vonage.com/ui/auth/registration).\n\n### Contents:\n\n- [Installation](#installation)\n- [Migration Guides](#migration-guides)\n- [Calling Vonage APIs](#calling-vonage-apis)\n- [Usage](#usage)\n- [Account API](#account-api)\n- [Application API](#application-api)\n- [HTTP Client](#http-client)\n- [JWT Client](#jwt-client)\n- [Messages API](#messages-api)\n- [Network Number Verification API](#network-number-verification-api)\n- [Network Sim Swap API](#network-sim-swap-api)\n- [Number Insight API](#number-insight-api)\n- [Numbers API](#numbers-api)\n- [SMS API](#sms-api)\n- [Subaccounts API](#subaccounts-api)\n- [Users API](#users-api)\n- [Verify API](#verify-api)\n- [Verify API (Legacy)](#verify-api-legacy)\n- [Video API](#video-api)\n- [Voice API](#voice-api)\n- [Vonage Utils Package](#vonage-utils-package)\n- [Frequently Asked Questions](#frequently-asked-questions)\n- [Contributing](#contributing)\n- [License](#license)\n- [Additional Resources](#additional-resources)\n\n## Installation\n\nIt's recommended to create a new virtual environment to install the SDK. You can do this with\n\n```bash\n# Create the virtual environment\npython3 -m venv venv\n\n# Activate the virtual environment in Mac/Linux\n. ./venv/bin/activate\n\n# Or on Windows Command Prompt\nvenv\\Scripts\\activate\n```\n\nTo install the Python SDK package using pip:\n\n```bash\npip install vonage\n```\n\nTo upgrade your installed client library using pip:\n\n```bash\npip install vonage --upgrade\n```\n\nAlternatively, you can clone the repository via the command line, or by opening it on GitHub desktop.\n\n## Migration Guides\n\n### V3 to V4\n\nThis version of the Vonage Python SDK (4.x+) works very differently to the previous SDK. See [the v3 -\u003e v4 migration guide](V3_TO_V4_SDK_MIGRATION_GUIDE.md) for help migrating your application code using v3 of the SDK to the new structure.\n\n### OpenTok to Vonage Video API\n\nThis SDK includes support for the [Vonage Video API](https://developer.vonage.com/en/video/overview). If you have an application that uses OpenTok for video and want to migrate (which is highly recommended!) then [A migration guide is available here](video/OPENTOK_TO_VONAGE_MIGRATION.md) which will help you to migrate your applications to use Vonage Video.\n\n## Calling Vonage APIs\n\nThe Vonage Python SDK is a monorepo, with separate packages for each API. When you install the Python SDK, you'll see there's a top-level package, `vonage`, and then specialised packages for every API class.\n\nMost methods to call Vonage APIs are accessed through the top-level `vonage` package. Many require specific custom data models accessed though the specific Vonage package corresponding to the API you're trying to use.\n\nFor example, to send an SMS, you will access the SMS method from `vonage` and the `SmsMessage` object from the `vonage-sms` package. This looks something like this:\n\n```python\nfrom vonage_sms import SmsMessage, SmsResponse\n\nmessage = SmsMessage(to='1234567890', from_='Acme Inc.', text='Hello, World!')\nresponse: SmsResponse = vonage_client.sms.send(message) # vonage_client is an instance of `vonage.Vonage`\n\nprint(response.model_dump(exclude_unset=True))\n```\n\n## Usage\n\nMany of the use cases require you to buy a Vonage Number, which you can [do in the Vonage Developer Dashboard](https://dashboard.nexmo.com/).\n\n```python\nfrom vonage import Vonage, Auth, HttpClientOptions\n\n# Create an Auth instance\nauth = Auth(api_key='your_api_key', api_secret='your_api_secret')\n\n# Create HttpClientOptions instance\n# (not required unless you want to change options from the defaults)\noptions = HttpClientOptions(api_host='api.nexmo.com', timeout=30)\n\n# Create a Vonage instance\nvonage = Vonage(auth=auth, http_client_options=options)\n```\n\nThe Vonage class provides access to various Vonage APIs through its properties. For example, to use methods to call the SMS API:\n\n```python\nfrom vonage_sms import SmsMessage\n\nmessage = SmsMessage(to='1234567890', from_='Vonage', text='Hello World')\nresponse = client.sms.send(message)\nprint(response.model_dump_json(exclude_unset=True))\n```\n\nYou can also access the underlying `HttpClient` instance through the `http_client` property:\n\n```python\nuser_agent = vonage.http_client.user_agent\n```\n\n### Convert a Pydantic Model to Dict or Json\n\nMost responses to API calls in the SDK are Pydantic models. To convert a Pydantic model to a dict, use `model.model_dump`. To convert to a JSON string, use `model.model_dump_json`\n\n```python\nresponse = vonage.api_package.api_call(...)\n\nresponse_dict = response.model_dump()\nresponse_json = response.model_dump_json()\n```\n\n## Account API\n\n### Get Account Balance\n\n```python\nbalance = vonage_client.account.get_balance()\nprint(balance)\n```\n\n### Top-Up Account\n\n```python\nresponse = vonage_client.account.top_up(trx='1234567890')\nprint(response)\n```\n\n### Update the Default SMS Webhook\n\nThis will return a Pydantic object (`SettingsResponse`) containing multiple settings for your account.\n\n```python\nsettings: SettingsResponse = vonage_client.account.update_default_sms_webhook(\n    mo_callback_url='https://example.com/inbound_sms_webhook',\n    dr_callback_url='https://example.com/delivery_receipt_webhook',\n)\n\nprint(settings)\n```\n\n### Get Service Pricing for a Specific Country\n\n```python\nfrom vonage_account import GetCountryPricingRequest\n\nresponse = vonage_client.account.get_country_pricing(\n    GetCountryPricingRequest(type='sms', country_code='US')\n)\nprint(response)\n```\n\n### Get Service Pricing for All Countries\n\n```python\nresponse = vonage_client.account.get_all_countries_pricing(service_type='sms')\nprint(response)\n```\n\n### Get Service Pricing by Dialing Prefix\n\n```python\nfrom vonage_account import GetPrefixPricingRequest\n\nresponse = client.account.get_prefix_pricing(\n    GetPrefixPricingRequest(prefix='44', type='sms')\n)\nprint(response)\n```\n\n### List Secrets Associated with the Account\n\n```python\nresponse = vonage_client.account.list_secrets()\nprint(response)\n```\n\n### Create a New Account Secret\n\n```python\nsecret = vonage_client.account.create_secret('Mytestsecret12345')\nprint(secret)\n```\n\n### Get Information About One Secret\n\n```python\nsecret = vonage_client.account.get_secret(MY_SECRET_ID)\nprint(secret)\n```\n\n### Revoke a Secret\n\nNote: it isn't possible to revoke all account secrets, there must always be one valid secret. Attempting to do so will give a 403 error.\n\n```python\nclient.account.revoke_secret(MY_SECRET_ID)\n```\n\n## Application API\n\n\n### List Applications\n\nWith no custom options specified, this method will get the first 100 applications. It returns a tuple consisting of a list of `ApplicationData` objects and an int showing the page number of the next page of results.\n\n```python\nfrom vonage_application import ListApplicationsFilter, ApplicationData\n\napplications, next_page = vonage_client.application.list_applications()\n\n# With options\noptions = ListApplicationsFilter(page_size=3, page=2)\napplications, next_page = vonage_client.application.list_applications(options)\n```\n\n### Create a New Application\n\n```python\nfrom vonage_application import ApplicationConfig\n\napp_data = vonage_client.application.create_application()\n\n# Create with custom options (can also be done with a dict)\nfrom vonage_application import ApplicationConfig, Keys, Voice, VoiceWebhooks\nvoice = Voice(\n    webhooks=VoiceWebhooks(\n        event_url=VoiceUrl(\n            address='https://example.com/event',\n            http_method='POST',\n            connect_timeout=500,\n            socket_timeout=3000,\n        ),\n    ),\n    signed_callbacks=True,\n)\ncapabilities = Capabilities(voice=voice)\nkeys = Keys(public_key='MY_PUBLIC_KEY')\nconfig = ApplicationConfig(\n    name='My Customised Application',\n    capabilities=capabilities,\n    keys=keys,\n)\napp_data = vonage_client.application.create_application(config)\n```\n\n### Get an Application\n\n```python\napp_data = client.application.get_application('MY_APP_ID')\napp_data_as_dict = app.model_dump(exclude_none=True)\n```\n\n### Update an Application\n\nTo update an application, pass config for the updated field(s) in an ApplicationConfig object\n\n```python\nfrom vonage_application import ApplicationConfig, Keys, Voice, VoiceWebhooks\n\nconfig = ApplicationConfig(name='My Updated Application')\napp_data = vonage_client.application.update_application('MY_APP_ID', config)\n```\n\n### Delete an Application\n\n```python\nvonage_client.applications.delete_application('MY_APP_ID')\n```\n\n## HTTP Client\n\n\n```python\nfrom vonage_http_client import HttpClient, HttpClientOptions\nfrom vonage_http_client.auth import Auth\n\n# Create an Auth instance\nauth = Auth(api_key='your_api_key', api_secret='your_api_secret')\n\n# Create HttpClientOptions instance\noptions = HttpClientOptions(api_host='api.nexmo.com', timeout=30)\n\n# Create a HttpClient instance\nclient = HttpClient(auth=auth, http_client_options=options)\n\n# Make a GET request\nresponse = client.get(host='api.nexmo.com', request_path='/v1/messages')\n\n# Make a POST request\nresponse = client.post(host='api.nexmo.com', request_path='/v1/messages', params={'key': 'value'})\n```\n\n### Get the Last Request and Last Response from the HTTP Client\n\nThe `HttpClient` class exposes two properties, `last_request` and `last_response` that cache the last sent request and response.\n\n```python\n# Get last request, has type requests.PreparedRequest\nrequest = client.last_request\n\n# Get last response, has type requests.Response\nresponse = client.last_response\n```\n\n### Appending to the User-Agent Header\n\nThe `HttpClient` class also supports appending additional information to the User-Agent header via the append_to_user_agent method:\n\n```python\nclient.append_to_user_agent('additional_info')\n```\n\n### Changing the Authentication Method Used\n\nThe `HttpClient` class automatically handles JWT and basic authentication based on the Auth instance provided. It uses JWT authentication by default, but you can specify the authentication type when making a request:\n\n```python\n# Use basic authentication for this request\nresponse = client.get(host='api.nexmo.com', request_path='/v1/messages', auth_type='basic')\n```\n\n### Catching errors\n\nError objects are exposed in the package scope, so you can catch errors like this:\n\n```python\nfrom vonage_http_client import HttpRequestError\n\ntry:\n    client.post(...)\nexcept HttpRequestError:\n    ...\n```\n\n## JWT Client\n\nThis JWT Generator can be used implicitly, just by using the [Vonage Python SDK](https://github.com/Vonage/vonage-python-sdk) to make JWT-authenticated API calls.\n\nIt can also be used as a standalone JWT generator for use with Vonage APIs, like so:\n\n### Import the `JwtClient` object\n\n```python\nfrom vonage_jwt import JwtClient\n```\n\n### Create a `JwtClient` object\n\n```python\njwt_client = JwtClient(application_id, private_key)\n```\n\n### Generate a JWT using the provided application id and private key\n\n```python\njwt_client.generate_application_jwt()\n```\n\nOptional JWT claims can be provided in a python dictionary:\n\n```python\nclaims = {'jti': 'asdfzxcv1234', 'nbf': now + 100}\njwt_client.generate_application_jwt(claims)\n```\n\n## Verifying a JWT signature\n\nYou can use the `verify_jwt.verify_signature` method to verify a JWT signature is valid.\n\n```python\nfrom vonage_jwt import verify_signature\n\nverify_signature(TOKEN, SIGNATURE_SECRET) # Returns a boolean\n```\n\n## Messages API\n\n### How to Construct a Message\n\nIn order to send a message, you must construct a message object of the correct type.\n\n```python\nfrom vonage_messages import Sms\n\nmessage = Sms(\n    from_='Vonage APIs',\n    to='1234567890',\n    text='This is a test message sent from the Vonage Python SDK',\n)\n```\n\nThis message can now be sent with\n\n```python\nvonage_client.messages.send(message)\n```\n\nAll possible message types from every message channel have their own message model. They are named following this rule: {Channel}{MessageType}, e.g. `Sms`, `MmsImage`, `RcsFile`, `MessengerAudio`, `WhatsappSticker`, `ViberVideo`, etc.\n\nThe different message models are listed at the bottom of the page.\n\nSome message types have submodels with additional fields. In this case, import the submodels as well and use them to construct the overall options.\n\ne.g.\n\n```python\nfrom vonage_messages import MessengerImage, MessengerOptions, MessengerResource\n\nmessenger = MessengerImage(\n    to='1234567890',\n    from_='1234567890',\n    image=MessengerResource(url='https://example.com/image.jpg'),\n    messenger=MessengerOptions(category='message_tag', tag='invalid_tag'),\n)\n```\n\n### Send a message\n\nTo send a message, access the `Messages.send` method via the main Vonage object, passing in an instance of a subclass of `BaseMessage` like this:\n\n```python\nfrom vonage import Auth, Vonage\nfrom vonage_messages import Sms\n\nvonage_client = Vonage(Auth(application_id='my-application-id', private_key='my-private-key'))\n\nmessage = Sms(\n    from_='Vonage APIs',\n    to='1234567890',\n    text='This is a test message sent from the Vonage Python SDK',\n)\n\nvonage_client.messages.send(message)\n```\n\n### Mark a WhatsApp Message as Read\n\nNote: to use this method, update the `api_host` attribute of the `vonage_http_client.HttpClientOptions` object to the API endpoint corresponding to the region where the WhatsApp number is hosted.\n\nFor example, to use the EU API endpoint, set the `api_host` attribute to 'api-eu.vonage.com'.\n\n```python\nfrom vonage import Vonage, Auth, HttpClientOptions\n\nauth = Auth(application_id='MY-APP-ID', private_key='MY-PRIVATE-KEY')\noptions = HttpClientOptions(api_host='api-eu.vonage.com')\n\nvonage_client = Vonage(auth, options)\nvonage_client.messages.mark_whatsapp_message_read('MESSAGE_UUID')\n```\n\n### Revoke an RCS Message\n\nNote: as above, to use this method you need to update the `api_host` attribute of the `vonage_http_client.HttpClientOptions` object to the API endpoint corresponding to the region where the WhatsApp number is hosted.\n\nFor example, to use the EU API endpoint, set the `api_host` attribute to 'api-eu.vonage.com'.\n\n```python\nfrom vonage import Vonage, Auth, HttpClientOptions\n\nauth = Auth(application_id='MY-APP-ID', private_key='MY-PRIVATE-KEY')\noptions = HttpClientOptions(api_host='api-eu.vonage.com')\n\nvonage_client = Vonage(auth, options)\nvonage_client.messages.revoke_rcs_message('MESSAGE_UUID')\n```\n\n## Message Models\n\nTo send a message, instantiate a message model of the correct type as described above. This is a list of message models that can be used:\n\n```\nSms\nMmsImage, MmsVcard, MmsAudio, MmsVideo\nRcsText, RcsImage, RcsVideo, RcsFile, RcsCustom\nWhatsappText, WhatsappImage, WhatsappAudio, WhatsappVideo, WhatsappFile, WhatsappTemplate, WhatsappSticker, WhatsappCustom\nMessengerText, MessengerImage, MessengerAudio, MessengerVideo, MessengerFile\nViberText, ViberImage, ViberVideo, ViberFile\n```\n\n## Network Number Verification API\n\nThe Vonage Number Verification API uses Oauth2 authentication, which this SDK will also help you to do. Verifying a number has 3 stages:\n\n1. Get an OIDC URL for use in your front-end application\n2. Use this URL in your own application to get an authorization code\n3. Make a Number Verification Request using this code to verify the number\n\nThis package contains methods to help with Steps 1 and 3.\n\n### Get an OIDC URL\n\n```python\nfrom vonage_network_number_verification import CreateOidcUrl\n\nurl_options = CreateOidcUrl(\n    redirect_uri='https://example.com/redirect',\n    state='c9896ee6-4ff8-464c-b393-d56d6e638f88',\n    login_hint='+990123456',\n)\n\nurl = number_verification.get_oidc_url(url_options)\nprint(url)\n```\n\nGet your user's device to follow this URL and a code to use for number verification will be returned in the final redirect query parameters. Note: your user must be connected to their mobile network.\n\n### Make a Number Verification Request\n\n```python\nfrom vonage_network_number_verification import NumberVerificationRequest\n\nresponse = number_verification.verify(\n    NumberVerificationRequest(\n        code='code',\n        redirect_uri='https://example.com/redirect',\n        phone_number='+990123456',\n    )\n)\nprint(response.device_phone_number_verified)\n```\n\n## Network Sim Swap API\n\n### Check if a SIM Has Been Swapped\n\n```python\nfrom vonage_network_sim_swap import SwapStatus\nswap_status: SwapStatus = vonage_client.sim_swap.check(phone_number='MY_NUMBER')\nprint(swap_status.swapped)\n```\n\n### Get the Date of the Last SIM Swap\n\n```python\nfrom vonage_network_sim_swap import LastSwapDate\nswap_date: LastSwapDate = vonage_client.sim_swap.get_last_swap_date\nprint(swap_date.last_swap_date)\n```\n\n## Number Insight API\n\n### Make a Basic Number Insight Request\n\n```python\nfrom vonage_number_insight import BasicInsightRequest\n\nresponse = vonage_client.number_insight.basic_number_insight(\n    BasicInsightRequest(number='12345678900')\n)\n\nprint(response.model_dump(exclude_none=True))\n```\n\n### Make a Standard Number Insight Request\n\n```python\nfrom vonage_number_insight import StandardInsightRequest\n\nvonage_client.number_insight.standard_number_insight(\n    StandardInsightRequest(number='12345678900')\n)\n\n# Optionally, you can get caller name information (additional charge) by setting the `cnam` parameter = True\nvonage_client.number_insight.standard_number_insight(\n    StandardInsightRequest(number='12345678900', cnam=True)\n)\n```\n\n### Make an Asynchronous Advanced Number Insight Request\n\nWhen making an asynchronous advanced number insight request, the API will return basic information about the request to you immediately and send the full data to the webhook callback URL you specify.\n\n```python\nfrom vonage_number_insight import AdvancedAsyncInsightRequest\n\nvonage_client.number_insight.advanced_async_number_insight(\n    AdvancedAsyncInsightRequest(callback='https://example.com', number='12345678900')\n)\n```\n\n### Make a Synchronous Advanced Number Insight Request\n\n```python\nfrom vonage_number_insight import AdvancedSyncInsightRequest\n\nvonage_client.number_insight.advanced_sync_number_insight(\n    AdvancedSyncInsightRequest(number='12345678900')\n)\n```\n\n## Numbers API\n\n### List Numbers You Own\n\n```python\nnumbers, count, next_page = vonage_client.numbers.list_owned_numbers()\nprint(numbers)\nprint(count)\nprint(next_page)\n\n# With filtering\nfrom vonage_numbers import ListOwnedNumbersFilter\nnumbers, count, next_page = vonage_client.numbers.list_owned_numbers(\n    ListOwnedNumbersFilter(country='GB', size=3, index=2)\n)\n\nnumbers, count, next_page_index = vonage_client.numbers.list_owned_numbers()\nprint(numbers)\nprint(count)\nprint(next_page_index)\n```\n\n### Search for Available Numbers\n\n```python\nfrom vonage_numbers import SearchAvailableNumbersFilter\n\nnumbers, count, next_page_index = vonage_client.numbers.search_available_numbers(\n    SearchAvailableNumbersFilter(\n        country='GB', size=10, pattern='44701', search_pattern=1\n    )\n)\nprint(numbers)\nprint(count)\nprint(next_page_index)\n```\n\n### Buy a Number\n\n```python\nfrom vonage_numbers import NumberParams\n\nstatus = vonage_client.numbers.buy_number(NumberParams(country='GB', msisdn='447007000000'))\nprint(status)\n```\n\n### Cancel a number\n\n```python\nfrom vonage_numbers import NumberParams\n\nstatus = vonage_client.numbers.cancel_number(NumberParams(country='GB', msisdn='447007000000'))\nprint(status)\n```\n\n### Update a Number\n\n```python\nfrom vonage_numbers import UpdateNumberParams\n\nstatus = vonage_client.numbers.update_number(\n    UpdateNumberParams(\n        country='GB',\n        msisdn='447007000000',\n        mo_http_url='https://example.com',\n        mo_smpp_sytem_type='inbound',\n        voice_callback_type='tel',\n        voice_callback_value='447008000000',\n        voice_status_callback='https://example.com',\n    )\n)\n\nprint(status)\n```\n\n## SMS API\n\n### Send an SMS\n\nCreate an `SmsMessage` object, then pass into the `Sms.send` method.\n\n```python\nfrom vonage_sms import SmsMessage, SmsResponse\n\nmessage = SmsMessage(to='1234567890', from_='Acme Inc.', text='Hello, World!')\nresponse: SmsResponse = vonage_client.sms.send(message)\n\nprint(response.model_dump(exclude_unset=True))\n```\n\n## Subaccounts API\n\n### List Subaccounts\n\n```python\nresponse = vonage_client.subaccounts.list_subaccounts()\nprint(response.model_dump)\n```\n\n### Create Subaccount\n\n```python\nfrom vonage_subaccounts import SubaccountOptions\n\nresponse = vonage_client.subaccounts.create_subaccount(\n    SubaccountOptions(\n        name='test_subaccount', secret='1234asdfA', use_primary_account_balance=False\n    )\n)\nprint(response)\n```\n\n### Modify a Subaccount\n\n```python\nfrom vonage_subaccounts import ModifySubaccountOptions\n\nresponse = vonage_client.subaccounts.modify_subaccount(\n    'test_subaccount',\n    ModifySubaccountOptions(\n        suspended=True,\n        name='modified_test_subaccount',\n    ),\n)\nprint(response)\n```\n\n### List Balance Transfers\n\n```python\nfrom vonage_subaccounts import ListTransfersFilter\n\nfilter = {'start_date': '2023-08-07T10:50:44Z'}\nresponse = vonage_client.subaccounts.list_balance_transfers(ListTransfersFilter(**filter))\nfor item in response:\n    print(item.model_dump())\n```\n\n### Transfer Balance Between Subaccounts\n\n```python\nfrom vonage_subaccounts import TransferRequest\n\nrequest = TransferRequest(\n    from_='test_api_key', to='test_subaccount', amount=0.02, reference='A reference'\n)\nresponse = vonage_client.subaccounts.transfer_balance(request)\nprint(response)\n```\n\n### List Credit Transfers\n\n```python\nfrom vonage_subaccounts import ListTransfersFilter\n\nfilter = {'start_date': '2023-08-07T10:50:44Z'}\nresponse = vonage_client.subaccounts.list_credit_transfers(ListTransfersFilter(**filter))\nfor item in response:\n    print(item.model_dump())\n```\n\n### Transfer Credit Between Subaccounts\n\n```python\nfrom vonage_subaccounts import TransferRequest\n\nrequest = TransferRequest(\n    from_='test_api_key', to='test_subaccount', amount=0.02, reference='A reference'\n)\nresponse = vonage_client.subaccounts.transfer_balance(request)\nprint(response)\n```\n\n### Transfer a Phone Number Between Subaccounts\n\n```python\nfrom vonage_subaccounts import TransferNumberRequest\n\nrequest = TransferNumberRequest(\n    from_='test_api_key', to='test_subaccount', number='447700900000', country='GB'\n)\nresponse = vonage_client.subaccounts.transfer_number(request)\nprint(response)\n```\n\n## Users API\n\n### List Users\n\nWith no custom options specified, this method will get the last 100 users. It returns a tuple consisting of a list of `UserSummary` objects and a string describing the cursor to the next page of results.\n\n```python\nfrom vonage_users import ListUsersRequest\n\nusers, _ = vonage_client.users.list_users()\n\n# With options\nparams = ListUsersRequest(\n    page_size=10,\n    cursor=my_cursor,\n    order='desc',\n)\nusers, next_cursor = vonage_client.users.list_users(params)\n```\n\n### Create a New User\n\n```python\nfrom vonage_users import User, Channels, SmsChannel\nuser_options = User(\n    name='my_user_name',\n    display_name='My User Name',\n    properties={'custom_key': 'custom_value'},\n    channels=Channels(sms=[SmsChannel(number='1234567890')]),\n)\nuser = vonage_client.users.create_user(user_options)\n```\n\n### Get a User\n\n```python\nuser = client.users.get_user('USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b')\nuser_as_dict = user.model_dump(exclude_none=True)\n```\n\n### Update a User\n```python\nfrom vonage_users import User, Channels, SmsChannel, WhatsappChannel\nuser_options = User(\n    name='my_user_name',\n    display_name='My User Name',\n    properties={'custom_key': 'custom_value'},\n    channels=Channels(sms=[SmsChannel(number='1234567890')], whatsapp=[WhatsappChannel(number='9876543210')]),\n)\nuser = vonage_client.users.update_user(id, user_options)\n```\n\n### Delete a User\n\n```python\nvonage_client.users.delete_user(id)\n```\n\n## Verify API\n\n### Make a Verify Request\n\n```python\nfrom vonage_verify import VerifyRequest, SmsChannel\n# All channels have associated models\nsms_channel = SmsChannel(to='1234567890')\nparams = {\n    'brand': 'Vonage',\n    'workflow': [sms_channel],\n}\nverify_request = VerifyRequest(**params)\n\nresponse = vonage_client.verify.start_verification(verify_request)\n```\n\nIf using silent authentication, the response will include a `check_url` field with a url that should be accessed on the user's device to proceed with silent authentication. If used, silent auth must be the first element in the `workflow` list.\n\n```python\nsilent_auth_channel = SilentAuthChannel(channel=ChannelType.SILENT_AUTH, to='1234567890')\nsms_channel = SmsChannel(to='1234567890')\nparams = {\n    'brand': 'Vonage',\n    'workflow': [silent_auth_channel, sms_channel],\n}\nverify_request = VerifyRequest(**params)\n\nresponse = vonage_client.verify.start_verification(verify_request)\n```\n\n### Check a Verification Code\n\n```python\nvonage_client.verify.check_code(request_id='my_request_id', code='1234')\n```\n\n### Cancel a Verification\n\n```python\nvonage_client.verify.cancel_verification('my_request_id')\n```\n\n### Trigger the Next Workflow Event\n\n```python\nvonage_client.verify.trigger_next_workflow('my_request_id')\n```\n\n## Verify API (Legacy)\n\n### Make a Verify Request\n\n```python\nfrom vonage_verify_legacy import VerifyRequest\nparams = {'number': '1234567890', 'brand': 'Acme Inc.'}\nrequest = VerifyRequest(**params)\nresponse = vonage_client.verify_legacy.start_verification(request)\n```\n\n### Make a PSD2 (Payment Services Directive v2) Request\n\n```python\nfrom vonage_verify_legacy import Psd2Request\nparams = {'number': '1234567890', 'payee': 'Acme Inc.', 'amount': 99.99}\nrequest = VerifyRequest(**params)\nresponse = vonage_client.verify_legacy.start_verification(request)\n```\n\n### Check a Verification Code\n\n```python\nvonage_client.verify_legacy.check_code(request_id='my_request_id', code='1234')\n```\n\n### Search Verification Requests\n\n```python\n# Search for single request\nresponse = vonage_client.verify_legacy.search('my_request_id')\n\n# Search for multiple requests\nresponse = vonage_client.verify_legacy.search(['my_request_id_1', 'my_request_id_2'])\n```\n\n### Cancel a Verification\n\n```python\nresponse = vonage_client.verify_legacy.cancel_verification('my_request_id')\n```\n\n### Trigger the Next Workflow Event\n\n```python\nresponse = vonage_client.verify_legacy.trigger_next_event('my_request_id')\n```\n\n### Request a Network Unblock\n\nNote: Network Unblock is switched off by default. Contact Sales to enable the Network Unblock API for your account.\n\n```python\nresponse = vonage_client.verify_legacy.request_network_unblock('23410')\n```\n\n## Video API\n\n### Generate a Client Token\n\n```python\nfrom vonage_video import TokenOptions\n\ntoken_options = TokenOptions(session_id='your_session_id', role='publisher')\nclient_token = vonage_client.video.generate_client_token(token_options)\n```\n\n### Create a Session\n\n```python\nfrom vonage_video import SessionOptions\n\nsession_options = SessionOptions(media_mode='routed')\nvideo_session = vonage_client.video.create_session(session_options)\n```\n\n### List Streams\n\n```python\nstreams = vonage_client.video.list_streams(session_id='your_session_id')\n```\n\n### Get a Stream\n\n```python\nstream_info = vonage_client.video.get_stream(session_id='your_session_id', stream_id='your_stream_id')\n```\n\n### Change Stream Layout\n\n```python\nfrom vonage_video import StreamLayoutOptions\n\nlayout_options = StreamLayoutOptions(type='bestFit')\nupdated_streams = vonage_client.video.change_stream_layout(session_id='your_session_id', stream_layout_options=layout_options)\n```\n\n### Send a Signal\n\n```python\nfrom vonage_video import SignalData\n\nsignal_data = SignalData(type='chat', data='Hello, World!')\nvonage_client.video.send_signal(session_id='your_session_id', data=signal_data)\n```\n\n### Disconnect a Client\n\n```python\nvonage_client.video.disconnect_client(session_id='your_session_id', connection_id='your_connection_id')\n```\n\n### Mute a Stream\n\n```python\nvonage_client.video.mute_stream(session_id='your_session_id', stream_id='your_stream_id')\n```\n\n### Mute All Streams\n\n```python\nvonage_client.video.mute_all_streams(session_id='your_session_id', excluded_stream_ids=['stream_id_1', 'stream_id_2'])\n```\n\n### Disable Mute All Streams\n\n```python\nvonage_client.video.disable_mute_all_streams(session_id='your_session_id')\n```\n\n### Start Captions\n\n```python\nfrom vonage_video import CaptionsOptions\n\ncaptions_options = CaptionsOptions(language='en-US')\ncaptions_data = vonage_client.video.start_captions(captions_options)\n```\n\n### Stop Captions\n\n```python\nfrom vonage_video import CaptionsData\n\ncaptions_data = CaptionsData(captions_id='your_captions_id')\nvonage_client.video.stop_captions(captions_data)\n```\n\n### Start Audio Connector\n\n```python\nfrom vonage_video import AudioConnectorOptions\n\naudio_connector_options = AudioConnectorOptions(session_id='your_session_id', token='your_token', url='https://example.com')\naudio_connector_data = vonage_client.video.start_audio_connector(audio_connector_options)\n```\n\n### Start Experience Composer\n\n```python\nfrom vonage_video import ExperienceComposerOptions\n\nexperience_composer_options = ExperienceComposerOptions(session_id='your_session_id', token='your_token', url='https://example.com')\nexperience_composer = vonage_client.video.start_experience_composer(experience_composer_options)\n```\n\n### List Experience Composers\n\n```python\nfrom vonage_video import ListExperienceComposersFilter\n\nfilter = ListExperienceComposersFilter(page_size=10)\nexperience_composers, count, next_page_offset = vonage_client.video.list_experience_composers(filter)\nprint(experience_composers)\n```\n\n### Get Experience Composer\n\n```python\nexperience_composer = vonage_client.video.get_experience_composer(experience_composer_id='experience_composer_id')\n```\n\n### Stop Experience Composer\n\n```python\nvonage_client.video.stop_experience_composer(experience_composer_id='experience_composer_id')\n```\n\n### List Archives\n\n```python\nfrom vonage_video import ListArchivesFilter\n\nfilter = ListArchivesFilter(offset=2)\narchives, count, next_page_offset = vonage_client.video.list_archives(filter)\nprint(archives)\n```\n\n### Start Archive\n\n```python\nfrom vonage_video import CreateArchiveRequest\n\narchive_options = CreateArchiveRequest(session_id='your_session_id', name='My Archive')\narchive = vonage_client.video.start_archive(archive_options)\n```\n\n### Get Archive\n\n```python\narchive = vonage_client.video.get_archive(archive_id='your_archive_id')\nprint(archive)\n```\n\n### Delete Archive\n\n```python\nvonage_client.video.delete_archive(archive_id='your_archive_id')\n```\n\n### Add Stream to Archive\n\n```python\nfrom vonage_video import AddStreamRequest\n\nadd_stream_request = AddStreamRequest(stream_id='your_stream_id')\nvonage_client.video.add_stream_to_archive(archive_id='your_archive_id', params=add_stream_request)\n```\n\n### Remove Stream from Archive\n\n```python\nvonage_client.video.remove_stream_from_archive(archive_id='your_archive_id', stream_id='your_stream_id')\n```\n\n### Stop Archive\n\n```python\narchive = vonage_client.video.stop_archive(archive_id='your_archive_id')\nprint(archive)\n```\n\n### Change Archive Layout\n\n```python\nfrom vonage_video import ComposedLayout\n\nlayout = ComposedLayout(type='bestFit')\narchive = vonage_client.video.change_archive_layout(archive_id='your_archive_id', layout=layout)\nprint(archive)\n```\n\n### List Broadcasts\n\n```python\nfrom vonage_video import ListBroadcastsFilter\n\nfilter = ListBroadcastsFilter(page_size=10)\nbroadcasts, count, next_page_offset = vonage_client.video.list_broadcasts(filter)\nprint(broadcasts)\n```\n\n### Start Broadcast\n\n```python\nfrom vonage_video import CreateBroadcastRequest, BroadcastOutputSettings, BroadcastHls, BroadcastRtmp\n\nbroadcast_options = CreateBroadcastRequest(session_id='your_session_id', outputs=BroadcastOutputSettings(\n    hls=BroadcastHls(dvr=True, low_latency=False),\n    rtmp=[\n        BroadcastRtmp(\n            id='test',\n            server_url='rtmp://a.rtmp.youtube.com/live2',\n            stream_name='stream-key',\n        )\n    ],\n)\n)\nbroadcast = vonage_client.video.start_broadcast(broadcast_options)\nprint(broadcast)\n```\n\n### Get Broadcast\n\n```python\nbroadcast = vonage_client.video.get_broadcast(broadcast_id='your_broadcast_id')\nprint(broadcast)\n```\n\n### Stop Broadcast\n\n```python\nbroadcast = vonage_client.video.stop_broadcast(broadcast_id='your_broadcast_id')\nprint(broadcast)\n```\n\n### Change Broadcast Layout\n\n```python\nfrom vonage_video import ComposedLayout\n\nlayout = ComposedLayout(type='bestFit')\nbroadcast = vonage_client.video.change_broadcast_layout(broadcast_id='your_broadcast_id', layout=layout)\nprint(broadcast)\n```\n\n### Add Stream to Broadcast\n\n```python\nfrom vonage_video import AddStreamRequest\n\nadd_stream_request = AddStreamRequest(stream_id='your_stream_id')\nvonage_client.video.add_stream_to_broadcast(broadcast_id='your_broadcast_id', params=add_stream_request)\n```\n\n### Remove Stream from Broadcast\n\n```python\nvonage_client.video.remove_stream_from_broadcast(broadcast_id='your_broadcast_id', stream_id='your_stream_id')\n```\n\n### Initiate SIP Call\n\n```python\nfrom vonage_video import InitiateSipRequest, SipOptions, SipAuth\n\nsip_request_params = InitiateSipRequest(\n    session_id='your_session_id',\n    token='your_token',\n    sip=SipOptions(\n        uri=f'sip:{vonage_number}@sip.nexmo.com;transport=tls',\n        from_=f'test@vonage.com',\n        headers={'header_key': 'header_value'},\n        auth=SipAuth(username='1485b9e6', password='fL8jvi4W2FmS9som'),\n        secure=False,\n        video=False,\n        observe_force_mute=True,\n    ),\n)\nsip_call = vonage_client.video.initiate_sip_call(sip_request_params)\nprint(sip_call)\n```\n\n### Play DTMF into a call\n\n```python\n# Play into all connections\nsession_id = 'your_session_id'\ndigits = '1234#*p'\n\nvonage_client.video.play_dtmf(session_id=session_id, digits=digits)\n\n# Play into one connection\nsession_id = 'your_session_id'\ndigits = '1234#*p'\nconnection_id = 'your_connection_id'\n\nvonage_client.video.play_dtmf(session_id=session_id, digits=digits, connection_id=connection_id)\n```\n\n## Voice API\n\n### Create a Call\n\nTo create a call, you must pass an instance of the `CreateCallRequest` model to the `create_call` method. If supplying an NCCO, import the NCCO actions you want to use and pass them in as a list to the `ncco` model field.\n\n```python\nfrom vonage_voice import CreateCallRequest, Talk\n\nncco = [Talk(text='Hello world', loop=3, language='en-GB')]\n\ncall = CreateCallRequest(\n    to=[{'type': 'phone', 'number': '1234567890'}],\n    ncco=ncco,\n    random_from_number=True,\n)\n\nresponse = vonage_client.voice.create_call(call)\nprint(response.model_dump())\n```\n\n### List Calls\n\n```python\n# Gets the first 100 results and the record_index of the\n# next page if there's more than 100\ncalls, next_record_index = vonage_client.voice.list_calls()\n\n# Specify filtering options\nfrom vonage_voice import ListCallsFilter\n\ncall_filter = ListCallsFilter(\n    status='completed',\n    date_start='2024-03-14T07:45:14Z',\n    date_end='2024-04-19T08:45:14Z',\n    page_size=10,\n    record_index=0,\n    order='asc',\n    conversation_uuid='CON-2be039b2-d0a4-4274-afc8-d7b241c7c044',\n)\n\ncalls, next_record_index = vonage_client.voice.list_calls(call_filter)\n```\n\n### Get Information About a Specific Call\n\n```python\ncall = vonage_client.voice.get_call('CALL_ID')\n```\n\n### Transfer a Call to a New NCCO\n\n```python\nncco = [Talk(text='Hello world')]\nvonage_client.voice.transfer_call_ncco('UUID', ncco)\n```\n\n### Transfer a Call to a New Answer URL\n\n```python\nvonage_client.voice.transfer_call_answer_url('UUID', 'ANSWER_URL')\n```\n\n### Hang Up a Call\n\nEnd the call for a specified UUID, removing them from it.\n\n```python\nvonage_client.voice.hangup('UUID')\n```\n\n### Mute/Unmute a Participant\n\n```python\nvonage_client.voice.mute('UUID')\nvonage_client.voice.unmute('UUID')\n```\n\n### Earmuff/Unearmuff a UUID\n\nPrevent/allow a specified UUID participant to be able to hear audio.\n\n```python\nvonage_client.voice.earmuff('UUID')\nvonage_client.voice.unearmuff('UUID')\n```\n\n### Play Audio Into a Call\n\n```python\nfrom vonage_voice import AudioStreamOptions\n\n# Only the `stream_url` option is required\noptions = AudioStreamOptions(\n    stream_url=['https://example.com/audio'], loop=2, level=0.5\n)\nresponse = vonage_client.voice.play_audio_into_call('UUID', options)\n```\n\n### Stop Playing Audio Into a Call\n\n```python\nvonage_client.voice.stop_audio_stream('UUID')\n```\n\n### Play TTS Into a Call\n\n```python\nfrom vonage_voice import TtsStreamOptions\n\n# Only the `text` field is required\noptions = TtsStreamOptions(\n    text='Hello world', language='en-ZA', style=1, premium=False, loop=2, level=0.5\n)\nresponse = voice.play_tts_into_call('UUID', options)\n```\n\n### Stop Playing TTS Into a Call\n\n```python\nvonage_client.voice.stop_tts('UUID')\n```\n\n### Play DTMF Tones Into a Call\n\n```python\nresponse = voice.play_dtmf_into_call('UUID', '1234*#')\n```\n\n## Vonage Utils Package\n\n```python\nfrom utils import format_phone_number, remove_none_values\n\n# Use format_phone_number\ntry:\n    formatted_number = format_phone_number('123-456-7890')\n    print(formatted_number)\nexcept (InvalidPhoneNumberError, InvalidPhoneNumberTypeError) as e:\n    print(e)\n\n# Use remove_none_values to remove null values from a Vonage API response when converting to a dictionary with the `asdict` method\nfrom dataclasses import asdict\n\nvonage_api_response = vonage.api.method()\ncleaned_dict = asdict(my_dataclass, dict_factory=remove_none_values)\nprint(cleaned_dict)\n```\n\n## Frequently Asked Questions\n\n### Supported APIs\n\nThe following is a list of Vonage APIs and whether the Python SDK provides support for them:\n\n| API                   |  API Release Status  | Supported? |\n| --------------------- | :------------------: | :--------: |\n| Account API           | General Availability |     ✅     |\n| Application API       | General Availability |     ✅     |\n| Audit API             |         Beta         |     ❌     |\n| Conversation API      |         Beta         |     ❌     |\n| Dispatch API          |         Beta         |     ❌     |\n| External Accounts API |         Beta         |     ❌     |\n| Media API             |         Beta         |     ❌     |\n| Messages API          | General Availability |     ✅     |\n| Number Insight API    | General Availability |     ✅     |\n| Number Management API | General Availability |     ✅     |\n| Pricing API           | General Availability |     ✅     |\n| Redact API            |   Developer Preview  |     ❌     |\n| Reports API           |         Beta         |     ❌     |\n| SMS API               | General Availability |     ✅     |\n| Subaccounts API       | General Availability |     ✅     |\n| Verify API            | General Availability |     ✅     |\n| Verify API (Legacy)   | General Availability |     ✅     |\n| Video API             | General Availability |     ✅     |\n| Voice API             | General Availability |     ✅     |\n\n### asyncio Support\n\n[asyncio](https://docs.python.org/3/library/asyncio.html) is a library to write **concurrent** code using the **async/await** syntax.\n\nWe don't currently support asyncio in the Python SDK.\n\n## Contributing\n\nWe :heart: contributions! But if you plan to work on something big or controversial, please contact us by raising an issue first!\n\nWe recommend working on `vonage-python-sdk` within a virtual environment - below we're using the [venv](https://docs.python.org/3/library/venv.html)] module:\n\n```bash\n# Create the virtual environment\npython3 -m venv venv\n\n# Activate the virtual environment in Mac/Linux\n. ./venv/bin/activate\n\n# Or on Windows Command Prompt\nvenv\\Scripts\\activate\n```\n\nThe following command will install all the Python dependencies you need to run the tests:\n\n```bash\npip install -r requirements.txt\n```\n\nThe tests are all written with pytest. You run them with:\n\n```bash\nPYTHONPATH=. pytest -v\n```\n\nWe use [Black](https://black.readthedocs.io/en/stable/index.html) for code formatting, with our config in the `pyproject.toml` file. To ensure a PR follows the right format, you can set up and use our pre-commit settings with\n\n```bash\npre-commit install\n```\n\nThen when you commit code, if it's not in the right format, it will be automatically fixed for you. After that, just commit again and everything should work as expected!\n\n## License\n\nThis library is released under the [Apache License](license).\n\n## Additional Resources\n\n- [Vonage Video API Developer Documentation](https://developer.vonage.com/en/video/overview)\n- [Link to the Vonage Python SDK](https://github.com/Vonage/vonage-python-sdk)\n- [Join the Vonage Developer Community Slack](https://developer.vonage.com/en/community/slack)\n- [Submit a Vonage Video API Support Request](https://api.support.vonage.com/hc/en-us)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvonage%2Fvonage-python-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvonage%2Fvonage-python-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvonage%2Fvonage-python-sdk/lists"}