├── sms
├── tests
│ ├── data
│ │ ├── null
│ │ ├── send_sms_error.json
│ │ ├── conversion_not_enabled.html
│ │ ├── send_sms.json
│ │ ├── send_sms_partial_error.json
│ │ └── send_long_sms.json
│ └── BUILD
├── src
│ └── vonage_sms
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ ├── errors.py
│ │ └── responses.py
├── BUILD
├── CHANGES.md
├── README.md
└── pyproject.toml
├── video
├── tests
│ ├── data
│ │ ├── nothing.json
│ │ ├── start_captions.json
│ │ ├── start_broadcast_error.json
│ │ ├── audio_connector.json
│ │ ├── stop_broadcast_timeout_error.json
│ │ ├── get_stream.json
│ │ ├── captions_error_already_enabled.json
│ │ ├── list_streams.json
│ │ ├── stop_archive_error.json
│ │ ├── delete_archive_error.json
│ │ ├── change_stream_layout.json
│ │ ├── initiate_sip_call.json
│ │ ├── start_experience_composer.json
│ │ ├── get_experience_composer.json
│ │ ├── stop_broadcast.json
│ │ ├── archive.json
│ │ ├── stop_archive.json
│ │ ├── create_session.json
│ │ ├── archive_with_transcription.json
│ │ ├── broadcast.json
│ │ ├── list_broadcasts_next_page.json
│ │ ├── list_experience_composers.json
│ │ └── list_archives.json
│ ├── BUILD
│ └── test_signal.py
├── src
│ └── vonage_video
│ │ ├── BUILD
│ │ ├── models
│ │ ├── BUILD
│ │ ├── signal.py
│ │ ├── captions.py
│ │ └── stream.py
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ └── errors.py
├── BUILD
├── CHANGES.md
└── pyproject.toml
├── vonage
├── tests
│ ├── BUILD
│ └── test_vonage.py
├── src
│ └── vonage
│ │ ├── BUILD
│ │ ├── _version.py
│ │ └── __init__.py
├── BUILD
├── pyproject.toml
└── README.md
├── number_management
├── tests
│ ├── data
│ │ ├── nothing.json
│ │ ├── number.json
│ │ ├── no_number.json
│ │ ├── list_owned_numbers_subset.json
│ │ ├── search_available_numbers_filter.json
│ │ ├── search_available_numbers_end_of_list.json
│ │ ├── list_owned_numbers_filter.json
│ │ ├── list_owned_numbers_basic.json
│ │ └── search_available_numbers_basic.json
│ └── BUILD
├── src
│ └── vonage_numbers
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── enums.py
│ │ └── __init__.py
├── CHANGES.md
├── BUILD
└── pyproject.toml
├── http_client
├── tests
│ ├── data
│ │ ├── 400.txt
│ │ ├── 400.json
│ │ ├── example_get.json
│ │ ├── example_post.json
│ │ ├── file_stream.mp3
│ │ ├── 500.json
│ │ ├── 429.json
│ │ ├── 401.json
│ │ ├── 403.json
│ │ ├── 404.json
│ │ ├── dummy_public_key.txt
│ │ └── dummy_private_key.txt
│ └── BUILD
├── src
│ └── vonage_http_client
│ │ ├── _version.py
│ │ ├── BUILD
│ │ └── __init__.py
├── BUILD
├── CHANGES.md
└── pyproject.toml
├── jwt
├── src
│ └── vonage_jwt
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ ├── errors.py
│ │ └── verify_jwt.py
├── tests
│ ├── BUILD
│ ├── data
│ │ ├── public_key.txt
│ │ └── private_key.txt
│ └── test_verify_jwt.py
├── BUILD
├── CHANGES.md
├── pyproject.toml
└── README.md
├── account
├── src
│ └── vonage_account
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── __init__.py
│ │ └── requests.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── get_balance.json
│ │ ├── top_up.json
│ │ ├── secret.json
│ │ ├── update_default_sms_webhook.json
│ │ ├── create_secret_error_max_number.json
│ │ ├── revoke_secret_error.json
│ │ ├── list_secrets.json
│ │ └── get_multiple_countries_pricing.json
├── CHANGES.md
├── BUILD
└── pyproject.toml
├── users
├── src
│ └── vonage_users
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ └── requests.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── user_not_found.json
│ │ ├── user.json
│ │ ├── updated_user.json
│ │ └── list_users_options.json
├── BUILD
├── CHANGES.md
├── pyproject.toml
└── README.md
├── verify
├── src
│ └── vonage_verify
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── enums.py
│ │ ├── __init__.py
│ │ └── responses.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── check_code.json
│ │ ├── verify_request.json
│ │ ├── trigger_next_workflow_error.json
│ │ ├── verify_request_error.json
│ │ ├── check_code_400.json
│ │ └── check_code_410.json
├── BUILD
├── CHANGES.md
├── pyproject.toml
└── README.md
├── voice
├── src
│ └── vonage_voice
│ │ ├── BUILD
│ │ ├── models
│ │ ├── BUILD
│ │ └── __init__.py
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ └── errors.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── file_stream.mp3
│ │ ├── stop_tts.json
│ │ ├── play_dtmf_into_call.json
│ │ ├── play_tts_into_call.json
│ │ ├── stop_audio_stream.json
│ │ ├── play_audio_into_call.json
│ │ ├── create_call.json
│ │ ├── get_call.json
│ │ └── list_calls_filter.json
├── BUILD
├── pyproject.toml
└── CHANGES.md
├── BUILD
├── messages
├── src
│ └── vonage_messages
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── models
│ │ ├── BUILD
│ │ ├── enums.py
│ │ └── base_message.py
│ │ ├── __init__.py
│ │ └── responses.py
├── tests
│ ├── BUILD
│ ├── data
│ │ ├── send_message.json
│ │ ├── send_message_with_failover.json
│ │ ├── not_found.json
│ │ ├── low_balance_error.json
│ │ └── invalid_error.json
│ └── test_sms_models.py
├── BUILD
├── CHANGES.md
└── pyproject.toml
├── application
├── src
│ └── vonage_application
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── enums.py
│ │ ├── requests.py
│ │ └── __init__.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── update_application.json
│ │ ├── create_application_basic.json
│ │ ├── get_application.json
│ │ └── list_applications_basic.json
├── CHANGES.md
├── BUILD
└── pyproject.toml
├── network_auth
├── src
│ └── vonage_network_auth
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ ├── requests.py
│ │ └── responses.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── oidc_request.json
│ │ ├── oidc_request_permissions_error.json
│ │ └── token_request.json
├── CHANGES.md
├── BUILD
├── pyproject.toml
└── README.md
├── subaccounts
├── src
│ └── vonage_subaccounts
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ └── __init__.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── transfer_number.json
│ │ ├── transfer_number_error_suspended_account.json
│ │ ├── get_subaccount.json
│ │ ├── modify_subaccount.json
│ │ ├── create_subaccount.json
│ │ ├── transfer.json
│ │ ├── list_balance_transfers.json
│ │ ├── list_credit_transfers.json
│ │ └── list_subaccounts.json
├── CHANGES.md
├── BUILD
└── pyproject.toml
├── number_insight
├── src
│ └── vonage_number_insight
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── __init__.py
│ │ └── requests.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── advanced_async_insight_error.json
│ │ ├── basic_insight_error.json
│ │ ├── advanced_async_insight.json
│ │ ├── advanced_async_insight_partial_error.json
│ │ ├── basic_insight.json
│ │ ├── standard_insight.json
│ │ └── advanced_sync_insight.json
├── BUILD
├── CHANGES.md
└── pyproject.toml
├── verify_legacy
├── src
│ └── vonage_verify_legacy
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── __init__.py
│ │ └── language_codes.py
├── tests
│ ├── BUILD
│ └── data
│ │ ├── cancel_verification.json
│ │ ├── trigger_next_event.json
│ │ ├── search_request_error.json
│ │ ├── network_unblock.json
│ │ ├── verify_request.json
│ │ ├── cancel_verification_error.json
│ │ ├── trigger_next_event_error.json
│ │ ├── check_code_error.json
│ │ ├── verify_request_error.json
│ │ ├── verify_request_error_with_network.json
│ │ ├── network_unblock_error.json
│ │ ├── check_code.json
│ │ └── search_request.json
├── CHANGES.md
├── BUILD
└── pyproject.toml
├── vonage_utils
├── src
│ └── vonage_utils
│ │ ├── _version.py
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── errors.py
│ │ ├── types.py
│ │ ├── models.py
│ │ └── utils.py
├── tests
│ ├── BUILD
│ ├── test_remove_none_values.py
│ └── test_format_phone_number.py
├── BUILD
├── CHANGES.md
├── pyproject.toml
└── README.md
├── network_sim_swap
├── src
│ └── vonage_network_sim_swap
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── __init__.py
│ │ ├── requests.py
│ │ └── responses.py
├── tests
│ ├── data
│ │ ├── check_sim_swap.json
│ │ └── get_swap_date.json
│ ├── BUILD
│ └── test_sim_swap.py
├── CHANGES.md
├── BUILD
├── pyproject.toml
└── README.md
├── network_number_verification
├── src
│ └── vonage_network_number_verification
│ │ ├── BUILD
│ │ ├── _version.py
│ │ ├── errors.py
│ │ ├── __init__.py
│ │ ├── responses.py
│ │ └── requests.py
├── tests
│ ├── data
│ │ ├── verify_number.json
│ │ └── token_request.json
│ └── BUILD
├── CHANGES.md
├── BUILD
└── pyproject.toml
├── pyproject.toml
├── pants.ci.toml
├── .mend
├── testutils
├── BUILD
├── __init__.py
├── mock_auth.py
├── data
│ └── fake_private_key.txt
└── testutils.py
├── .pre-commit-config.yaml
├── .github
├── ISSUE_TEMPLATE
│ ├── something-else.md
│ ├── feature_request.md
│ └── bug_report.md
└── workflows
│ ├── mutation-test.yml
│ └── build.yml
├── Makefile
├── requirements.txt
├── pants.toml
└── .gitignore
/sms/tests/data/null:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/video/tests/data/nothing.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/vonage/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests()
2 |
--------------------------------------------------------------------------------
/number_management/tests/data/nothing.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/http_client/tests/data/400.txt:
--------------------------------------------------------------------------------
1 | Error: Bad Request
--------------------------------------------------------------------------------
/jwt/src/vonage_jwt/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/sms/src/vonage_sms/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/account/src/vonage_account/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/users/src/vonage_users/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/verify/src/vonage_verify/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/video/src/vonage_video/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/voice/src/vonage_voice/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/BUILD:
--------------------------------------------------------------------------------
1 | python_requirements(
2 | name="reqs",
3 | )
4 |
--------------------------------------------------------------------------------
/http_client/tests/data/400.json:
--------------------------------------------------------------------------------
1 | {"Error": "Bad Request"}
--------------------------------------------------------------------------------
/jwt/src/vonage_jwt/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.1.5'
2 |
--------------------------------------------------------------------------------
/messages/src/vonage_messages/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/sms/src/vonage_sms/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.1.6'
2 |
--------------------------------------------------------------------------------
/video/src/vonage_video/models/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/voice/src/vonage_voice/models/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/vonage/src/vonage/BUILD:
--------------------------------------------------------------------------------
1 | python_sources(name='vonage')
2 |
--------------------------------------------------------------------------------
/vonage/src/vonage/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '4.7.2'
2 |
--------------------------------------------------------------------------------
/application/src/vonage_application/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/network_auth/src/vonage_network_auth/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/number_management/src/vonage_numbers/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/subaccounts/src/vonage_subaccounts/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/users/src/vonage_users/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.2.1'
2 |
--------------------------------------------------------------------------------
/verify/src/vonage_verify/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '2.1.0'
2 |
--------------------------------------------------------------------------------
/video/src/vonage_video/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.5.1'
2 |
--------------------------------------------------------------------------------
/voice/src/vonage_voice/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.4.0'
2 |
--------------------------------------------------------------------------------
/account/src/vonage_account/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.1.1'
2 |
--------------------------------------------------------------------------------
/jwt/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['jwt', 'testutils'])
2 |
--------------------------------------------------------------------------------
/messages/src/vonage_messages/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.6.2'
2 |
--------------------------------------------------------------------------------
/number_insight/src/vonage_number_insight/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/sms/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['sms', 'testutils'])
2 |
--------------------------------------------------------------------------------
/verify_legacy/src/vonage_verify_legacy/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.1.4'
2 |
--------------------------------------------------------------------------------
/application/src/vonage_application/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '2.0.1'
2 |
--------------------------------------------------------------------------------
/http_client/src/vonage_http_client/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.5.1'
2 |
--------------------------------------------------------------------------------
/http_client/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['http_client'])
2 |
--------------------------------------------------------------------------------
/http_client/tests/data/example_get.json:
--------------------------------------------------------------------------------
1 | {
2 | "hello": "world"
3 | }
--------------------------------------------------------------------------------
/http_client/tests/data/example_post.json:
--------------------------------------------------------------------------------
1 | {
2 | "hello": "world!"
3 | }
--------------------------------------------------------------------------------
/network_sim_swap/src/vonage_network_sim_swap/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/subaccounts/src/vonage_subaccounts/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.4'
2 |
--------------------------------------------------------------------------------
/users/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['users', 'testutils'])
2 |
--------------------------------------------------------------------------------
/verify/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['verify', 'testutils'])
2 |
--------------------------------------------------------------------------------
/video/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['video', 'testutils'])
2 |
--------------------------------------------------------------------------------
/voice/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['voice', 'testutils'])
2 |
--------------------------------------------------------------------------------
/account/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['account', 'testutils'])
2 |
--------------------------------------------------------------------------------
/messages/src/vonage_messages/models/BUILD:
--------------------------------------------------------------------------------
1 | python_sources(name='models')
2 |
--------------------------------------------------------------------------------
/messages/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['messages', 'testutils'])
2 |
--------------------------------------------------------------------------------
/network_auth/src/vonage_network_auth/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.2'
2 |
--------------------------------------------------------------------------------
/network_sim_swap/tests/data/check_sim_swap.json:
--------------------------------------------------------------------------------
1 | {
2 | "swapped": true
3 | }
--------------------------------------------------------------------------------
/number_insight/src/vonage_number_insight/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.7'
2 |
--------------------------------------------------------------------------------
/number_management/src/vonage_numbers/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.5'
2 |
--------------------------------------------------------------------------------
/verify_legacy/src/vonage_verify_legacy/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.1'
2 |
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/BUILD:
--------------------------------------------------------------------------------
1 | python_sources(name='vonage_utils')
2 |
--------------------------------------------------------------------------------
/application/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['application', 'testutils'])
2 |
--------------------------------------------------------------------------------
/http_client/src/vonage_http_client/BUILD:
--------------------------------------------------------------------------------
1 | python_sources(name='http_client')
2 |
--------------------------------------------------------------------------------
/network_sim_swap/src/vonage_network_sim_swap/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.1.2'
2 |
--------------------------------------------------------------------------------
/subaccounts/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['subaccounts', 'testutils'])
2 |
--------------------------------------------------------------------------------
/network_auth/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['network_auth', 'testutils'])
2 |
--------------------------------------------------------------------------------
/verify_legacy/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['verify_legacy', 'testutils'])
2 |
--------------------------------------------------------------------------------
/network_number_verification/src/vonage_network_number_verification/BUILD:
--------------------------------------------------------------------------------
1 | python_sources()
2 |
--------------------------------------------------------------------------------
/network_sim_swap/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['network_sim_swap', 'testutils'])
2 |
--------------------------------------------------------------------------------
/number_insight/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['number_insight', 'testutils'])
2 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.coverage.run]
2 | omit = ['**/tests/*', '**/src/**/_version.py']
3 |
--------------------------------------------------------------------------------
/vonage_utils/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['vonage_utils/src/vonage_utils'])
2 |
--------------------------------------------------------------------------------
/number_management/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['number_management', 'testutils'])
2 |
--------------------------------------------------------------------------------
/account/tests/data/get_balance.json:
--------------------------------------------------------------------------------
1 | {
2 | "value": 29.18202293,
3 | "autoReload": false
4 | }
--------------------------------------------------------------------------------
/pants.ci.toml:
--------------------------------------------------------------------------------
1 | [GLOBAL]
2 | colors = true
3 |
4 | [python]
5 | interpreter_constraints = ['>=3.9']
6 |
--------------------------------------------------------------------------------
/account/tests/data/top_up.json:
--------------------------------------------------------------------------------
1 | {
2 | "error-code": "200",
3 | "error-code-label": "success"
4 | }
--------------------------------------------------------------------------------
/messages/tests/data/send_message.json:
--------------------------------------------------------------------------------
1 | {
2 | "message_uuid": "d8f86df1-dec6-442f-870a-2241be27d721"
3 | }
--------------------------------------------------------------------------------
/network_number_verification/src/vonage_network_number_verification/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = '1.0.2'
2 |
--------------------------------------------------------------------------------
/network_number_verification/tests/data/verify_number.json:
--------------------------------------------------------------------------------
1 | {
2 | "devicePhoneNumberVerified": true
3 | }
--------------------------------------------------------------------------------
/network_sim_swap/tests/data/get_swap_date.json:
--------------------------------------------------------------------------------
1 | {
2 | "latestSimChange": "2023-12-22T04:00:44.000Z"
3 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/cancel_verification.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "0",
3 | "command": "cancel"
4 | }
--------------------------------------------------------------------------------
/video/tests/data/start_captions.json:
--------------------------------------------------------------------------------
1 | {
2 | "captionsId": "bc01a6b7-0e8e-4aa0-bb4e-2390f7cb18a1"
3 | }
--------------------------------------------------------------------------------
/network_number_verification/tests/BUILD:
--------------------------------------------------------------------------------
1 | python_tests(dependencies=['network_number_verification', 'testutils'])
2 |
--------------------------------------------------------------------------------
/number_management/tests/data/number.json:
--------------------------------------------------------------------------------
1 | {
2 | "error-code": "200",
3 | "error-code-label": "success"
4 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/trigger_next_event.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "0",
3 | "command": "trigger_next_event"
4 | }
--------------------------------------------------------------------------------
/number_management/tests/data/no_number.json:
--------------------------------------------------------------------------------
1 | {
2 | "error-code": "420",
3 | "error-code-label": "method failed"
4 | }
--------------------------------------------------------------------------------
/verify_legacy/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.0.1
2 | - Updated dependency versions
3 |
4 | # 1.0.0
5 | - Initial upload as `legacy` package
6 |
--------------------------------------------------------------------------------
/verify_legacy/tests/data/search_request_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "101",
3 | "error_text": "No response found"
4 | }
--------------------------------------------------------------------------------
/video/tests/data/start_broadcast_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "Session is already composed for given tag with code 409"
3 | }
--------------------------------------------------------------------------------
/voice/tests/data/file_stream.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vonage/vonage-python-sdk/HEAD/voice/tests/data/file_stream.mp3
--------------------------------------------------------------------------------
/voice/tests/data/stop_tts.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "Talk stopped",
3 | "uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
4 | }
--------------------------------------------------------------------------------
/number_insight/tests/data/advanced_async_insight_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "error_text": "Invalid credentials",
3 | "status": 4
4 | }
--------------------------------------------------------------------------------
/verify/tests/data/check_code.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "36e7060d-2b23-4257-bad0-773ab47f85ef",
3 | "status": "completed"
4 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/network_unblock.json:
--------------------------------------------------------------------------------
1 | {
2 | "network": "23410",
3 | "unblocked_until": "2024-04-22T08:34:58Z"
4 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/verify_request.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "abcdef0123456789abcdef0123456789",
3 | "status": "0"
4 | }
--------------------------------------------------------------------------------
/.mend:
--------------------------------------------------------------------------------
1 | {
2 | "settingsInheritedFrom": "Vonage/whitesource-config@main",
3 | "scanSettings": {
4 | "enableIaC": false
5 | }
6 | }
--------------------------------------------------------------------------------
/http_client/tests/data/file_stream.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Vonage/vonage-python-sdk/HEAD/http_client/tests/data/file_stream.mp3
--------------------------------------------------------------------------------
/voice/tests/data/play_dtmf_into_call.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "DTMF sent",
3 | "uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
4 | }
--------------------------------------------------------------------------------
/voice/tests/data/play_tts_into_call.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "Talk started",
3 | "uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
4 | }
--------------------------------------------------------------------------------
/voice/tests/data/stop_audio_stream.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "Stream stopped",
3 | "uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
4 | }
--------------------------------------------------------------------------------
/voice/tests/data/play_audio_into_call.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "Stream started",
3 | "uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
4 | }
--------------------------------------------------------------------------------
/testutils/BUILD:
--------------------------------------------------------------------------------
1 | file(name='fake_private_key', source='data/fake_private_key.txt')
2 |
3 | python_sources(dependencies=[':fake_private_key'])
4 |
--------------------------------------------------------------------------------
/video/tests/data/audio_connector.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "b3cd31f4-020e-4ba3-9a2a-12d98b8a184f",
3 | "connectionId": "1bf530df-97f4-4437-b6c9-2a66200200c8"
4 | }
--------------------------------------------------------------------------------
/video/tests/data/stop_broadcast_timeout_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": -1,
3 | "message": "Request timed out.",
4 | "description": "Request timed out."
5 | }
--------------------------------------------------------------------------------
/network_auth/tests/data/oidc_request.json:
--------------------------------------------------------------------------------
1 | {
2 | "auth_req_id": "arid/8b0d35f3-4627-487c-a776-aegtdsf4rsd2",
3 | "expires_in": 300,
4 | "interval": 0
5 | }
--------------------------------------------------------------------------------
/network_number_verification/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.0.2
2 | - Updated dependency versions
3 |
4 | # 1.0.1
5 | - Update dependency versions
6 |
7 | # 1.0.0
8 | - Initial upload
--------------------------------------------------------------------------------
/subaccounts/tests/data/transfer_number.json:
--------------------------------------------------------------------------------
1 | {
2 | "number": "447700900000",
3 | "country": "GB",
4 | "from": "test_api_key",
5 | "to": "asdfqwer"
6 | }
--------------------------------------------------------------------------------
/number_insight/tests/data/basic_insight_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": 3,
3 | "status_message": "Invalid request :: Not valid number format detected [ 145645562 ]"
4 | }
--------------------------------------------------------------------------------
/video/tests/data/get_stream.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "e08ff3f4-d04b-4363-bd6c-31bd29648ec8",
3 | "videoType": "camera",
4 | "name": "",
5 | "layoutClassList": []
6 | }
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.4.0
4 | hooks:
5 | - id: check-yaml
6 | - id: trailing-whitespace
--------------------------------------------------------------------------------
/http_client/tests/data/500.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.vonage.com/api-errors",
3 | "title": "Internal Server Error",
4 | "instance": "272c5fa3-c02a-4451-b33c-d01e8de74023"
5 | }
--------------------------------------------------------------------------------
/verify/src/vonage_verify/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class VerifyError(VonageError):
5 | """Indicates an error when using the Vonage Verify API."""
6 |
--------------------------------------------------------------------------------
/verify_legacy/tests/data/cancel_verification_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "6",
3 | "error_text": "The requestId 'cc121958d8fb4368aa3bb762bb9a0f75' does not exist or its no longer active."
4 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/trigger_next_event_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "19",
3 | "error_text": "No more events are left to execute for the request ['2c021d25cf2e47a9b277a996f4325b81']"
4 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/something-else.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Something else
3 | about: Custom template
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | Tell us what's up!
11 |
--------------------------------------------------------------------------------
/account/src/vonage_account/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class InvalidSecretError(VonageError):
5 | """Indicates that the secret provided was invalid."""
6 |
--------------------------------------------------------------------------------
/messages/tests/data/send_message_with_failover.json:
--------------------------------------------------------------------------------
1 | {
2 | "message_uuid": "d8f86df1-dec6-442f-870a-2241be27d721",
3 | "workflow_id": "3TcNjguHxr2vcCZ9Ddsnq6tw8yQUpZ9rMHv9QXSxLan5ibMxqSzLdx9"
4 | }
--------------------------------------------------------------------------------
/video/tests/data/captions_error_already_enabled.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 60003,
3 | "message": "Audio captioning is already enabled",
4 | "description": "Audio captioning is already enabled"
5 | }
--------------------------------------------------------------------------------
/application/src/vonage_application/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class ApplicationError(VonageError):
5 | """Indicates an error with the Application package."""
6 |
--------------------------------------------------------------------------------
/number_management/src/vonage_numbers/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class NumbersError(VonageError):
5 | """Indicates an error with the Numbers API package."""
6 |
--------------------------------------------------------------------------------
/subaccounts/src/vonage_subaccounts/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class InvalidSecretError(VonageError):
5 | """Indicates that the secret provided was invalid."""
6 |
--------------------------------------------------------------------------------
/sms/tests/data/send_sms_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "message-count": "1",
3 | "messages": [
4 | {
5 | "status": "7",
6 | "error-text": "Number barred."
7 | }
8 | ]
9 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/check_code_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "cc121958d8fb4368aa3bb762bb9a0f74",
3 | "status": "16",
4 | "error_text": "The code provided does not match the expected value"
5 | }
--------------------------------------------------------------------------------
/testutils/__init__.py:
--------------------------------------------------------------------------------
1 | from .mock_auth import get_mock_api_key_auth, get_mock_jwt_auth
2 | from .testutils import build_response
3 |
4 | __all__ = ['build_response', 'get_mock_api_key_auth', 'get_mock_jwt_auth']
5 |
--------------------------------------------------------------------------------
/verify_legacy/src/vonage_verify_legacy/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class VerifyError(VonageError):
5 | """Indicates an error when using the legacy Vonage Verify API."""
6 |
--------------------------------------------------------------------------------
/verify_legacy/tests/data/verify_request_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "b6fc2b91d23c43f9b8ea05f9be64415c",
3 | "status": "10",
4 | "error_text": "Concurrent verifications to the same number are not allowed"
5 | }
--------------------------------------------------------------------------------
/number_insight/src/vonage_number_insight/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class NumberInsightError(VonageError):
5 | """Indicates an error when using the Vonage Number Insight API."""
6 |
--------------------------------------------------------------------------------
/verify/tests/data/verify_request.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "2c59e3f4-a047-499f-a14f-819cd1989d2e",
3 | "check_url": "https://api-eu-3.vonage.com/v2/verify/cfbc9a3b-27a2-40d4-a4e0-0c59b3b41901/silent-auth/redirect"
4 | }
--------------------------------------------------------------------------------
/voice/tests/data/create_call.json:
--------------------------------------------------------------------------------
1 | {
2 | "uuid": "106a581a-34d0-432a-a625-220221fd434f",
3 | "status": "started",
4 | "direction": "outbound",
5 | "conversation_uuid": "CON-2be039b2-d0a4-4274-afc8-d7b241c7c044"
6 | }
--------------------------------------------------------------------------------
/messages/tests/data/not_found.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.vonage.com/api-errors#not-found",
3 | "title": "Not Found",
4 | "detail": "Message with ID asdf not found",
5 | "instance": "617431f2-06b7-4798-af36-1b8151df8359"
6 | }
--------------------------------------------------------------------------------
/http_client/tests/data/429.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Rate Limit Hit",
3 | "type": "https://developer.vonage.com/api-errors#rate-limit",
4 | "detail": "Please wait, then retry your request",
5 | "instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf"
6 | }
--------------------------------------------------------------------------------
/network_number_verification/src/vonage_network_number_verification/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils import VonageError
2 |
3 |
4 | class NetworkNumberVerificationError(VonageError):
5 | """Base class for Vonage Network Number Verification errors."""
6 |
--------------------------------------------------------------------------------
/account/tests/data/secret.json:
--------------------------------------------------------------------------------
1 | {
2 | "_links": {
3 | "self": {
4 | "href": "/accounts/test_api_key/secrets"
5 | }
6 | },
7 | "id": "ad6dc56f-07b5-46e1-a527-85530e625800",
8 | "created_at": "2017-03-02T16:34:49Z"
9 | }
--------------------------------------------------------------------------------
/http_client/tests/data/401.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.nexmo.com/api-errors#unauthorized",
3 | "title": "Unauthorized",
4 | "detail": "You did not provide correct credentials.",
5 | "instance": "a813c536-43f6-4568-acbf-f36ef2db955a"
6 | }
--------------------------------------------------------------------------------
/jwt/src/vonage_jwt/__init__.py:
--------------------------------------------------------------------------------
1 | from .errors import VonageJwtError, VonageVerifyJwtError
2 | from .jwt import JwtClient
3 | from .verify_jwt import verify_signature
4 |
5 | __all__ = ['JwtClient', 'VonageJwtError', 'VonageVerifyJwtError', 'verify_signature']
6 |
--------------------------------------------------------------------------------
/number_insight/tests/data/advanced_async_insight.json:
--------------------------------------------------------------------------------
1 | {
2 | "number": "447700900000",
3 | "remaining_balance": "32.92665294",
4 | "request_id": "434205b5-90ec-4ee2-a337-7b40d9683420",
5 | "request_price": "0.04000000",
6 | "status": 0
7 | }
--------------------------------------------------------------------------------
/video/src/vonage_video/__init__.py:
--------------------------------------------------------------------------------
1 | from . import errors, models # Import models to access the module directly
2 | from .models import * # Need this to directly expose data models
3 | from .video import Video
4 |
5 | __all__ = ['Video', 'errors', 'models']
6 |
--------------------------------------------------------------------------------
/voice/src/vonage_voice/__init__.py:
--------------------------------------------------------------------------------
1 | from . import errors, models # Import models to access the module directly
2 | from .models import * # Need this to directly expose data models
3 | from .voice import Voice
4 |
5 | __all__ = ['Voice', 'errors', 'models']
6 |
--------------------------------------------------------------------------------
/verify_legacy/tests/data/verify_request_error_with_network.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "b6fc2b91d23c43f9b8ea05f9be64415c",
3 | "status": "10",
4 | "error_text": "Concurrent verifications to the same number are not allowed",
5 | "network": "244523"
6 | }
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/__init__.py:
--------------------------------------------------------------------------------
1 | from . import models, types
2 | from .errors import VonageError
3 | from .utils import format_phone_number, remove_none_values
4 |
5 | __all__ = ['VonageError', 'format_phone_number', 'remove_none_values', 'models', 'types']
6 |
--------------------------------------------------------------------------------
/http_client/tests/data/403.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.vonage.com/api-errors#forbidden",
3 | "title": "Forbidden",
4 | "detail": "Your account does not have permission to perform this action.",
5 | "instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf"
6 | }
--------------------------------------------------------------------------------
/verify/tests/data/trigger_next_workflow_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Conflict",
3 | "detail": "There are no more events left to trigger.",
4 | "instance": "4d731cb7-25d3-487a-9ea0-f6b5811b534f",
5 | "type": "https://developer.nexmo.com/api-errors#conflict"
6 | }
--------------------------------------------------------------------------------
/http_client/tests/data/404.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Not found.",
3 | "type": "https://developer.vonage.com/api/conversation#user:error:not-found",
4 | "detail": "User does not exist, or you do not have access.",
5 | "instance": "00a5916655d650e920ccf0daf40ef4ee"
6 | }
--------------------------------------------------------------------------------
/verify/tests/data/verify_request_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Conflict",
3 | "detail": "Concurrent verifications to the same number are not allowed",
4 | "instance": "229ececf-382e-4ab6-b380-d8e0e830fd44",
5 | "request_id": "f8386e0f-6873-4617-aa99-19016217b2aa"
6 | }
--------------------------------------------------------------------------------
/network_sim_swap/src/vonage_network_sim_swap/__init__.py:
--------------------------------------------------------------------------------
1 | from .requests import SimSwapCheckRequest
2 | from .responses import LastSwapDate, SwapStatus
3 | from .sim_swap import NetworkSimSwap
4 |
5 | __all__ = ['NetworkSimSwap', 'LastSwapDate', 'SimSwapCheckRequest', 'SwapStatus']
6 |
--------------------------------------------------------------------------------
/users/tests/data/user_not_found.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Not found.",
3 | "type": "https://developer.vonage.com/api/conversation#user:error:not-found",
4 | "detail": "User does not exist, or you do not have access.",
5 | "instance": "00a5916655d650e920ccf0daf40ef4ee"
6 | }
--------------------------------------------------------------------------------
/verify/tests/data/check_code_400.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.nexmo.com/api-errors#bad-request",
3 | "title": "Invalid Code",
4 | "detail": "The code you provided does not match the expected value.",
5 | "instance": "475343c0-9239-4715-aed1-72b4a18379d1"
6 | }
--------------------------------------------------------------------------------
/verify/tests/data/check_code_410.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Invalid Code",
3 | "detail": "An incorrect code has been provided too many times. Workflow terminated.",
4 | "instance": "f79d7a15-30b7-498a-bc99-4e879b836b18",
5 | "type": "https://developer.nexmo.com/api-errors#gone"
6 | }
--------------------------------------------------------------------------------
/verify_legacy/tests/data/network_unblock_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.vonage.com/api-errors#bad-request",
3 | "title": "Not Found",
4 | "detail": "The network you provided does not have an active block.",
5 | "instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf"
6 | }
--------------------------------------------------------------------------------
/jwt/src/vonage_jwt/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils import VonageError
2 |
3 |
4 | class VonageJwtError(VonageError):
5 | """An error relating to the Vonage JWT Generator."""
6 |
7 |
8 | class VonageVerifyJwtError(VonageError):
9 | """The signature could not be verified."""
10 |
--------------------------------------------------------------------------------
/verify_legacy/tests/data/check_code.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "c5037cb8b47449158ed6611afde58990",
3 | "status": "0",
4 | "event_id": "390f7296-aeff-45ba-8931-84a13f3f76d7",
5 | "price": "0.05000000",
6 | "currency": "EUR",
7 | "estimated_price_messages_sent": "0.04675"
8 | }
--------------------------------------------------------------------------------
/video/tests/data/list_streams.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "items": [
4 | {
5 | "id": "e08ff3f4-d04b-4363-bd6c-31bd29648ec8",
6 | "videoType": "camera",
7 | "name": "",
8 | "layoutClassList": []
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/messages/tests/data/low_balance_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.nexmo.com/api-errors/#low-balance",
3 | "title": "Low balance",
4 | "detail": "This request could not be performed due to your account balance being low.",
5 | "instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf"
6 | }
--------------------------------------------------------------------------------
/account/tests/data/update_default_sms_webhook.json:
--------------------------------------------------------------------------------
1 | {
2 | "mo-callback-url": "https://example.com/inbound_sms_webhook",
3 | "dr-callback-url": "https://example.com/delivery_receipt_webhook",
4 | "max-outbound-request": 30,
5 | "max-inbound-request": 30,
6 | "max-calls-per-second": 30
7 | }
--------------------------------------------------------------------------------
/video/tests/data/stop_archive_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 15002,
3 | "message": "You can only stop an archive that has one of the following statuses: started OR paused OR stopped",
4 | "description": "You can only stop an archive that has one of the following statuses: started OR paused OR stopped"
5 | }
--------------------------------------------------------------------------------
/voice/src/vonage_voice/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class VoiceError(VonageError):
5 | """Indicates an error when using the Vonage Voice API."""
6 |
7 |
8 | class NccoActionError(VoiceError):
9 | """Indicates an error when using an NCCO action."""
10 |
--------------------------------------------------------------------------------
/network_auth/src/vonage_network_auth/__init__.py:
--------------------------------------------------------------------------------
1 | from .network_auth import NetworkAuth
2 | from .requests import CreateOidcUrl
3 | from .responses import OidcResponse, TokenResponse
4 |
5 | __all__ = [
6 | 'NetworkAuth',
7 | 'CreateOidcUrl',
8 | 'OidcResponse',
9 | 'TokenResponse',
10 | ]
11 |
--------------------------------------------------------------------------------
/video/tests/data/delete_archive_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 15004,
3 | "message": "You can only delete an archive that has one of the following statuses: available OR uploaded OR deleted",
4 | "description": "You can only delete an archive that has one of the following statuses: available OR uploaded OR deleted"
5 | }
--------------------------------------------------------------------------------
/messages/src/vonage_messages/__init__.py:
--------------------------------------------------------------------------------
1 | from . import models # Import models to access the module directly
2 | from .messages import Messages
3 | from .models import * # Need this to directly expose data models
4 | from .responses import SendMessageResponse
5 |
6 | __all__ = ['models', 'Messages', 'SendMessageResponse']
7 |
--------------------------------------------------------------------------------
/number_insight/tests/data/advanced_async_insight_partial_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "error_text": "Live mobile lookup not returned",
3 | "status": 43,
4 | "number": "447700900000",
5 | "remaining_balance": "32.92665294",
6 | "request_id": "434205b5-90ec-4ee2-a337-7b40d9683420",
7 | "request_price": "0.04000000"
8 | }
--------------------------------------------------------------------------------
/network_auth/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.0.2
2 | - Updated dependency versions
3 |
4 | # 1.0.1
5 | - Update dependency versions
6 |
7 | # 1.0.0
8 | - Add methods to work with the Vonage Number Verification API
9 | - Internal refactoring
10 |
11 | # 0.1.1b0
12 | - Add docstrings to data models
13 |
14 | # 0.1.0b0
15 | - Initial upload
--------------------------------------------------------------------------------
/account/tests/data/create_secret_error_max_number.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.nexmo.com/api-errors/account/secret-management#add-excess-secret",
3 | "title": "Secret Addition Forbidden",
4 | "detail": "Account reached maximum number [2] of allowed secrets",
5 | "instance": "48898273-7ae1-4ce4-8125-a71058ca6069"
6 | }
--------------------------------------------------------------------------------
/number_management/tests/data/list_owned_numbers_subset.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "numbers": [
4 | {
5 | "country": "ES",
6 | "msisdn": "3400000000",
7 | "type": "mobile-lvn",
8 | "features": [
9 | "SMS"
10 | ]
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/network_auth/tests/data/oidc_request_permissions_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.vonage.com/api-errors#invalid-param",
3 | "title": "Bad Request",
4 | "detail": "No Network Application associated with Vonage Application: 29f760f8-7ce1-46c9-ade3-f2dedee4ed5f",
5 | "instance": "b45ae630-7621-42b0-8ff0-6c1ad98e6e32"
6 | }
--------------------------------------------------------------------------------
/subaccounts/tests/data/transfer_number_error_suspended_account.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.nexmo.com/api-errors/subaccounts#invalid-number-transfer",
3 | "title": "Invalid Number Transfer",
4 | "detail": "One of the accounts involved in the transfer is banned",
5 | "instance": "ba2abf2a-e64d-4281-aca5-30f13947cbcd"
6 | }
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: format test coverage coverage-report install
2 |
3 | format:
4 | pants lint ::
5 | pants fix ::
6 |
7 | test:
8 | pants test ::
9 |
10 | coverage:
11 | pants test --use-coverage ::
12 |
13 | coverage-report:
14 | pants test --use-coverage --open-coverage ::
15 |
16 | install:
17 | pip install -r requirements.txt
--------------------------------------------------------------------------------
/video/tests/data/change_stream_layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "items": [
4 | {
5 | "id": "e08ff3f4-d04b-4363-bd6c-31bd29648ec8",
6 | "videoType": "camera",
7 | "name": "",
8 | "layoutClassList": [
9 | "full"
10 | ]
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/subaccounts/tests/data/get_subaccount.json:
--------------------------------------------------------------------------------
1 | {
2 | "api_key": "1234qwer",
3 | "primary_account_api_key": "test_api_key",
4 | "use_primary_account_balance": false,
5 | "name": "test_subaccount",
6 | "balance": 0.0000,
7 | "credit_limit": 0.0000,
8 | "suspended": false,
9 | "created_at": "2024-08-28T14:11:32.000Z"
10 | }
--------------------------------------------------------------------------------
/vonage/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 |
3 | file(name='readme', source='README.md')
4 |
5 | python_distribution(
6 | name='vonage',
7 | dependencies=[':pyproject', ':readme', 'vonage/src/vonage'],
8 | provides=python_artifact(),
9 | generate_setup=False,
10 | repositories=['@pypi'],
11 | )
12 |
--------------------------------------------------------------------------------
/subaccounts/tests/data/modify_subaccount.json:
--------------------------------------------------------------------------------
1 | {
2 | "api_key": "1234qwer",
3 | "primary_account_api_key": "asdf1234",
4 | "use_primary_account_balance": false,
5 | "name": "modified_test_subaccount",
6 | "balance": 0.0000,
7 | "credit_limit": 0.0000,
8 | "suspended": true,
9 | "created_at": "2024-08-28T14:11:32.000Z"
10 | }
--------------------------------------------------------------------------------
/account/tests/data/revoke_secret_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.nexmo.com/api-errors/account/secret-management#delete-last-secret",
3 | "title": "Secret Deletion Forbidden",
4 | "detail": "Can not delete the last secret. The account must always have at least 1 secret active at any time",
5 | "instance": "a845d164-5623-4cc1-b7c6-0f95b94c6e53"
6 | }
--------------------------------------------------------------------------------
/number_management/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.0.5
2 | - Added `by_alias=True` to the numbers update model
3 |
4 | # 1.0.4
5 | - Updated dependency versions
6 |
7 | # 1.0.3
8 | - Update dependency versions
9 |
10 | # 1.0.2
11 | - Support for Python 3.13, drop support for 3.8
12 |
13 | # 1.0.1
14 | - Add docstrings for data models
15 |
16 | # 1.0.0
17 | - Initial upload
18 |
--------------------------------------------------------------------------------
/account/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.1.1
2 | - Update dependency versions
3 |
4 | # 1.1.0
5 | - Add support for the [Vonage Pricing API](https://developer.vonage.com/en/api/pricing)
6 | - Update dependency versions
7 |
8 | # 1.0.2
9 | - Support for Python 3.13, drop support for 3.8
10 |
11 | # 1.0.1
12 | - Add docstrings to data models
13 |
14 | # 1.0.0
15 | - Initial upload
16 |
--------------------------------------------------------------------------------
/sms/src/vonage_sms/__init__.py:
--------------------------------------------------------------------------------
1 | from .errors import PartialFailureError, SmsError
2 | from .requests import SmsMessage
3 | from .responses import MessageResponse, SmsResponse
4 | from .sms import Sms
5 |
6 | __all__ = [
7 | 'Sms',
8 | 'SmsMessage',
9 | 'SmsResponse',
10 | 'MessageResponse',
11 | 'SmsError',
12 | 'PartialFailureError',
13 | ]
14 |
--------------------------------------------------------------------------------
/vonage_utils/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 |
3 | file(name='readme', source='README.md')
4 |
5 | python_distribution(
6 | name='vonage-utils',
7 | dependencies=[':pyproject', ':readme', 'vonage_utils/src/vonage_utils'],
8 | provides=python_artifact(),
9 | generate_setup=False,
10 | repositories=['@pypi'],
11 | )
12 |
--------------------------------------------------------------------------------
/number_management/tests/data/search_available_numbers_filter.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "numbers": [
4 | {
5 | "country": "GB",
6 | "msisdn": "442039055555",
7 | "cost": "1.00",
8 | "type": "landline",
9 | "features": [
10 | "VOICE"
11 | ]
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/application/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 2.0.1
2 | - Updated dependency versions
3 |
4 | # 2.0.0
5 | - Rename `params` -> `config` in method arguments
6 | - Update dependency versions
7 |
8 | # 1.0.3
9 | - Support for Python 3.13, drop support for 3.8
10 |
11 | # 1.0.2
12 | - Add docstrings to data models
13 |
14 | # 1.0.1
15 | - Update project metadata
16 |
17 | # 1.0.0
18 | - Initial upload
19 |
--------------------------------------------------------------------------------
/subaccounts/tests/data/create_subaccount.json:
--------------------------------------------------------------------------------
1 | {
2 | "api_key": "1234qwer",
3 | "secret": "SuperSecr3t",
4 | "primary_account_api_key": "test_api_key",
5 | "use_primary_account_balance": false,
6 | "name": "test_subaccount",
7 | "balance": 0.0000,
8 | "credit_limit": 0.0000,
9 | "suspended": false,
10 | "created_at": "2024-08-28T14:11:32.239Z"
11 | }
--------------------------------------------------------------------------------
/video/tests/data/initiate_sip_call.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "0022f6ba-c3a7-44db-843e-dd5ffa9d0493",
3 | "projectId": "29f760f8-7ce1-46c9-ade3-f2dedee4ed5f",
4 | "sessionId": "test_session_id",
5 | "connectionId": "4baf5788-fa5d-4b8d-b344-7315194ebc7d",
6 | "streamId": "de7d4fde-1773-4c7f-a0f8-3e1e2956d739",
7 | "createdAt": 1728383115393,
8 | "updatedAt": 1728383115393
9 | }
--------------------------------------------------------------------------------
/sms/tests/data/conversion_not_enabled.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Error 402
5 |
6 |
7 | HTTP ERROR: 402
8 | Problem accessing /conversions/sms. Reason:
9 |
Bad Account Credentials
10 |
Powered by Jetty://
11 |
12 |
--------------------------------------------------------------------------------
/subaccounts/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.0.4
2 | - Updated dependency versions
3 |
4 | # 1.0.3
5 | - Update dependency versions
6 |
7 | # 1.0.3
8 | - Support for Python 3.13, drop support for 3.8
9 |
10 | # 1.0.2
11 | - Add docstrings to data models
12 |
13 | # 1.0.1
14 | - Updated `vonage_subaccounts.ListSubaccountsResponse` for compatibility with Python 3.8
15 |
16 | # 1.0.0
17 | - Initial upload
18 |
--------------------------------------------------------------------------------
/network_sim_swap/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.1.2
2 | - Updated dependency versions
3 |
4 | # 1.1.1
5 | - Update dependency versions
6 |
7 | # 1.1.0
8 | - Add new model `SimSwapCheckRequest` to replace arguments in the `SimSwap.check` method
9 |
10 | # 1.0.0
11 | - Support for Python 3.13, drop support for 3.8
12 |
13 | # 0.1.1b0
14 | - Add docstrings to data models
15 |
16 | # 0.1.0b0
17 | - Initial upload
--------------------------------------------------------------------------------
/sms/tests/data/send_sms.json:
--------------------------------------------------------------------------------
1 | {
2 | "message-count": "1",
3 | "messages": [
4 | {
5 | "to": "1234567890",
6 | "message-id": "3295d748-4e14-4681-af78-166dca3c5aab",
7 | "status": "0",
8 | "remaining-balance": "38.07243628",
9 | "message-price": "0.04120000",
10 | "network": "23420"
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/number_management/tests/data/search_available_numbers_end_of_list.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "numbers": [
4 | {
5 | "country": "GB",
6 | "msisdn": "442039055555",
7 | "cost": "0.80",
8 | "type": "mobile-lvn",
9 | "features": [
10 | "VOICE",
11 | "SMS"
12 | ]
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/video/src/vonage_video/models/signal.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field
2 |
3 |
4 | class SignalData(BaseModel):
5 | """The data to send in a signal.
6 |
7 | Args:
8 | type (str): The type of data being sent to the client.
9 | data (str): Payload to send to the client.
10 | """
11 |
12 | type: str = Field(..., max_length=128)
13 | data: str = Field(..., max_length=8192)
14 |
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/errors.py:
--------------------------------------------------------------------------------
1 | class VonageError(Exception):
2 | """Base Error Class for all Vonage SDK errors."""
3 |
4 |
5 | class InvalidPhoneNumberError(VonageError):
6 | """An invalid phone number was provided."""
7 |
8 |
9 | class InvalidPhoneNumberTypeError(VonageError):
10 | """An invalid phone number type was provided.
11 |
12 | Should be a string or an integer.
13 | """
14 |
--------------------------------------------------------------------------------
/number_insight/tests/data/basic_insight.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": 0,
3 | "status_message": "Success",
4 | "request_id": "7f4a8a16-aa89-4078-b0ae-7743da34aca5",
5 | "international_format_number": "12345678900",
6 | "national_format_number": "(234) 567-8900",
7 | "country_code": "US",
8 | "country_code_iso3": "USA",
9 | "country_name": "United States of America",
10 | "country_prefix": "1"
11 | }
--------------------------------------------------------------------------------
/messages/tests/data/invalid_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "https://developer.vonage.com/api-errors/messages#1150",
3 | "title": "Invalid params",
4 | "detail": "The value of one or more parameters is invalid.",
5 | "instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf",
6 | "invalid_parameters": [
7 | {
8 | "name": "messenger.tag",
9 | "reason": "invalid value"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/jwt/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-jwt',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'jwt/src/vonage_jwt',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/sms/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-sms',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'sms/src/vonage_sms',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/users/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-users',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'users/src/vonage_users',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/video/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-video',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'video/src/vonage_video',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/video/tests/data/start_experience_composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "80c3d2d8-0848-41b2-be14-1a5b8936c87d",
3 | "sessionId": "test_session_id",
4 | "createdAt": 1727781191064,
5 | "updatedAt": 1727781191064,
6 | "url": "https://example.com",
7 | "status": "starting",
8 | "name": "test_experience_composer",
9 | "event": "render",
10 | "applicationId": "test_application_id",
11 | "resolution": "1280x720"
12 | }
--------------------------------------------------------------------------------
/voice/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-voice',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'voice/src/vonage_voice',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/verify/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-verify',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'verify/src/vonage_verify',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/account/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-account',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'account/src/vonage_account',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/messages/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-messages',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'messages/src/vonage_messages',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/application/tests/data/update_application.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1b1b1b1b-1b1b-1b1b-1b1b-1b1b1b1b1b1b",
3 | "name": "My Updated Application",
4 | "keys": {
5 | "public_key": "-----BEGIN PUBLIC KEY-----\nupdated_public_key_info\n-----END PUBLIC KEY-----\n"
6 | },
7 | "capabilities": {},
8 | "_links": {
9 | "self": {
10 | "href": "/v2/applications/1b1b1b1b-1b1b-1b1b-1b1b-1b1b1b1b1b1b"
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/application/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-application',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'application/src/vonage_application',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/subaccounts/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-subaccounts',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'subaccounts/src/vonage_subaccounts',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/verify_legacy/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-verify',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'verify_legacy/src/vonage_verify_legacy',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/network_auth/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-network-auth',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'network_auth/src/vonage_network_auth',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/number_management/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-numbers',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'number_management/src/vonage_numbers',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/vonage_utils/tests/test_remove_none_values.py:
--------------------------------------------------------------------------------
1 | from dataclasses import asdict, dataclass
2 |
3 | from vonage_utils.utils import remove_none_values
4 |
5 |
6 | @dataclass
7 | class MyDataClass:
8 | name: str
9 | age: int
10 | address: str = None
11 |
12 |
13 | def test_remove_none_values():
14 | data = MyDataClass(name='John', age=30)
15 | result = asdict(data, dict_factory=remove_none_values)
16 | assert result == {'name': 'John', 'age': 30}
17 |
--------------------------------------------------------------------------------
/http_client/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-http-client',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'http_client/src/vonage_http_client:http_client',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/number_insight/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-number-insight',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'number_insight/src/vonage_number_insight',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/subaccounts/tests/data/transfer.json:
--------------------------------------------------------------------------------
1 | {
2 | "masterAccountId": "test_api_key",
3 | "_links": {
4 | "self": {
5 | "href": "/accounts/test_api_key/balance-transfers/a1a90387-fcf2-41dc-9beb-cfd82b6b994d"
6 | }
7 | },
8 | "from": "test_api_key",
9 | "to": "asdfqwer",
10 | "amount": 0.02,
11 | "reference": "A reference",
12 | "id": "a1a90387-fcf2-41dc-9beb-cfd82b6b994d",
13 | "created_at": "2024-08-29T13:29:51.000Z"
14 | }
--------------------------------------------------------------------------------
/messages/src/vonage_messages/responses.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class SendMessageResponse(BaseModel):
7 | """Response from Vonage's Messages API.
8 |
9 | Attributes:
10 | message_uuid (str): The UUID of the sent message.
11 | workflow_id [str]: Workflow ID if the `failover` parameter was used in the request.
12 | """
13 |
14 | message_uuid: str
15 | workflow_id: Optional[str] = None
16 |
--------------------------------------------------------------------------------
/network_sim_swap/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-network-sim-swap',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'network_sim_swap/src/vonage_network_sim_swap',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/vonage_utils/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.1.4
2 | - Support for Python 3.13, drop support for 3.8
3 |
4 | # 1.1.3
5 | - Add docstrings to data models
6 |
7 | # 1.1.2
8 | - Refactoring common pydantic models across the monorepo into this package
9 |
10 | # 1.1.1
11 | - Update minimum dependency version
12 |
13 | # 1.1.0
14 | - Add `Dtmf` and `SipUri` types
15 | - Add `Link` model
16 | - Internal refactoring
17 |
18 | # 1.0.1
19 | - Add `PhoneNumber` type
20 |
21 | # 1.0.0
22 | - Initial upload
--------------------------------------------------------------------------------
/video/tests/data/get_experience_composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "be7712a4-3a63-4ed7-a2c6-7ffaebefd4a6",
3 | "sessionId": "test_session_id",
4 | "createdAt": 1727784741000,
5 | "updatedAt": 1727788344000,
6 | "url": "https://developer.vonage.com",
7 | "status": "stopped",
8 | "streamId": "C1B0E149-8169-4AFD-9397-882516EE9430",
9 | "reason": "Max duration exceeded",
10 | "event": "render",
11 | "applicationId": "test_application_id",
12 | "resolution": "1280x720"
13 | }
--------------------------------------------------------------------------------
/jwt/tests/data/public_key.txt:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HQB6iR7P2vkWtrm70nd
3 | b8/2lpSfQapzFLQe4Lk5coIHRDQG5XiJM3qeplB3qQyXUIfEL+s0t5aVHitFJA36
4 | 9fxb7L8bqxsP2GD2oFBIT/x8TG7Nq50E4gHVjk/lMfbzwAaMjWL2QfdMTSFYQQ0V
5 | oJM9Rz0AUTYxXJtzTqJfN4eVMKeWK6Bk1sfq6ZiIkYUI95r+pbpNdNnfeeLpaT6c
6 | 3GFiiKSTXXJSaxJAWWoIQ2UzqW7+/anfnbPQFadY/IvXBv6MASabCVsX8ErTA6TX
7 | hGaqKXkFpgNdtbEhLMaQGyieQwOxf5ZnJMe+LLpSh19Xw1k++nEYZaGhEFZhE3Y9
8 | FQIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/sms/tests/data/send_sms_partial_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "message-count": "2",
3 | "messages": [
4 | {
5 | "to": "1234567890",
6 | "message-id": "3295d748-4e14-4681-af78-166dca3c5aab",
7 | "status": "0",
8 | "remaining-balance": "38.07243628",
9 | "message-price": "0.04120000",
10 | "network": "23420"
11 | },
12 | {
13 | "status": "1",
14 | "error-text": "Throttled"
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/network_number_verification/src/vonage_network_number_verification/__init__.py:
--------------------------------------------------------------------------------
1 | from .errors import NetworkNumberVerificationError
2 | from .number_verification import CreateOidcUrl, NetworkNumberVerification
3 | from .requests import NumberVerificationRequest
4 | from .responses import NumberVerificationResponse
5 |
6 | __all__ = [
7 | 'NetworkNumberVerification',
8 | 'CreateOidcUrl',
9 | 'NumberVerificationRequest',
10 | 'NumberVerificationResponse',
11 | 'NetworkNumberVerificationError',
12 | ]
13 |
--------------------------------------------------------------------------------
/http_client/tests/data/dummy_public_key.txt:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HQB6iR7P2vkWtrm70nd
3 | b8/2lpSfQapzFLQe4Lk5coIHRDQG5XiJM3qeplB3qQyXUIfEL+s0t5aVHitFJA36
4 | 9fxb7L8bqxsP2GD2oFBIT/x8TG7Nq50E4gHVjk/lMfbzwAaMjWL2QfdMTSFYQQ0V
5 | oJM9Rz0AUTYxXJtzTqJfN4eVMKeWK6Bk1sfq6ZiIkYUI95r+pbpNdNnfeeLpaT6c
6 | 3GFiiKSTXXJSaxJAWWoIQ2UzqW7+/anfnbPQFadY/IvXBv6MASabCVsX8ErTA6TX
7 | hGaqKXkFpgNdtbEhLMaQGyieQwOxf5ZnJMe+LLpSh19Xw1k++nEYZaGhEFZhE3Y9
8 | FQIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/network_number_verification/BUILD:
--------------------------------------------------------------------------------
1 | resource(name='pyproject', source='pyproject.toml')
2 | file(name='readme', source='README.md')
3 |
4 | files(sources=['tests/data/*'])
5 |
6 | python_distribution(
7 | name='vonage-network-number-verification',
8 | dependencies=[
9 | ':pyproject',
10 | ':readme',
11 | 'network_number_verification/src/vonage_network_number_verification',
12 | ],
13 | provides=python_artifact(),
14 | generate_setup=False,
15 | repositories=['@pypi'],
16 | )
17 |
--------------------------------------------------------------------------------
/network_number_verification/src/vonage_network_number_verification/responses.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field
2 |
3 |
4 | class NumberVerificationResponse(BaseModel):
5 | """Model for the response from the Number Verification API.
6 |
7 | Args:
8 | device_phone_number_verified (bool): Whether the phone number has been
9 | successfully verified.
10 | """
11 |
12 | device_phone_number_verified: bool = Field(
13 | ..., validation_alias='devicePhoneNumberVerified'
14 | )
15 |
--------------------------------------------------------------------------------
/jwt/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.1.5
2 | - Improve `verify_signature` docstring
3 |
4 | # 1.1.4
5 | - Fix a bug with generating non-default JWTs
6 |
7 | # 1.1.3
8 | - Support for Python 3.13, drop support for 3.8
9 |
10 | # 1.1.2
11 | - Dynamically specify package version
12 |
13 | # 1.1.1
14 | - Exceptions inherit from `VonageError`
15 | - Moving the package into the Vonage Python SDK monorepo
16 |
17 | # 1.1.0
18 | - Add new module with method to verify JWT signatures, `verify_jwt.verify_signature`
19 |
20 | # 1.0.0
21 | - First stable release
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pytest>=8.0.0
2 | requests>=2.31.0
3 | responses>=0.24.1
4 | pydantic>=2.9.2
5 | typing-extensions>=4.9.0
6 | pyjwt[crypto]>=1.6.4
7 | toml>=0.10.2
8 | urllib3
9 |
10 | -e jwt
11 | -e http_client
12 | -e account
13 | -e application
14 | -e messages
15 | -e network_auth
16 | -e network_number_verification
17 | -e network_sim_swap
18 | -e number_insight
19 | -e number_management
20 | -e sms
21 | -e subaccounts
22 | -e users
23 | -e verify
24 | -e verify_legacy
25 | -e video
26 | -e voice
27 | -e vonage_utils
28 | -e vonage
29 |
--------------------------------------------------------------------------------
/sms/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.1.6
2 | - Make returned response fields optional
3 |
4 | # 1.1.5
5 | - Updated dependency versions
6 |
7 | # 1.1.4
8 | - Update dependency versions
9 |
10 | # 1.1.3
11 | - Support for Python 3.13, drop support for 3.8
12 |
13 | # 1.1.2
14 | - Add docstrings to data models
15 |
16 | # 1.1.1
17 | - Update minimum dependency version
18 |
19 | # 1.1.0
20 | - Add `http_client` property
21 |
22 | # 1.0.2
23 | - Internal refactoring
24 |
25 | # 1.0.1
26 | - Internal refactoring
27 |
28 | # 1.0.0
29 | - Initial upload
30 |
--------------------------------------------------------------------------------
/video/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.2.0
2 | - Make all models originally accessed by `vonage_video.models.***` available at the top level of the package, i.e. `vonage_video.***`
3 |
4 | # 1.1.0
5 | - Add new `max_bitrate` field for archives
6 |
7 | # 1.0.4
8 | - Updated dependency versions
9 |
10 | # 1.0.3
11 | - Make the filter optional in `Video.list_archives` and `Video.list_broadcasts`
12 |
13 | # 1.0.2
14 | - Update dependency versions
15 |
16 | # 1.0.1
17 | - Support for Python 3.13, drop support for 3.8
18 |
19 | # 1.0.0
20 | - Initial upload
21 |
--------------------------------------------------------------------------------
/number_management/tests/data/list_owned_numbers_filter.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "numbers": [
4 | {
5 | "country": "GB",
6 | "msisdn": "447007000000",
7 | "type": "mobile-lvn",
8 | "features": [
9 | "VOICE",
10 | "SMS"
11 | ],
12 | "voiceCallbackType": "app",
13 | "voiceCallbackValue": "29f769u7-7ce1-46c9-ade3-f2dedee4fr4t",
14 | "app_id": "29f769u7-7ce1-46c9-ade3-f2dedee4fr4t"
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/users/tests/data/user.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b",
3 | "name": "my_user_name",
4 | "display_name": "My User Name",
5 | "properties": {
6 | "custom_data": {}
7 | },
8 | "_links": {
9 | "self": {
10 | "href": "https://api-us-3.vonage.com/v1/users/USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b"
11 | }
12 | },
13 | "channels": {
14 | "sms": [
15 | {
16 | "number": "1234567890"
17 | }
18 | ]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/number_management/src/vonage_numbers/enums.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class NumberType(str, Enum):
5 | LANDLINE = 'landline'
6 | MOBILE_LVN = 'mobile-lvn'
7 | LANDLINE_TOLL_FREE = 'landline-toll-free'
8 |
9 |
10 | class NumberFeatures(str, Enum):
11 | SMS = 'SMS'
12 | VOICE = 'VOICE'
13 | MMS = 'MMS'
14 | SMS_VOICE = 'SMS,VOICE'
15 | SMS_MMS = 'SMS,MMS'
16 | VOICE_MMS = 'VOICE,MMS'
17 | SMS_VOICE_MMS = 'SMS,VOICE,MMS'
18 |
19 |
20 | class VoiceCallbackType(str, Enum):
21 | SIP = 'sip'
22 | TEL = 'tel'
23 |
--------------------------------------------------------------------------------
/application/src/vonage_application/enums.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class Region(str, Enum):
5 | """All inbound, programmable SIP and SIP connect voice calls will be sent to the
6 | selected region unless the call itself is sent to a regional endpoint.
7 |
8 | If the call is using a regional endpoint, this will override the application setting.
9 | """
10 |
11 | NA_EAST = 'na-east'
12 | NA_WEST = 'na-west'
13 | EU_EAST = 'eu-east'
14 | EU_WEST = 'eu-west'
15 | APAC_SNG = 'apac-sng'
16 | APAC_AUSTRALIA = 'apac-australia'
17 |
--------------------------------------------------------------------------------
/verify/src/vonage_verify/enums.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class ChannelType(str, Enum):
5 | SILENT_AUTH = 'silent_auth'
6 | SMS = 'sms'
7 | WHATSAPP = 'whatsapp'
8 | VOICE = 'voice'
9 | EMAIL = 'email'
10 |
11 |
12 | class Locale(str, Enum):
13 | EN_US = 'en-us'
14 | EN_GB = 'en-gb'
15 | ES_ES = 'es-es'
16 | ES_MX = 'es-mx'
17 | ES_US = 'es-us'
18 | IT_IT = 'it-it'
19 | FR_FR = 'fr-fr'
20 | DE_DE = 'de-de'
21 | RU_RU = 'ru-ru'
22 | HI_IN = 'hi-in'
23 | PT_BR = 'pt-br'
24 | PT_PT = 'pt-pt'
25 | ID_ID = 'id-id'
26 |
--------------------------------------------------------------------------------
/sms/src/vonage_sms/errors.py:
--------------------------------------------------------------------------------
1 | from requests import Response
2 | from vonage_utils.errors import VonageError
3 |
4 |
5 | class SmsError(VonageError):
6 | """Indicates an error with the Vonage SMS Package."""
7 |
8 |
9 | class PartialFailureError(SmsError):
10 | """Indicates that a request was partially successful."""
11 |
12 | def __init__(self, response: Response):
13 | self.message = (
14 | 'Sms.send_message method partially failed. Not all of the message(s) sent successfully.',
15 | )
16 | super().__init__(self.message)
17 | self.response = response
18 |
--------------------------------------------------------------------------------
/account/tests/data/list_secrets.json:
--------------------------------------------------------------------------------
1 | {
2 | "_links": {
3 | "self": {
4 | "href": "/accounts/test_api_key/secrets"
5 | }
6 | },
7 | "_embedded": {
8 | "secrets": [
9 | {
10 | "_links": {
11 | "self": {
12 | "href": "/accounts/test_api_key/secrets/1b1b1b1b-1b1b-1b-1b1b-1b1b1b1b1b1b"
13 | }
14 | },
15 | "id": "1b1b1b1b-1b1b-1b-1b1b-1b1b1b1b1b1b",
16 | "created_at": "2022-03-28T14:16:56Z"
17 | }
18 | ]
19 | }
20 | }
--------------------------------------------------------------------------------
/users/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.2.1
2 | - Updated dependency versions
3 |
4 | # 1.2.0
5 | - Expose more properties in the top-level `vonage_users` scope
6 | - Update dependency versions
7 |
8 | # 1.1.4
9 | - Support for Python 3.13, drop support for 3.8
10 |
11 | # 1.1.3
12 | - Add docstrings to data models
13 |
14 | # 1.1.2
15 | - Internal refactoring
16 |
17 | # 1.1.1
18 | - Update minimum dependency version
19 |
20 | # 1.1.0
21 | - Add `http_client` property
22 | - Rename `ListUsersRequest` -> `ListUsersFilter`
23 | - Internal refactoring
24 |
25 | # 1.0.1
26 | - Internal refactoring
27 |
28 | # 1.0.0
29 | - Initial upload
30 |
--------------------------------------------------------------------------------
/application/tests/data/create_application_basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "ba1a6aa3-8ac6-487d-ac5c-be469e77ddb7",
3 | "name": "My Application",
4 | "keys": {
5 | "private_key": "-----BEGIN PRIVATE KEY-----\nprivate_key_info_goes_here\n-----END PRIVATE KEY-----\n",
6 | "public_key": "-----BEGIN PUBLIC KEY-----\npublic_key_info_goes_here\n-----END PUBLIC KEY-----\n"
7 | },
8 | "privacy": {
9 | "improve_ai": false
10 | },
11 | "capabilities": {},
12 | "_links": {
13 | "self": {
14 | "href": "/v2/applications/ba1a6aa3-8ac6-487d-ac5c-be469e77ddb7"
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/users/tests/data/updated_user.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b",
3 | "name": "new name!",
4 | "display_name": "My New Renamed User Name",
5 | "properties": {},
6 | "_links": {
7 | "self": {
8 | "href": "https://api-us-3.vonage.com/v1/users/USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b"
9 | }
10 | },
11 | "channels": {
12 | "sms": [
13 | {
14 | "number": "1234567890"
15 | }
16 | ],
17 | "pstn": [
18 | {
19 | "number": 123456
20 | }
21 | ]
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/vonage/tests/test_vonage.py:
--------------------------------------------------------------------------------
1 | from vonage_http_client.http_client import HttpClient
2 |
3 | from vonage.vonage import Auth, Vonage, __version__
4 |
5 |
6 | def test_create_vonage_class_instance():
7 | vonage = Vonage(Auth(api_key='asdf', api_secret='qwerasdf'))
8 |
9 | assert vonage.http_client.auth.api_key == 'asdf'
10 | assert vonage.http_client.auth.api_secret == 'qwerasdf'
11 | assert (
12 | vonage.http_client.auth.create_basic_auth_string() == 'Basic YXNkZjpxd2VyYXNkZg=='
13 | )
14 | assert type(vonage.http_client) == HttpClient
15 | assert f'vonage-python-sdk/{__version__}' in vonage.http_client._user_agent
16 |
--------------------------------------------------------------------------------
/verify/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 2.1.0
2 | - Add support for API key/secret header authentication
3 | - Updated dependency versions
4 |
5 | # 2.0.0
6 | - Rename `vonage-verify-v2` package -> `vonage-verify`, `VerifyV2` -> `Verify`, etc. This package now contains code for the Verify v2 API
7 | - Update dependency versions
8 |
9 | # 1.1.4
10 | - Support for Python 3.13, drop support for 3.8
11 |
12 | # 1.1.3
13 | - Add docstrings for data models
14 |
15 | # 1.1.2
16 | - Allow minimum `channel_timeout` value to be 15 seconds
17 |
18 | # 1.1.1
19 | - Update minimum dependency version
20 |
21 | # 1.1.0
22 | - Add `http_client` property
23 |
24 | # 1.0.0
25 | - Initial upload
26 |
--------------------------------------------------------------------------------
/number_insight/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.0.7
2 | - Use basic header auth instead of request body auth
3 |
4 | # 1.0.6
5 | - Updated dependency versions
6 |
7 | # 1.0.5
8 | - Fix missed method renaming
9 | - Docstring update
10 |
11 | # 1.0.4
12 | - Update dependency versions
13 |
14 | # 1.0.3
15 | - Rename `basic_number_insight` -> `get_basic_info`, `standard_number_insight` -> `get_standard_info`, `advanced_async_number_insight` -> `get_advanced_info_async`, `advanced_sync_number_insight` -> `get_advanced_info_sync`
16 |
17 | # 1.0.2
18 | - Support for Python 3.13, drop support for 3.8
19 |
20 | # 1.0.1
21 | - Add docstrings to data models
22 |
23 | # 1.0.0
24 | - Initial upload
25 |
--------------------------------------------------------------------------------
/network_sim_swap/src/vonage_network_sim_swap/requests.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel, Field
4 |
5 |
6 | class SimSwapCheckRequest(BaseModel):
7 | """Request model to check if a SIM has been swapped using the Vonage Sim Swap Network
8 | API.
9 |
10 | Args:
11 | phone_number (str): The phone number to check. Use the E.164 format with
12 | or without a leading +.
13 | max_age (int, optional): Period in hours to be checked for SIM swap.
14 | """
15 |
16 | phone_number: str = Field(..., serialization_alias='phoneNumber')
17 | max_age: Optional[int] = Field(None, serialization_alias='maxAge')
18 |
--------------------------------------------------------------------------------
/network_auth/src/vonage_network_auth/requests.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class CreateOidcUrl(BaseModel):
7 | """Model to craft a URL for OIDC authentication.
8 |
9 | Args:
10 | redirect_uri (str): The URI to redirect to after authentication.
11 | state (str): A unique identifier for the request. Can be any string.
12 | login_hint (str): The phone number to use for the request.
13 | """
14 |
15 | redirect_uri: str
16 | state: str
17 | login_hint: str
18 | scope: Optional[str] = (
19 | 'openid dpv:FraudPreventionAndDetection#number-verification-verify-read'
20 | )
21 |
--------------------------------------------------------------------------------
/network_sim_swap/src/vonage_network_sim_swap/responses.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field
2 |
3 |
4 | class SwapStatus(BaseModel):
5 | """Model for the status of a SIM swap.
6 |
7 | Args:
8 | swapped (str): Indicates whether the SIM card has been swapped during the period
9 | within the `max_age` provided in the request.
10 | """
11 |
12 | swapped: str
13 |
14 |
15 | class LastSwapDate(BaseModel):
16 | """Model for the last SIM swap date information.
17 |
18 | Args:
19 | last_swap_date (str): The timestamp of the latest SIM swap performed.
20 | """
21 |
22 | last_swap_date: str = Field(..., validation_alias='latestSimChange')
23 |
--------------------------------------------------------------------------------
/video/tests/data/stop_broadcast.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "f03fad17-4591-4422-8bd3-00a4df1e616a",
3 | "sessionId": "test_session_id",
4 | "applicationId": "test_application_id",
5 | "createdAt": 1728060457664,
6 | "broadcastUrls": null,
7 | "updatedAt": 1728060581508,
8 | "status": "stopped",
9 | "streamMode": "auto",
10 | "hasAudio": true,
11 | "hasVideo": true,
12 | "maxDuration": 3600,
13 | "multiBroadcastTag": "test-broadcast",
14 | "maxBitrate": 1000000,
15 | "settings": {
16 | "hls": {
17 | "lowLatency": false,
18 | "dvr": true
19 | }
20 | },
21 | "event": "broadcast",
22 | "resolution": "1280x720"
23 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/verify/src/vonage_verify/__init__.py:
--------------------------------------------------------------------------------
1 | from .enums import ChannelType, Locale
2 | from .errors import VerifyError
3 | from .requests import (
4 | EmailChannel,
5 | SilentAuthChannel,
6 | SmsChannel,
7 | VerifyRequest,
8 | VoiceChannel,
9 | WhatsappChannel,
10 | )
11 | from .responses import CheckCodeResponse, StartVerificationResponse
12 | from .verify import Verify
13 |
14 | __all__ = [
15 | 'Verify',
16 | 'VerifyError',
17 | 'ChannelType',
18 | 'CheckCodeResponse',
19 | 'Locale',
20 | 'VerifyRequest',
21 | 'SilentAuthChannel',
22 | 'SmsChannel',
23 | 'WhatsappChannel',
24 | 'VoiceChannel',
25 | 'EmailChannel',
26 | 'StartVerificationResponse',
27 | ]
28 |
--------------------------------------------------------------------------------
/testutils/mock_auth.py:
--------------------------------------------------------------------------------
1 | from os.path import dirname, join
2 |
3 | from vonage_http_client.auth import Auth
4 |
5 |
6 | def read_file(path):
7 | """Read a file from the testutils/data directory."""
8 |
9 | with open(join(dirname(__file__), path)) as input_file:
10 | return input_file.read()
11 |
12 |
13 | def get_mock_api_key_auth():
14 | """Return an Auth object with an API key and secret."""
15 |
16 | return Auth(api_key='test_api_key', api_secret='test_api_secret')
17 |
18 |
19 | def get_mock_jwt_auth():
20 | """Return an Auth object with a JWT."""
21 |
22 | return Auth(
23 | application_id='test_application_id',
24 | private_key=read_file('data/fake_private_key.txt'),
25 | )
26 |
--------------------------------------------------------------------------------
/verify_legacy/src/vonage_verify_legacy/__init__.py:
--------------------------------------------------------------------------------
1 | from .errors import VerifyError
2 | from .language_codes import LanguageCode, Psd2LanguageCode
3 | from .requests import Psd2Request, VerifyRequest
4 | from .responses import (
5 | CheckCodeResponse,
6 | NetworkUnblockStatus,
7 | StartVerificationResponse,
8 | VerifyControlStatus,
9 | VerifyStatus,
10 | )
11 | from .verify_legacy import VerifyLegacy
12 |
13 | __all__ = [
14 | 'VerifyError',
15 | 'VerifyLegacy',
16 | 'LanguageCode',
17 | 'Psd2LanguageCode',
18 | 'Psd2Request',
19 | 'VerifyRequest',
20 | 'CheckCodeResponse',
21 | 'NetworkUnblockStatus',
22 | 'StartVerificationResponse',
23 | 'VerifyControlStatus',
24 | 'VerifyStatus',
25 | ]
26 |
--------------------------------------------------------------------------------
/number_management/tests/data/list_owned_numbers_basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "numbers": [
4 | {
5 | "country": "ES",
6 | "msisdn": "3400000000",
7 | "type": "mobile-lvn",
8 | "features": [
9 | "SMS"
10 | ]
11 | },
12 | {
13 | "country": "GB",
14 | "msisdn": "447007000000",
15 | "type": "mobile-lvn",
16 | "features": [
17 | "VOICE",
18 | "SMS"
19 | ],
20 | "voiceCallbackType": "app",
21 | "voiceCallbackValue": "29f769u7-7ce1-46c9-ade3-f2dedee4fr4t",
22 | "app_id": "29f769u7-7ce1-46c9-ade3-f2dedee4fr4t"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/voice/tests/data/get_call.json:
--------------------------------------------------------------------------------
1 | {
2 | "_links": {
3 | "self": {
4 | "href": "/v1/calls/e154eb57-2962-41e7-baf4-90f63e25e439"
5 | }
6 | },
7 | "conversation_uuid": "CON-d4e1389a-b2c8-4621-97eb-c6f3a2b51c72",
8 | "direction": "outbound",
9 | "duration": "2",
10 | "end_time": "2024-04-19T01:34:20.000Z",
11 | "from": {
12 | "number": "9876543210",
13 | "type": "phone"
14 | },
15 | "network": "23420",
16 | "price": "0.00333333",
17 | "rate": "0.10000000",
18 | "start_time": "2024-04-19T01:34:18.000Z",
19 | "status": "completed",
20 | "to": {
21 | "number": "1234567890",
22 | "type": "phone"
23 | },
24 | "uuid": "e154eb57-2962-41e7-baf4-90f63e25e439"
25 | }
--------------------------------------------------------------------------------
/number_management/src/vonage_numbers/__init__.py:
--------------------------------------------------------------------------------
1 | from .enums import NumberFeatures, NumberType, VoiceCallbackType
2 | from .errors import NumbersError
3 | from .number_management import Numbers
4 | from .requests import (
5 | ListOwnedNumbersFilter,
6 | NumberParams,
7 | SearchAvailableNumbersFilter,
8 | UpdateNumberParams,
9 | )
10 | from .responses import AvailableNumber, NumbersStatus, OwnedNumber
11 |
12 | __all__ = [
13 | 'NumberFeatures',
14 | 'NumberType',
15 | 'VoiceCallbackType',
16 | 'NumbersError',
17 | 'Numbers',
18 | 'ListOwnedNumbersFilter',
19 | 'NumberParams',
20 | 'SearchAvailableNumbersFilter',
21 | 'UpdateNumberParams',
22 | 'AvailableNumber',
23 | 'NumbersStatus',
24 | 'OwnedNumber',
25 | ]
26 |
--------------------------------------------------------------------------------
/account/src/vonage_account/__init__.py:
--------------------------------------------------------------------------------
1 | from .account import Account
2 | from .errors import InvalidSecretError
3 | from .requests import GetCountryPricingRequest, GetPrefixPricingRequest, ServiceType
4 | from .responses import (
5 | Balance,
6 | GetMultiplePricingResponse,
7 | GetPricingResponse,
8 | NetworkPricing,
9 | SettingsResponse,
10 | TopUpResponse,
11 | VonageApiSecret,
12 | )
13 |
14 | __all__ = [
15 | 'Account',
16 | 'InvalidSecretError',
17 | 'GetCountryPricingRequest',
18 | 'GetPrefixPricingRequest',
19 | 'ServiceType',
20 | 'Balance',
21 | 'GetPricingResponse',
22 | 'GetMultiplePricingResponse',
23 | 'NetworkPricing',
24 | 'SettingsResponse',
25 | 'TopUpResponse',
26 | 'VonageApiSecret',
27 | ]
28 |
--------------------------------------------------------------------------------
/sms/tests/data/send_long_sms.json:
--------------------------------------------------------------------------------
1 | {
2 | "message-count": "2",
3 | "messages": [
4 | {
5 | "to": "1234567890",
6 | "message-id": "62dfdf68-6c7c-479a-a190-5c52f798a787",
7 | "status": "0",
8 | "remaining-balance": "37.43563628",
9 | "message-price": "0.04120000",
10 | "network": "23420",
11 | "client-ref": "ref123"
12 | },
13 | {
14 | "to": "1234567890",
15 | "message-id": "72ff9536-62d6-455a-9f0b-65f3c265b423",
16 | "status": "0",
17 | "remaining-balance": "37.43563628",
18 | "message-price": "0.04120000",
19 | "network": "23420",
20 | "client-ref": "ref123"
21 | }
22 | ]
23 | }
--------------------------------------------------------------------------------
/video/tests/data/archive.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "5b1521e6-115f-4efd-bed9-e527b87f0699",
3 | "status": "started",
4 | "name": "first archive test",
5 | "reason": "",
6 | "sessionId": "test_session_id",
7 | "applicationId": "test_application_id",
8 | "createdAt": 1727870434974,
9 | "size": 0,
10 | "duration": 0,
11 | "outputMode": "composed",
12 | "streamMode": "manual",
13 | "hasAudio": true,
14 | "hasVideo": true,
15 | "hasTranscription": false,
16 | "sha256sum": "",
17 | "password": "",
18 | "updatedAt": 1727870434977,
19 | "multiArchiveTag": "my-multi-archive",
20 | "event": "archive",
21 | "resolution": "1280x720",
22 | "url": null,
23 | "maxBitrate": 2000000,
24 | "quantizationParameter": 25
25 | }
--------------------------------------------------------------------------------
/users/src/vonage_users/__init__.py:
--------------------------------------------------------------------------------
1 | from .common import (
2 | Channels,
3 | MessengerChannel,
4 | MmsChannel,
5 | Properties,
6 | PstnChannel,
7 | SipChannel,
8 | SmsChannel,
9 | User,
10 | VbcChannel,
11 | ViberChannel,
12 | WebsocketChannel,
13 | WhatsappChannel,
14 | )
15 | from .requests import ListUsersFilter
16 | from .responses import UserSummary
17 | from .users import Users
18 |
19 | __all__ = [
20 | 'User',
21 | 'PstnChannel',
22 | 'SipChannel',
23 | 'WebsocketChannel',
24 | 'VbcChannel',
25 | 'SmsChannel',
26 | 'MmsChannel',
27 | 'WhatsappChannel',
28 | 'ViberChannel',
29 | 'MessengerChannel',
30 | 'Channels',
31 | 'Properties',
32 | 'ListUsersFilter',
33 | 'UserSummary',
34 | 'Users',
35 | ]
36 |
--------------------------------------------------------------------------------
/sms/README.md:
--------------------------------------------------------------------------------
1 | # Vonage SMS Package
2 |
3 | This package contains the code to use Vonage's SMS API in Python.
4 |
5 | It includes a method for sending SMS messages and returns an `SmsResponse` class to handle the response.
6 |
7 | ## Usage
8 |
9 | It is recommended to use this as part of the main `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`.
10 |
11 | ### Send an SMS
12 |
13 | Create an `SmsMessage` object, then pass into the `Sms.send` method.
14 |
15 | ```python
16 | from vonage_sms import SmsMessage, SmsResponse
17 |
18 | message = SmsMessage(to='1234567890', from_='Acme Inc.', text='Hello, World!')
19 | response: SmsResponse = vonage_client.sms.send(message)
20 |
21 | print(response.model_dump(exclude_unset=True))
22 | ```
23 |
24 |
25 |
--------------------------------------------------------------------------------
/http_client/src/vonage_http_client/__init__.py:
--------------------------------------------------------------------------------
1 | from .auth import Auth
2 | from .errors import (
3 | AuthenticationError,
4 | FileStreamingError,
5 | ForbiddenError,
6 | HttpRequestError,
7 | InvalidAuthError,
8 | InvalidHttpClientOptionsError,
9 | JWTGenerationError,
10 | NotFoundError,
11 | RateLimitedError,
12 | ServerError,
13 | )
14 | from .http_client import HttpClient, HttpClientOptions
15 |
16 | __all__ = [
17 | 'Auth',
18 | 'AuthenticationError',
19 | 'FileStreamingError',
20 | 'ForbiddenError',
21 | 'HttpRequestError',
22 | 'InvalidAuthError',
23 | 'InvalidHttpClientOptionsError',
24 | 'JWTGenerationError',
25 | 'NotFoundError',
26 | 'RateLimitedError',
27 | 'ServerError',
28 | 'HttpClient',
29 | 'HttpClientOptions',
30 | ]
31 |
--------------------------------------------------------------------------------
/messages/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.5.0
2 | - Add an optional "failover" property to `vonage_messages.Messages.send`
3 |
4 | # 1.4.0
5 | - Make all models originally accessed by `vonage_messages.models.***` available at the top level of the package, i.e. `vonage_messages.***`
6 |
7 | # 1.3.0
8 | - Add support for API key/secret header authentication
9 | - Updated dependency versions
10 |
11 | # 1.2.3
12 | - Update dependency versions
13 |
14 | # 1.2.2
15 | - Support for Python 3.13, drop support for 3.8
16 |
17 | # 1.2.1
18 | - Add docstrings to data models
19 |
20 | # 1.2.0
21 | - Add RCS channel support
22 | - Add methods to revoke an RCS message and mark a WhatsApp message as read
23 |
24 | # 1.1.1
25 | - Update minimum dependency version
26 |
27 | # 1.1.0
28 | - Add `http_client` property
29 |
30 | # 1.0.0
31 | - Initial upload
32 |
--------------------------------------------------------------------------------
/verify/src/vonage_verify/responses.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class StartVerificationResponse(BaseModel):
7 | """Model for the response of a start verification request.
8 |
9 | Args:
10 | request_id (str): The request ID.
11 | check_url (str, Optional): URL for Silent Authentication Verify workflow
12 | completion (only shows if using Silent Auth).
13 | """
14 |
15 | request_id: str
16 | check_url: Optional[str] = None
17 |
18 |
19 | class CheckCodeResponse(BaseModel):
20 | """Model for the response of a check code request.
21 |
22 | Args:
23 | request_id (str): The request ID.
24 | status (str): The status of the verification request.
25 | """
26 |
27 | request_id: str
28 | status: str
29 |
--------------------------------------------------------------------------------
/video/tests/data/stop_archive.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "e05d6f8f-2280-4025-b1d2-defc4f5c8dfa",
3 | "status": "stopped",
4 | "name": "archive test",
5 | "reason": "user initiated",
6 | "sessionId": "2_MX4yOWY3NjBmOC03Y2UxLTQ2YzktYWRlMy1mMmRlZGVlNGVkNWZ-fjE3Mjc4NzcyMTYwNzJ-OUJ1WHN0V05vN0NoU044OGthaURwNmpxfn5-",
7 | "applicationId": "29f760f8-7ce1-46c9-ade3-f2dedee4ed5f",
8 | "createdAt": 1727887464000,
9 | "size": 0,
10 | "duration": 0,
11 | "outputMode": "composed",
12 | "streamMode": "auto",
13 | "hasAudio": true,
14 | "hasVideo": true,
15 | "hasTranscription": false,
16 | "sha256sum": "",
17 | "password": "",
18 | "updatedAt": 1727887464000,
19 | "multiArchiveTag": "start-to-stop",
20 | "event": "archive",
21 | "resolution": "1280x720",
22 | "url": null
23 | }
--------------------------------------------------------------------------------
/video/tests/data/create_session.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "session_id": "1_MX4yOWY3NjBmOC03Y2UxLTQ2YzktYWRlMy1mMmRlZGVlNGVkNWZ-fjE3MjY0NjI1ODg2NDd-MTF4TGExYmJoelBlR1FHbVhzbWd4STBrfn5-",
4 | "project_id": "29f760f8-7ce1-46c9-ade3-f2dedee4ed5f",
5 | "partner_id": "29f760f8-7ce1-46c9-ade3-f2dedee4ed5f",
6 | "create_dt": "Sun Sep 15 21:56:28 PDT 2024",
7 | "session_status": null,
8 | "status_invalid": null,
9 | "media_server_hostname": null,
10 | "messaging_server_url": null,
11 | "messaging_url": null,
12 | "symphony_address": null,
13 | "properties": null,
14 | "ice_server": null,
15 | "session_segment_id": "35308566-4012-4c1e-90f7-cc15b5a390fe",
16 | "ice_servers": null,
17 | "ice_credential_expiration": 86100
18 | }
19 | ]
--------------------------------------------------------------------------------
/vonage/src/vonage/__init__.py:
--------------------------------------------------------------------------------
1 | from vonage_utils import VonageError
2 |
3 | from .vonage import (
4 | Account,
5 | Application,
6 | Auth,
7 | HttpClientOptions,
8 | Messages,
9 | NetworkNumberVerification,
10 | NetworkSimSwap,
11 | NumberInsight,
12 | Numbers,
13 | Sms,
14 | Subaccounts,
15 | Users,
16 | Verify,
17 | VerifyLegacy,
18 | Video,
19 | Voice,
20 | Vonage,
21 | )
22 |
23 | __all__ = [
24 | 'Account',
25 | 'Application',
26 | 'Auth',
27 | 'HttpClientOptions',
28 | 'Messages',
29 | 'NetworkSimSwap',
30 | 'NetworkNumberVerification',
31 | 'NumberInsight',
32 | 'Numbers',
33 | 'Sms',
34 | 'Subaccounts',
35 | 'Users',
36 | 'Verify',
37 | 'VerifyLegacy',
38 | 'Video',
39 | 'Voice',
40 | 'Vonage',
41 | 'VonageError',
42 | ]
43 |
--------------------------------------------------------------------------------
/number_management/tests/data/search_available_numbers_basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 8353,
3 | "numbers": [
4 | {
5 | "country": "GB",
6 | "msisdn": "442039050911",
7 | "cost": "1.00",
8 | "type": "landline",
9 | "features": [
10 | "VOICE"
11 | ]
12 | },
13 | {
14 | "country": "GB",
15 | "msisdn": "442039051911",
16 | "cost": "1.00",
17 | "type": "landline",
18 | "features": [
19 | "VOICE"
20 | ]
21 | },
22 | {
23 | "country": "GB",
24 | "msisdn": "442039052911",
25 | "cost": "1.00",
26 | "type": "landline",
27 | "features": [
28 | "VOICE"
29 | ]
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/jwt/src/vonage_jwt/verify_jwt.py:
--------------------------------------------------------------------------------
1 | from jwt import InvalidSignatureError, decode
2 |
3 | from .errors import VonageVerifyJwtError
4 |
5 |
6 | def verify_signature(token: str, signature_secret: str = None) -> bool:
7 | """Method to verify that an incoming JWT was sent by Vonage.
8 |
9 | Args:
10 | token (str): The token to verify.
11 | signature_secret (str, optional): The signature to verify the token against.
12 |
13 | Returns:
14 | bool: True if the token is verified, False otherwise.
15 |
16 | Raises:
17 | VonageVerifyJwtError: The signature could not be verified.
18 | """
19 |
20 | try:
21 | decode(token, signature_secret, algorithms='HS256')
22 | return True
23 | except InvalidSignatureError:
24 | return False
25 | except Exception as e:
26 | raise VonageVerifyJwtError(repr(e))
27 |
--------------------------------------------------------------------------------
/jwt/tests/test_verify_jwt.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from vonage_jwt.errors import VonageVerifyJwtError
3 | from vonage_jwt.verify_jwt import verify_signature
4 |
5 | token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2OTc2MzQ2ODAsImV4cCI6MzMyNTQ1NDA4MjgsImF1ZCI6IiIsInN1YiI6IiJ9.88vJc3I2HhuqEDixHXVhc9R30tA6U_HQHZTC29y6CGM'
6 | valid_signature = "qwertyuiopasdfghjklzxcvbnm123456"
7 | invalid_signature = 'asdf'
8 |
9 |
10 | def test_verify_signature_valid():
11 | assert verify_signature(token, valid_signature) is True
12 |
13 |
14 | def test_verify_signature_invalid():
15 | assert verify_signature(token, invalid_signature) is False
16 |
17 |
18 | def test_verify_signature_error():
19 | with pytest.raises(VonageVerifyJwtError) as e:
20 | verify_signature('asdf', valid_signature)
21 | assert 'DecodeError' in str(e.value)
22 |
--------------------------------------------------------------------------------
/subaccounts/tests/data/list_balance_transfers.json:
--------------------------------------------------------------------------------
1 | {
2 | "_links": {
3 | "self": {
4 | "href": "/accounts/test_api_key/balance-transfers"
5 | }
6 | },
7 | "_embedded": {
8 | "balance_transfers": [
9 | {
10 | "from": "test_api_key",
11 | "to": "asdfqwer",
12 | "amount": 0.01,
13 | "reference": "",
14 | "id": "6917b0ae-aed3-453c-a918-e37f6ef7b21a",
15 | "created_at": "2023-12-22T19:41:19.000Z"
16 | },
17 | {
18 | "from": "test_api_key",
19 | "to": "asdfqwer",
20 | "amount": 0.5,
21 | "reference": "",
22 | "id": "049adc07-5da1-4d13-bacd-0ee6a99ef948",
23 | "created_at": "2023-12-22T19:40:36.000Z"
24 | }
25 | ]
26 | }
27 | }
--------------------------------------------------------------------------------
/subaccounts/tests/data/list_credit_transfers.json:
--------------------------------------------------------------------------------
1 | {
2 | "_links": {
3 | "self": {
4 | "href": "/accounts/test_api_key/balance-transfers"
5 | }
6 | },
7 | "_embedded": {
8 | "credit_transfers": [
9 | {
10 | "from": "test_api_key",
11 | "to": "asdfqwer",
12 | "amount": 0.01,
13 | "reference": "",
14 | "id": "6917b0ae-aed3-453c-a918-e37f6ef7b21a",
15 | "created_at": "2023-12-22T19:41:19.000Z"
16 | },
17 | {
18 | "from": "test_api_key",
19 | "to": "asdfqwer",
20 | "amount": 0.5,
21 | "reference": "",
22 | "id": "049adc07-5da1-4d13-bacd-0ee6a99ef948",
23 | "created_at": "2023-12-22T19:40:36.000Z"
24 | }
25 | ]
26 | }
27 | }
--------------------------------------------------------------------------------
/messages/src/vonage_messages/models/enums.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class MessageType(str, Enum):
5 | """The type of message."""
6 |
7 | TEXT = 'text'
8 | IMAGE = 'image'
9 | AUDIO = 'audio'
10 | VIDEO = 'video'
11 | FILE = 'file'
12 | TEMPLATE = 'template'
13 | STICKER = 'sticker'
14 | CUSTOM = 'custom'
15 | VCARD = 'vcard'
16 |
17 |
18 | class ChannelType(str, Enum):
19 | """The channel used to send a message."""
20 |
21 | SMS = 'sms'
22 | MMS = 'mms'
23 | RCS = 'rcs'
24 | WHATSAPP = 'whatsapp'
25 | MESSENGER = 'messenger'
26 | VIBER = 'viber_service'
27 |
28 |
29 | class WebhookVersion(str, Enum):
30 | """Which version of the Messages API will be used to send Status Webhook messages."""
31 |
32 | V0_1 = 'v0.1'
33 | V1 = 'v1'
34 |
35 |
36 | class EncodingType(str, Enum):
37 | TEXT = 'text'
38 | UNICODE = 'unicode'
39 | AUTO = 'auto'
40 |
--------------------------------------------------------------------------------
/subaccounts/src/vonage_subaccounts/__init__.py:
--------------------------------------------------------------------------------
1 | from .errors import InvalidSecretError
2 | from .requests import (
3 | ListTransfersFilter,
4 | ModifySubaccountOptions,
5 | SubaccountOptions,
6 | TransferNumberRequest,
7 | TransferRequest,
8 | )
9 | from .responses import (
10 | ListSubaccountsResponse,
11 | NewSubaccount,
12 | PrimaryAccount,
13 | Subaccount,
14 | Transfer,
15 | TransferNumberResponse,
16 | VonageAccount,
17 | )
18 | from .subaccounts import Subaccounts
19 |
20 | __all__ = [
21 | 'Subaccounts',
22 | 'InvalidSecretError',
23 | 'ListTransfersFilter',
24 | 'SubaccountOptions',
25 | 'ModifySubaccountOptions',
26 | 'TransferNumberRequest',
27 | 'TransferRequest',
28 | 'VonageAccount',
29 | 'PrimaryAccount',
30 | 'Subaccount',
31 | 'ListSubaccountsResponse',
32 | 'NewSubaccount',
33 | 'Transfer',
34 | 'TransferNumberResponse',
35 | ]
36 |
--------------------------------------------------------------------------------
/number_insight/src/vonage_number_insight/__init__.py:
--------------------------------------------------------------------------------
1 | from . import errors
2 | from .number_insight import NumberInsight
3 | from .requests import (
4 | AdvancedAsyncInsightRequest,
5 | AdvancedSyncInsightRequest,
6 | BasicInsightRequest,
7 | StandardInsightRequest,
8 | )
9 | from .responses import (
10 | AdvancedAsyncInsightResponse,
11 | AdvancedSyncInsightResponse,
12 | BasicInsightResponse,
13 | CallerIdentity,
14 | Carrier,
15 | RoamingStatus,
16 | StandardInsightResponse,
17 | )
18 |
19 | __all__ = [
20 | 'NumberInsight',
21 | 'BasicInsightRequest',
22 | 'StandardInsightRequest',
23 | 'AdvancedAsyncInsightRequest',
24 | 'AdvancedSyncInsightRequest',
25 | 'BasicInsightResponse',
26 | 'CallerIdentity',
27 | 'Carrier',
28 | 'RoamingStatus',
29 | 'StandardInsightResponse',
30 | 'AdvancedSyncInsightResponse',
31 | 'AdvancedAsyncInsightResponse',
32 | 'errors',
33 | ]
34 |
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/types.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated
2 |
3 | from pydantic import Field
4 |
5 | PhoneNumber = Annotated[str, Field(pattern=r'^[1-9]\d{6,14}$')]
6 | """A phone number, which must be between 7 and 15 digits long and not start with 0. Don't
7 | use a leading `+` or `00` in the number. For example, use `447700900000` instead of
8 | `+447700900000` or `00447700900000`.
9 |
10 | Examples:
11 | - `447700900000`
12 | - `14155552671`
13 | """
14 |
15 | Dtmf = Annotated[str, Field(pattern=r'^[0-9#*p]+$')]
16 | """A string of DTMF (Dual-Tone Multi-Frequency) tones. The string can contain the digits
17 | 0-9, the symbols `#`, `*`, and `p`. The `p` symbol represents a pause of 500ms.
18 |
19 | Examples:
20 | - `1234#*`
21 | - `1p2p3p4`
22 | """
23 |
24 | SipUri = Annotated[str, Field(pattern=r'^(sip|sips):\+?([\w|:.\-@;,=%&]+)')]
25 | """A SIP URI, which must start with `sip:` or `sips:` and contain a valid SIP address."""
26 |
--------------------------------------------------------------------------------
/application/src/vonage_application/requests.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 |
5 | from .common import ApplicationBase
6 |
7 |
8 | class ListApplicationsFilter(BaseModel):
9 | """Request object for filtering applications.
10 |
11 | Args:
12 | page_size (int, Optional): The number of applications to return per page.
13 | page (int, Optional): The page number to return.
14 | """
15 |
16 | page_size: Optional[int] = 100
17 | page: int = None
18 |
19 |
20 | class ApplicationConfig(ApplicationBase):
21 | """Application object used in requests when communicating with the Vonage Application
22 | API.
23 |
24 | Args:
25 | name (str): The name of the application.
26 | capabilities (Capabilities, Optional): The capabilities of the application.
27 | privacy (Privacy, Optional): The privacy settings for the application.
28 | keys (Keys, Optional): The application keys.
29 | """
30 |
--------------------------------------------------------------------------------
/messages/src/vonage_messages/models/base_message.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel, Field
4 | from vonage_utils.types import PhoneNumber
5 |
6 | from .enums import WebhookVersion
7 |
8 |
9 | class BaseMessage(BaseModel):
10 | """Model with base properties for a message.
11 |
12 | Args:
13 | to (PhoneNumber): The recipient's phone number in E.164 format. Don't use a leading plus sign.
14 | client_ref (str, Optional): An optional client reference.
15 | webhook_url (str, Optional): The URL to which Status Webhook messages will be sent for this particular message.
16 | webhook_version (WebhookVersion, Optional): Which version of the Messages API will be used to send Status Webhook messages for this particular message.
17 | """
18 |
19 | to: PhoneNumber
20 | client_ref: Optional[str] = Field(None, max_length=100)
21 | webhook_url: Optional[str] = None
22 | webhook_version: Optional[WebhookVersion] = None
23 |
--------------------------------------------------------------------------------
/verify_legacy/tests/data/search_request.json:
--------------------------------------------------------------------------------
1 | {
2 | "request_id": "cc121958d8fb4368aa3bb762bb9a0f74",
3 | "account_id": "abcdef01",
4 | "status": "EXPIRED",
5 | "number": "1234567890",
6 | "price": "0",
7 | "currency": "EUR",
8 | "sender_id": "Acme Inc.",
9 | "date_submitted": "2024-04-03 02:22:37",
10 | "date_finalized": "2024-04-03 02:27:38",
11 | "first_event_date": "2024-04-03 02:22:37",
12 | "last_event_date": "2024-04-03 02:24:38",
13 | "checks": [
14 | {
15 | "date_received": "2024-04-03 02:23:04",
16 | "code": "1234",
17 | "status": "INVALID",
18 | "ip_address": ""
19 | }
20 | ],
21 | "events": [
22 | {
23 | "type": "sms",
24 | "id": "23f3a13d-6d03-4262-8f4d-67f12a56e1c8"
25 | },
26 | {
27 | "type": "sms",
28 | "id": "09ef3984-3f62-453d-8f9c-1a161b373dba"
29 | }
30 | ],
31 | "estimated_price_messages_sent": "0.09350"
32 | }
--------------------------------------------------------------------------------
/vonage_utils/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-utils'
3 | dynamic = ["version"]
4 | description = 'Utils package containing objects for use with Vonage APIs'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | dependencies = ["pydantic>=2.9.2"]
8 | requires-python = ">=3.9"
9 | classifiers = [
10 | "Programming Language :: Python",
11 | "Programming Language :: Python :: 3",
12 | "Programming Language :: Python :: 3.9",
13 | "Programming Language :: Python :: 3.10",
14 | "Programming Language :: Python :: 3.11",
15 | "Programming Language :: Python :: 3.12",
16 | "Programming Language :: Python :: 3.13",
17 | "License :: OSI Approved :: Apache Software License",
18 | ]
19 |
20 | [project.urls]
21 | Homepage = "https://github.com/Vonage/vonage-python-sdk"
22 |
23 | [tool.setuptools.dynamic]
24 | version = { attr = "vonage_utils._version.__version__" }
25 |
26 | [build-system]
27 | requires = ["setuptools>=61.0", "wheel"]
28 | build-backend = "setuptools.build_meta"
29 |
--------------------------------------------------------------------------------
/jwt/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "vonage-jwt"
3 | dynamic = ["version"]
4 | description = "Tooling for working with JWTs for Vonage APIs in Python."
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = ["vonage-utils>=1.1.4", "pyjwt[crypto]>=1.6.4"]
9 | classifiers = [
10 | "Programming Language :: Python",
11 | "Programming Language :: Python :: 3",
12 | "Programming Language :: Python :: 3.9",
13 | "Programming Language :: Python :: 3.10",
14 | "Programming Language :: Python :: 3.11",
15 | "Programming Language :: Python :: 3.12",
16 | "Programming Language :: Python :: 3.13",
17 | "License :: OSI Approved :: Apache Software License",
18 | ]
19 |
20 | [project.urls]
21 | Homepage = "https://github.com/Vonage/vonage-python-sdk"
22 |
23 | [tool.setuptools.dynamic]
24 | version = { attr = "vonage_jwt._version.__version__" }
25 |
26 | [build-system]
27 | requires = ["setuptools>=61.0", "wheel"]
28 | build-backend = "setuptools.build_meta"
29 |
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/models.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class Link(BaseModel):
7 | """Model for a link object.
8 |
9 | Args:
10 | href (str): The URL of the link.
11 | """
12 |
13 | href: str
14 |
15 |
16 | class ResourceLink(BaseModel):
17 | """Model for a resource link object.
18 |
19 | Args:
20 | self (Link): The self link of the resource.
21 | """
22 |
23 | self: Link
24 |
25 |
26 | class HalLinks(BaseModel):
27 | """Model for links following a version of the HAL standard.
28 |
29 | Args:
30 | self (Link): The self link.
31 | first (Link, Optional): The first link.
32 | last (Link, Optional): The last link.
33 | prev (Link, Optional): The previous link.
34 | next (Link, Optional): The next link.
35 | """
36 |
37 | self: Link
38 | first: Optional[Link] = None
39 | last: Optional[Link] = None
40 | prev: Optional[Link] = None
41 | next: Optional[Link] = None
42 |
--------------------------------------------------------------------------------
/video/tests/data/archive_with_transcription.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "5b1521e6-115f-4efd-bed9-e527b87f0699",
3 | "status": "available",
4 | "name": "archive with transcription",
5 | "reason": "session ended",
6 | "sessionId": "test_session_id",
7 | "applicationId": "test_application_id",
8 | "createdAt": 1727870434974,
9 | "size": 1048576,
10 | "duration": 180,
11 | "outputMode": "individual",
12 | "streamMode": "auto",
13 | "hasAudio": true,
14 | "hasVideo": true,
15 | "hasTranscription": true,
16 | "sha256sum": "abc123def456",
17 | "password": "",
18 | "updatedAt": 1727870634977,
19 | "multiArchiveTag": "",
20 | "event": "archive",
21 | "resolution": "1280x720",
22 | "url": "https://example.com/archive.mp4",
23 | "transcription": {
24 | "status": "completed",
25 | "reason": "transcription completed successfully",
26 | "url": "https://example.com/transcription.json",
27 | "primaryLanguageCode": "en-US",
28 | "hasSummary": true
29 | }
30 | }
--------------------------------------------------------------------------------
/sms/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-sms'
3 | dynamic = ["version"]
4 | description = 'Vonage SMS package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_sms._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/users/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-users'
3 | dynamic = ["version"]
4 | description = 'Vonage Users package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_users._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/video/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-video'
3 | dynamic = ["version"]
4 | description = 'Vonage video package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_video._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/voice/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-voice'
3 | dynamic = ["version"]
4 | description = 'Vonage voice package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_voice._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/verify/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-verify'
3 | dynamic = ["version"]
4 | description = 'Vonage verify package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_verify._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/account/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-account'
3 | dynamic = ["version"]
4 | description = 'Vonage Account API package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_account._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/messages/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-messages'
3 | dynamic = ["version"]
4 | description = 'Vonage messages package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.8",
17 | "Programming Language :: Python :: 3.9",
18 | "Programming Language :: Python :: 3.10",
19 | "Programming Language :: Python :: 3.11",
20 | "Programming Language :: Python :: 3.12",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_messages._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/number_management/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-numbers'
3 | dynamic = ["version"]
4 | description = 'Vonage Numbers package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_numbers._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/vonage_utils/README.md:
--------------------------------------------------------------------------------
1 | # Vonage Utils Package
2 |
3 | This package contains utility code that is used by the Vonage Python SDK and other related packages.
4 |
5 | The utils module provides two utility functions: `format_phone_number` and `remove_none_values`. It also exposes the `VonageError` type that other exceptions related to Vonage SDK inherit from. This can also be accessed via the main SDK module with `vonage.VonageError`.
6 |
7 | ## Usage
8 |
9 | ```python
10 | from utils import format_phone_number, remove_none_values
11 |
12 | # Use format_phone_number
13 | try:
14 | formatted_number = format_phone_number('123-456-7890')
15 | print(formatted_number)
16 | except (InvalidPhoneNumberError, InvalidPhoneNumberTypeError) as e:
17 | print(e)
18 |
19 | # Use remove_none_values to remove null values from a Vonage API response when converting to a dictionary with the `asdict` method
20 | from dataclasses import asdict
21 |
22 | vonage_api_response = vonage.api.method()
23 | cleaned_dict = asdict(my_dataclass, dict_factory=remove_none_values)
24 | print(cleaned_dict)
25 | ```
--------------------------------------------------------------------------------
/application/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-application'
3 | dynamic = ["version"]
4 | description = 'Vonage Application API package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_application._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/application/src/vonage_application/__init__.py:
--------------------------------------------------------------------------------
1 | from . import errors
2 | from .application import Application
3 | from .common import (
4 | ApplicationUrl,
5 | Capabilities,
6 | Keys,
7 | Messages,
8 | MessagesWebhooks,
9 | Privacy,
10 | Rtc,
11 | RtcWebhooks,
12 | Vbc,
13 | Verify,
14 | VerifyWebhooks,
15 | Voice,
16 | VoiceUrl,
17 | VoiceWebhooks,
18 | )
19 | from .enums import Region
20 | from .requests import ApplicationConfig, ListApplicationsFilter
21 | from .responses import ApplicationData, ListApplicationsResponse
22 |
23 | __all__ = [
24 | 'Application',
25 | 'ApplicationConfig',
26 | 'ApplicationData',
27 | 'ApplicationUrl',
28 | 'Capabilities',
29 | 'Keys',
30 | 'ListApplicationsFilter',
31 | 'ListApplicationsResponse',
32 | 'Messages',
33 | 'MessagesWebhooks',
34 | 'Privacy',
35 | 'Region',
36 | 'Rtc',
37 | 'RtcWebhooks',
38 | 'Vbc',
39 | 'Verify',
40 | 'VerifyWebhooks',
41 | 'Voice',
42 | 'VoiceUrl',
43 | 'VoiceWebhooks',
44 | 'errors',
45 | ]
46 |
--------------------------------------------------------------------------------
/http_client/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.5.1
2 | - Remove unnecessary `Content-Type` check on error
3 |
4 | # 1.5.0
5 | - Add new `HttpClient.download_file_stream` method
6 | - Add new `FileStreamingError` exception type
7 | - Add backoff exponential timeout increase for HTTP request retries
8 | - Add retries for `RemoteDisconnected` exceptions
9 |
10 | # 1.4.3
11 | - Update JWT dependency version
12 |
13 | # 1.4.2
14 | - Support for Python 3.13, drop support for 3.8
15 |
16 | # 1.4.1
17 | - Add docstrings to data models
18 |
19 | # 1.4.0
20 | - Add new `oauth2` logic for calling APIs that require Oauth
21 |
22 | # 1.3.1
23 | - Update minimum dependency version
24 |
25 | # 1.3.0
26 | - Add new PUT method
27 |
28 | # 1.2.1
29 | - Expose classes and errors at the package level
30 |
31 | # 1.2.0
32 | - Add `last_request` and `last_response` properties
33 | - Add new `Forbidden` error
34 |
35 | # 1.1.1
36 | - Add new Patch method
37 | - New input fields for different ways to pass data in a request
38 |
39 | # 1.1.0
40 | - Add support for signature authentication
41 |
42 | # 1.0.0
43 | - Initial upload
44 |
--------------------------------------------------------------------------------
/subaccounts/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-subaccounts'
3 | dynamic = ["version"]
4 | description = 'Vonage Subaccounts API package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_subaccounts._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/network_auth/src/vonage_network_auth/responses.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class OidcResponse(BaseModel):
7 | """Model for an OpenID Connect response.
8 |
9 | Args:
10 | auth_req_id (str): The authentication request ID.
11 | expires_in (int): The time in seconds until the authentication code expires.
12 | interval (int, Optional): The time in seconds until the next request can be made.
13 | """
14 |
15 | auth_req_id: str
16 | expires_in: int
17 | interval: Optional[int] = None
18 |
19 |
20 | class TokenResponse(BaseModel):
21 | """Model for a token response.
22 |
23 | Args:
24 | access_token (str): The access token.
25 | token_type (str, Optional): The token type.
26 | refresh_token (str, Optional): The refresh token.
27 | expires_in (int, Optional): The time until the token expires.
28 | """
29 |
30 | access_token: str
31 | token_type: Optional[str] = None
32 | refresh_token: Optional[str] = None
33 | expires_in: Optional[int] = None
34 |
--------------------------------------------------------------------------------
/verify_legacy/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-verify-legacy'
3 | dynamic = ["version"]
4 | description = 'Vonage legacy verify package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_verify_legacy._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/number_insight/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = 'vonage-number-insight'
3 | dynamic = ["version"]
4 | description = 'Vonage Number Insight package'
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_number_insight._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/users/src/vonage_users/requests.py:
--------------------------------------------------------------------------------
1 | from typing import Literal, Optional
2 |
3 | from pydantic import BaseModel, Field
4 |
5 |
6 | class ListUsersFilter(BaseModel):
7 | """Request object for listing users.
8 |
9 | Args:
10 | page_size (int, Optional): The number of users to return per response.
11 | order (str, Optional): Return the records in ascending or descending order.
12 | cursor (str, Optional): The cursor to start returning results from. You must
13 | follow the url provided in the response tuple which contains a cursor value.
14 | name (str, Optional): The name of the user to filter by.
15 | """
16 |
17 | page_size: Optional[int] = Field(100, ge=1, le=100)
18 | order: Optional[Literal['asc', 'desc', 'ASC', 'DESC']] = None
19 | cursor: Optional[str] = Field(
20 | None,
21 | description="The cursor to start returning results from. You are not expected to provide this manually, but to follow the url provided in _links.next.href or _links.prev.href in the response which contains a cursor value.",
22 | )
23 | name: Optional[str] = None
24 |
--------------------------------------------------------------------------------
/network_auth/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "vonage-network-auth"
3 | dynamic = ["version"]
4 | description = "Package for working with Network APIs that require Oauth2 in Python."
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-utils>=1.1.4",
11 | "pydantic>=2.9.2",
12 | ]
13 | classifiers = [
14 | "Programming Language :: Python",
15 | "Programming Language :: Python :: 3",
16 | "Programming Language :: Python :: 3.9",
17 | "Programming Language :: Python :: 3.10",
18 | "Programming Language :: Python :: 3.11",
19 | "Programming Language :: Python :: 3.12",
20 | "Programming Language :: Python :: 3.13",
21 | "License :: OSI Approved :: Apache Software License",
22 | ]
23 |
24 | [project.urls]
25 | Homepage = "https://github.com/Vonage/vonage-python-sdk"
26 |
27 | [tool.setuptools.dynamic]
28 | version = { attr = "vonage_network_auth._version.__version__" }
29 |
30 | [build-system]
31 | requires = ["setuptools>=61.0", "wheel"]
32 | build-backend = "setuptools.build_meta"
33 |
--------------------------------------------------------------------------------
/network_auth/README.md:
--------------------------------------------------------------------------------
1 | # Vonage Network API Authentication Client
2 |
3 | This package (`vonage-network-auth`) provides a client for authenticating Network APIs that require Oauth2 authentication. Using it, it is possible to generate authenticated JWTs for use with Vonage Network APIs, e.g. Sim Swap, Number Verification.
4 |
5 | This package is intended to be used as part of the `vonage` SDK package, accessing required methods through the SDK instead of directly. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK.
6 |
7 | For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com).
8 |
9 | ## Installation
10 |
11 | Install from the Python Package Index with pip:
12 |
13 | ```bash
14 | pip install vonage-network-auth
15 | ```
16 |
17 | ## Usage
18 |
19 | ### Create a `NetworkAuth` Object
20 |
21 | ```python
22 | from vonage_network_auth import NetworkAuth
23 | from vonage_http_client import HttpClient, Auth
24 |
25 | network_auth = NetworkAuth(HttpClient(Auth(application_id='application-id', private_key='private-key')))
26 | ```
27 |
28 |
--------------------------------------------------------------------------------
/http_client/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "vonage-http-client"
3 | dynamic = ["version"]
4 | description = "An HTTP client for making requests to Vonage APIs."
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-utils>=1.1.4",
10 | "vonage-jwt>=1.1.5",
11 | "requests>=2.27.0",
12 | "typing-extensions>=4.9.0",
13 | "pydantic>=2.9.2",
14 | ]
15 | classifiers = [
16 | "Programming Language :: Python",
17 | "Programming Language :: Python :: 3",
18 | "Programming Language :: Python :: 3.9",
19 | "Programming Language :: Python :: 3.10",
20 | "Programming Language :: Python :: 3.11",
21 | "Programming Language :: Python :: 3.12",
22 | "Programming Language :: Python :: 3.13",
23 | "License :: OSI Approved :: Apache Software License",
24 | ]
25 |
26 | [project.urls]
27 | Homepage = "https://github.com/Vonage/vonage-python-sdk"
28 |
29 | [tool.setuptools.dynamic]
30 | version = { attr = "vonage_http_client._version.__version__" }
31 |
32 | [build-system]
33 | requires = ["setuptools>=61.0", "wheel"]
34 | build-backend = "setuptools.build_meta"
35 |
--------------------------------------------------------------------------------
/network_sim_swap/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "vonage-network-sim-swap"
3 | dynamic = ["version"]
4 | description = "Package for working with the Vonage Sim Swap Network API."
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-network-auth>=1.0.2",
11 | "vonage-utils>=1.1.4",
12 | "pydantic>=2.9.2",
13 | ]
14 | classifiers = [
15 | "Programming Language :: Python",
16 | "Programming Language :: Python :: 3",
17 | "Programming Language :: Python :: 3.9",
18 | "Programming Language :: Python :: 3.10",
19 | "Programming Language :: Python :: 3.11",
20 | "Programming Language :: Python :: 3.12",
21 | "Programming Language :: Python :: 3.13",
22 | "License :: OSI Approved :: Apache Software License",
23 | ]
24 |
25 | [project.urls]
26 | Homepage = "https://github.com/Vonage/vonage-python-sdk"
27 |
28 | [tool.setuptools.dynamic]
29 | version = { attr = "vonage_network_sim_swap._version.__version__" }
30 |
31 | [build-system]
32 | requires = ["setuptools>=61.0", "wheel"]
33 | build-backend = "setuptools.build_meta"
34 |
--------------------------------------------------------------------------------
/network_number_verification/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "vonage-network-number-verification"
3 | dynamic = ["version"]
4 | description = "Package for working with the Vonage Number Verification Network API."
5 | readme = "README.md"
6 | authors = [{ name = "Vonage", email = "devrel@vonage.com" }]
7 | requires-python = ">=3.9"
8 | dependencies = [
9 | "vonage-http-client>=1.5.0",
10 | "vonage-network-auth>=1.0.2",
11 | "vonage-utils>=1.1.4",
12 | "pydantic>=2.9.2",
13 | ]
14 | classifiers = [
15 | "Programming Language :: Python",
16 | "Programming Language :: Python :: 3",
17 | "Programming Language :: Python :: 3.9",
18 | "Programming Language :: Python :: 3.10",
19 | "Programming Language :: Python :: 3.11",
20 | "Programming Language :: Python :: 3.12",
21 | "Programming Language :: Python :: 3.13",
22 | "License :: OSI Approved :: Apache Software License",
23 | ]
24 |
25 | [project.urls]
26 | Homepage = "https://github.com/Vonage/vonage-python-sdk"
27 |
28 | [tool.setuptools.dynamic]
29 | version = { attr = "vonage_network_number_verification._version.__version__" }
30 |
31 | [build-system]
32 | requires = ["setuptools>=61.0", "wheel"]
33 | build-backend = "setuptools.build_meta"
34 |
--------------------------------------------------------------------------------
/number_insight/tests/data/standard_insight.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": 0,
3 | "status_message": "Success",
4 | "request_id": "1d56406b-9d52-497a-a023-b3f40b62f9b3",
5 | "international_format_number": "447700900000",
6 | "national_format_number": "07700 900000",
7 | "country_code": "GB",
8 | "country_code_iso3": "GBR",
9 | "country_name": "United Kingdom",
10 | "country_prefix": "44",
11 | "request_price": "0.00500000",
12 | "remaining_balance": "32.98665294",
13 | "current_carrier": {
14 | "network_code": "23415",
15 | "name": "Vodafone Limited",
16 | "country": "GB",
17 | "network_type": "mobile"
18 | },
19 | "original_carrier": {
20 | "network_code": "23420",
21 | "name": "Hutchison 3G Ltd",
22 | "country": "GB",
23 | "network_type": "mobile"
24 | },
25 | "ported": "ported",
26 | "caller_identity": {
27 | "caller_type": "consumer",
28 | "caller_name": "John Smith",
29 | "first_name": "John",
30 | "last_name": "Smith"
31 | },
32 | "caller_name": "John Smith",
33 | "last_name": "Smith",
34 | "first_name": "John",
35 | "caller_type": "consumer"
36 | }
--------------------------------------------------------------------------------
/pants.toml:
--------------------------------------------------------------------------------
1 | [GLOBAL]
2 | pants_version = '2.26.0'
3 |
4 | backend_packages = [
5 | 'pants.backend.python',
6 | 'pants.backend.python.lint.autoflake',
7 | 'pants.backend.build_files.fmt.black',
8 | 'pants.backend.python.lint.isort',
9 | 'pants.backend.python.lint.black',
10 | 'pants.backend.python.lint.docformatter',
11 | 'pants.backend.tools.taplo',
12 | "pants.backend.experimental.python",
13 | ]
14 |
15 | pants_ignore.add = ['!_test_scripts/', '!_dev_scripts/']
16 |
17 | [anonymous-telemetry]
18 | enabled = false
19 |
20 | [source]
21 | root_patterns = ['/', 'src/', 'tests/']
22 |
23 | [python]
24 | interpreter_constraints = ['==3.13.*']
25 |
26 | [pytest]
27 | args = ['-vv', '--no-header']
28 |
29 | [coverage-py]
30 | interpreter_constraints = ['>=3.9']
31 | report = ['html', 'console']
32 |
33 | [black]
34 | args = ['--line-length=90', '--skip-string-normalization']
35 | interpreter_constraints = ['>=3.9']
36 |
37 | [isort]
38 | args = ['--profile=black', '--line-length=90']
39 | interpreter_constraints = ['>=3.9']
40 |
41 | [docformatter]
42 | args = ['--wrap-summaries=90', '--wrap-descriptions=90']
43 | interpreter_constraints = ['>=3.9']
44 |
45 | [autoflake]
46 | interpreter_constraints = ['>=3.9']
47 |
--------------------------------------------------------------------------------
/application/tests/data/get_application.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1b1b1b1b-1b1b-1b1b-1b1b-1b1b1b1b1b1b",
3 | "name": "My Server Demo",
4 | "keys": {
5 | "public_key": "-----BEGIN PUBLIC KEY-----\npublic_key_info_goes_here\n-----END PUBLIC KEY-----\n"
6 | },
7 | "privacy": {
8 | "improve_ai": false
9 | },
10 | "capabilities": {
11 | "voice": {
12 | "webhooks": {
13 | "event_url": {
14 | "address": "http://example.ngrok.app/webhooks/events",
15 | "http_method": "POST",
16 | "socket_timeout": 10000,
17 | "connect_timeout": 1000
18 | },
19 | "answer_url": {
20 | "address": "http://example.ngrok.app/webhooks/answer",
21 | "http_method": "GET",
22 | "socket_timeout": 5000,
23 | "connect_timeout": 1000
24 | }
25 | },
26 | "signed_callbacks": true,
27 | "conversations_ttl": 48,
28 | "leg_persistence_time": 7
29 | }
30 | },
31 | "_links": {
32 | "self": {
33 | "href": "/v2/applications/1b1b1b1b-1b1b-1b1b-1b1b-1b1b1b1b1b1b"
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/account/src/vonage_account/requests.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class ServiceType(str, Enum):
7 | """The service you wish to retrieve outbound pricing data about.
8 |
9 | Values:
10 | ```
11 | SMS: SMS
12 | SMS_TRANSIT: SMS transit
13 | VOICE: Voice
14 | ```
15 | """
16 |
17 | SMS = 'sms'
18 | SMS_TRANSIT = 'sms-transit'
19 | VOICE = 'voice'
20 |
21 |
22 | class GetCountryPricingRequest(BaseModel):
23 | """The options for getting the pricing for a specific country.
24 |
25 | Args:
26 | country_code (str): The two-letter country code for the country to retrieve
27 | pricing data about.
28 | type (ServiceType, Optional): The type of service to retrieve pricing data about.
29 | """
30 |
31 | country_code: str
32 | type: ServiceType = ServiceType.SMS
33 |
34 |
35 | class GetPrefixPricingRequest(BaseModel):
36 | """The options for getting the pricing for a specific prefix.
37 |
38 | Args:
39 | prefix (str): The numerical dialing prefix to look up pricing for, e.g. "1", "44".
40 | type (ServiceType, Optional): The type of service to retrieve pricing data about.
41 | """
42 |
43 | prefix: str
44 | type: ServiceType = ServiceType.SMS
45 |
--------------------------------------------------------------------------------
/video/tests/data/broadcast.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "f03fad17-4591-4422-8bd3-00a4df1e616a",
3 | "sessionId": "test_session_id",
4 | "applicationId": "test_application_id",
5 | "createdAt": 1728039361014,
6 | "broadcastUrls": {
7 | "rtmp": [
8 | {
9 | "status": "connecting",
10 | "id": "test",
11 | "serverUrl": "rtmp://a.rtmp.youtube.com/live2",
12 | "streamName": "stream-key"
13 | }
14 | ],
15 | "hls": "https://broadcast2-euw1-cdn.media.prod.tokbox.com/broadcast-57d6569497-dj9b2.10293/broadcast-57d6569497-dj9b2.10293_f03fad17-4591-4422-8bd3-00a4df1e616a_29f760f8-7ce1-46c9-ade3-f2dedee4ed5f.2_MX4yOWY3NjBmOC03Y2UxLTQ2YzktYWRlMy1mMmRlZGVlNGVkNWZ-fjE3MjgwMzY0MTUzMDd-V2swbzlzeUppaGZIVTFzYUQwamdYM0Ryfn5-.smil/playlist.m3u8?DVR"
16 | },
17 | "updatedAt": 1728039361511,
18 | "status": "started",
19 | "streamMode": "auto",
20 | "hasAudio": true,
21 | "hasVideo": true,
22 | "maxDuration": 3600,
23 | "multiBroadcastTag": "test-broadcast-5",
24 | "maxBitrate": 1000000,
25 | "settings": {
26 | "hls": {
27 | "lowLatency": false,
28 | "dvr": true
29 | }
30 | },
31 | "event": "broadcast",
32 | "resolution": "1280x720"
33 | }
--------------------------------------------------------------------------------
/vonage_utils/tests/test_format_phone_number.py:
--------------------------------------------------------------------------------
1 | from pytest import raises
2 | from vonage_utils.errors import InvalidPhoneNumberError, InvalidPhoneNumberTypeError
3 | from vonage_utils.utils import format_phone_number
4 |
5 |
6 | def test_format_phone_numbers():
7 | number = '1234567890'
8 | assert format_phone_number('1234567890') == number
9 | assert format_phone_number(1234567890) == number
10 | assert format_phone_number('+1234567890') == number
11 | assert format_phone_number('+ 1 234 567 890') == number
12 | assert format_phone_number('00 1 234 567 890') == number
13 | assert format_phone_number('00 1234567890') == number
14 | assert format_phone_number('447700900000') == '447700900000'
15 | assert format_phone_number('1234567') == '1234567'
16 | assert format_phone_number('123456789012345') == '123456789012345'
17 |
18 |
19 | def test_format_phone_number_invalid_type():
20 | number = ['1234567890']
21 | with raises(InvalidPhoneNumberTypeError) as e:
22 | format_phone_number(number)
23 |
24 | assert e.match('""')
25 |
26 |
27 | def test_format_phone_number_invalid_format():
28 | number = 'not a phone number'
29 | with raises(InvalidPhoneNumberError) as e:
30 | format_phone_number(number)
31 | assert e.match('"not a phone number"')
32 |
--------------------------------------------------------------------------------
/.github/workflows/mutation-test.yml:
--------------------------------------------------------------------------------
1 | name: Mutation Test
2 | on: workflow_dispatch
3 |
4 | permissions:
5 | actions: write
6 | checks: write
7 | contents: read
8 | deployments: read
9 | issues: write
10 | discussions: write
11 | packages: read
12 | pages: write
13 | pull-requests: write
14 | security-events: write
15 | statuses: write
16 |
17 | jobs:
18 | mutation:
19 | name: run mutation test
20 | runs-on: ubuntu-latest
21 | strategy:
22 | fail-fast: true
23 | matrix:
24 | python-version: ["3.10"]
25 |
26 | continue-on-error: true
27 |
28 | steps:
29 | - uses: actions/checkout@v4
30 | - name: Set up Python ${{ matrix.python-version }}
31 | uses: actions/setup-python@v5
32 | with:
33 | python-version: ${{ matrix.python-version }}
34 | - name: Install dependencies
35 | run: |
36 | python -m pip install --upgrade pip
37 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
38 | python -m pip install mutmut
39 | - name: Run mutation test
40 | run: |
41 | mutmut run --no-progress --CI
42 | - name: Save HTML output
43 | run: |
44 | mutmut html
45 | - uses: actions/upload-artifact@v3
46 | with:
47 | name: mutation-test-report
48 | path: html/
49 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on: [push, pull_request]
3 |
4 | permissions:
5 | actions: write
6 | checks: write
7 | contents: read
8 | deployments: read
9 | issues: write
10 | discussions: write
11 | packages: read
12 | pages: write
13 | pull-requests: write
14 | security-events: write
15 | statuses: write
16 |
17 | env:
18 | PANTS_CONFIG_FILES: "pants.ci.toml"
19 |
20 | jobs:
21 | test:
22 | name: Test
23 | runs-on: ${{ matrix.os }}
24 | strategy:
25 | fail-fast: false
26 | matrix:
27 | python: ["3.9", "3.10", "3.11", "3.12"]
28 | os: ["ubuntu-latest"]
29 | steps:
30 | - name: Clone repo
31 | uses: actions/checkout@v4
32 | - name: Setup python
33 | uses: actions/setup-python@v5
34 | with:
35 | python-version: ${{ matrix.python }}
36 | - name: Initialize pants
37 | uses: pantsbuild/actions/init-pants@main
38 | with:
39 | gha-cache-key: cache0-py${{ matrix.python }}
40 | named-caches-hash: ${{ hashFiles('requirements.txt') }}
41 | - name: Check BUILD files
42 | run: |
43 | pants tailor --check update-build-files --check ::
44 | - name: Lint
45 | run: |
46 | pants lint ::
47 | - name: Run tests
48 | run: |
49 | pants test --use-coverage ::
50 |
--------------------------------------------------------------------------------
/video/tests/data/list_broadcasts_next_page.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "items": [
4 | {
5 | "id": "32cd16ee-715b-4025-bbc6-f314c1459e2f",
6 | "sessionId": "test_session_id",
7 | "applicationId": "test_application_id",
8 | "createdAt": 1728038157850,
9 | "broadcastUrls": {
10 | "rtmp": [
11 | {
12 | "status": "offline",
13 | "id": "test",
14 | "serverUrl": "rtmp://a.rtmp.youtube.com/live2",
15 | "streamName": "stream-key"
16 | }
17 | ],
18 | "hlsStatus": "ready",
19 | "hls": "https://example.com/hls.m3u8"
20 | },
21 | "updatedAt": 1728038163321,
22 | "status": "started",
23 | "streamMode": "auto",
24 | "hasAudio": true,
25 | "hasVideo": true,
26 | "maxDuration": 3600,
27 | "multiBroadcastTag": "test-broadcast-1",
28 | "maxBitrate": 1000000,
29 | "settings": {
30 | "hls": {
31 | "lowLatency": false,
32 | "dvr": true
33 | }
34 | },
35 | "event": "broadcast",
36 | "resolution": "1280x720"
37 | }
38 | ]
39 | }
--------------------------------------------------------------------------------
/video/tests/test_signal.py:
--------------------------------------------------------------------------------
1 | from os.path import abspath
2 |
3 | import responses
4 | from vonage_http_client import HttpClient
5 | from vonage_video.models.signal import SignalData
6 | from vonage_video.video import Video
7 |
8 | from testutils import build_response, get_mock_jwt_auth
9 |
10 | path = abspath(__file__)
11 |
12 |
13 | video = Video(HttpClient(get_mock_jwt_auth()))
14 |
15 |
16 | @responses.activate
17 | def test_send_signal_all():
18 | build_response(
19 | path,
20 | 'POST',
21 | 'https://video.api.vonage.com/v2/project/test_application_id/session/test_session_id/signal',
22 | status_code=204,
23 | )
24 |
25 | video.send_signal(
26 | session_id='test_session_id', data=SignalData(type='msg', data='Hello, World!')
27 | )
28 |
29 | assert responses.calls[0].response.status_code == 204
30 |
31 |
32 | @responses.activate
33 | def test_send_signal_to_connection_id():
34 | build_response(
35 | path,
36 | 'POST',
37 | 'https://video.api.vonage.com/v2/project/test_application_id/session/test_session_id/connection/test_connection_id/signal',
38 | status_code=204,
39 | )
40 |
41 | video.send_signal(
42 | session_id='test_session_id',
43 | data=SignalData(type='msg', data='Hello, World!'),
44 | connection_id='test_connection_id',
45 | )
46 |
47 | assert responses.calls[0].response.status_code == 204
48 |
--------------------------------------------------------------------------------
/video/src/vonage_video/models/captions.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel, Field
4 |
5 | from .enums import LanguageCode
6 |
7 |
8 | class CaptionsOptions(BaseModel):
9 | """The Options to send captions.
10 |
11 | Args:
12 | session_id (str): The session ID.
13 | token (str): A valid token with moderation privileges.
14 | language_code (LanguageCode, Optional): The language code.
15 | max_duration (int, Optional): The maximum duration.
16 | partial_captions (bool, Optional): The partial captions.
17 | status_callback_url (str, Optional): The status callback URL.
18 | """
19 |
20 | session_id: str = Field(..., serialization_alias='sessionId')
21 | token: str
22 | language_code: Optional[LanguageCode] = Field(
23 | None, serialization_alias='languageCode'
24 | )
25 | max_duration: Optional[int] = Field(
26 | None, ge=300, le=14400, serialization_alias='maxDuration'
27 | )
28 | partial_captions: Optional[bool] = Field(None, serialization_alias='partialCaptions')
29 | status_callback_url: Optional[str] = Field(
30 | None, min_length=15, max_length=2048, serialization_alias='statusCallbackUrl'
31 | )
32 |
33 |
34 | class CaptionsData(BaseModel):
35 | """Class containing captions ID.
36 |
37 | Args:
38 | captions_id (str): The captions ID.
39 | """
40 |
41 | captions_id: str = Field(..., serialization_alias='captionsId')
42 |
--------------------------------------------------------------------------------
/subaccounts/tests/data/list_subaccounts.json:
--------------------------------------------------------------------------------
1 | {
2 | "_links": {
3 | "self": {
4 | "href": "/accounts/test_api_key/subaccounts"
5 | }
6 | },
7 | "total_balance": 29.6672,
8 | "total_credit_limit": 0.0000,
9 | "_embedded": {
10 | "primary_account": {
11 | "api_key": "test_api_key",
12 | "name": "SMPP Account",
13 | "balance": 27.4572,
14 | "credit_limit": 0.0000,
15 | "suspended": false,
16 | "created_at": "2024-08-28T02:02:14.626Z"
17 | },
18 | "subaccounts": [
19 | {
20 | "api_key": "qwer1234",
21 | "primary_account_api_key": "test_api_key",
22 | "use_primary_account_balance": false,
23 | "name": "second own balance subacct",
24 | "balance": 0.5,
25 | "credit_limit": 0.0000,
26 | "suspended": false,
27 | "created_at": "2023-06-07T10:50:44.000Z"
28 | },
29 | {
30 | "api_key": "1234qwer",
31 | "primary_account_api_key": "test_api_key",
32 | "use_primary_account_balance": false,
33 | "name": "own balance subaccount",
34 | "balance": 1.71,
35 | "credit_limit": 0.0000,
36 | "suspended": false,
37 | "created_at": "2023-06-09T13:52:43.000Z"
38 | }
39 | ]
40 | }
41 | }
--------------------------------------------------------------------------------
/voice/CHANGES.md:
--------------------------------------------------------------------------------
1 | # 1.4.0
2 | - Increase maximum value of call `length_timer` to 86400s
3 | - Add additional fields `eventUrl` and `eventMethod` to NCCO model
4 |
5 | # 1.3.0
6 | - Add new `headers` and `standard_headers` options to the `Sip` data model
7 | - Add new `standardHeaders` option to the `SipEndpoint` NCCO model
8 | - Add check for invalid hostnames when downloading a recording with `Voice.download_recording`
9 | - Allow the `CreateCallRequest` model to accept a SIP URI as well as a phone number in the `from_` field
10 |
11 | # 1.2.0
12 | - Make all models originally accessed by `vonage_voice.models.***` available at the top level of the package, i.e. `vonage_voice.***`
13 |
14 | # 1.1.2
15 | - Update incorrect return type annotation for `Voice.download_recording`
16 |
17 | # 1.1.1
18 | - Remove maximum webhook uri length constraint
19 |
20 | # 1.1.0
21 | - Add `Voice.get_recording` method to get call recordings
22 | - Add `Voice.verify_signature` method to expose the verification functionality from `vonage-jwt`
23 | - Updated dependency versions
24 |
25 | # 1.0.6
26 | - Update dependency versions
27 |
28 | # 1.0.5
29 | - Support for Python 3.13, drop support for 3.8
30 |
31 | # 1.0.4
32 | - Add docstrings to data models
33 |
34 | # 1.0.3
35 | - Internal refactoring
36 |
37 | # 1.0.2
38 | - Update minimum dependency version
39 |
40 | # 1.0.1
41 | - Initial upload
42 |
43 | # 1.0.0
44 | - This version was skipped due to a technical issue with the package distribution. Please use version 1.0.1 or later.
--------------------------------------------------------------------------------
/vonage/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "vonage"
3 | dynamic = ["version"]
4 | description = "Python Server SDK for using Vonage APIs"
5 | readme = "README.md"
6 | requires-python = ">=3.9"
7 | dependencies = [
8 | "vonage-account>=1.1.1",
9 | "vonage-application>=2.0.1",
10 | "vonage-http-client>=1.5.1",
11 | "vonage-messages>=1.5.0",
12 | "vonage-network-auth>=1.0.2",
13 | "vonage-network-sim-swap>=1.1.2",
14 | "vonage-network-number-verification>=1.0.2",
15 | "vonage-number-insight>=1.0.7",
16 | "vonage-numbers>=1.0.4",
17 | "vonage-sms>=1.1.6",
18 | "vonage-subaccounts>=1.0.4",
19 | "vonage-users>=1.2.1",
20 | "vonage-utils>=1.1.4",
21 | "vonage-verify>=2.1.0",
22 | "vonage-verify-legacy>=1.0.1",
23 | "vonage-video>=1.2.0",
24 | "vonage-voice>=1.4.0",
25 | ]
26 | classifiers = [
27 | "Programming Language :: Python",
28 | "Programming Language :: Python :: 3",
29 | "Programming Language :: Python :: 3.9",
30 | "Programming Language :: Python :: 3.10",
31 | "Programming Language :: Python :: 3.11",
32 | "Programming Language :: Python :: 3.12",
33 | "Programming Language :: Python :: 3.13",
34 | "License :: OSI Approved :: Apache Software License",
35 | ]
36 | [[project.authors]]
37 | name = "Vonage"
38 | email = "devrel@vonage.com"
39 |
40 | [build-system]
41 | requires = ["setuptools>=61.0", "wheel"]
42 | build-backend = "setuptools.build_meta"
43 |
44 | [project.urls]
45 | homepage = "https://github.com/Vonage/vonage-python-sdk"
46 |
47 | [tool.setuptools.dynamic.version]
48 | attr = "vonage._version.__version__"
49 |
--------------------------------------------------------------------------------
/number_insight/tests/data/advanced_sync_insight.json:
--------------------------------------------------------------------------------
1 | {
2 | "caller_identity": {
3 | "caller_name": "John Smith",
4 | "caller_type": "consumer",
5 | "first_name": "John",
6 | "last_name": "Smith",
7 | "subscription_type": "postpaid"
8 | },
9 | "caller_name": "John Smith",
10 | "caller_type": "consumer",
11 | "country_code": "US",
12 | "country_code_iso3": "USA",
13 | "country_name": "United States of America",
14 | "country_prefix": "1",
15 | "current_carrier": {
16 | "country": "US",
17 | "name": "AT&T Mobility",
18 | "network_code": "310090",
19 | "network_type": "mobile"
20 | },
21 | "first_name": "John",
22 | "international_format_number": "12345678900",
23 | "ip_warnings": "unknown",
24 | "last_name": "Smith",
25 | "lookup_outcome": 1,
26 | "lookup_outcome_message": "Partial success - some fields populated",
27 | "national_format_number": "(234) 567-8900",
28 | "original_carrier": {
29 | "country": "US",
30 | "name": "AT&T Mobility",
31 | "network_code": "310090",
32 | "network_type": "mobile"
33 | },
34 | "ported": "not_ported",
35 | "reachable": "unknown",
36 | "refund_price": "0.01025000",
37 | "remaining_balance": "32.68590294",
38 | "request_id": "97e973e7-2e27-4fd3-9e1a-972ea14dd992",
39 | "request_price": "0.05025000",
40 | "roaming": "unknown",
41 | "status": 44,
42 | "status_message": "Lookup Handler unable to handle request",
43 | "valid_number": "valid"
44 | }
--------------------------------------------------------------------------------
/network_number_verification/src/vonage_network_number_verification/requests.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field, model_validator
2 | from vonage_network_number_verification.errors import NetworkNumberVerificationError
3 |
4 |
5 | class NumberVerificationRequest(BaseModel):
6 | """Model for the request to verify a phone number.
7 |
8 | Args:
9 | code (str): The code returned from the OIDC redirect.
10 | redirect_uri (str): The URI to redirect to after authentication.
11 | phone_number (str): The phone number to verify. Use the E.164 format with
12 | or without a leading +.
13 | hashed_phone_number (str): The hashed phone number to verify.
14 | """
15 |
16 | code: str
17 | redirect_uri: str
18 | phone_number: str = Field(None, serialization_alias='phoneNumber')
19 | hashed_phone_number: str = Field(None, serialization_alias='hashedPhoneNumber')
20 |
21 | @model_validator(mode='after')
22 | def check_only_one_phone_number(self):
23 | """Check that only one of `phone_number` and `hashed_phone_number` is set."""
24 |
25 | if self.phone_number is not None and self.hashed_phone_number is not None:
26 | raise NetworkNumberVerificationError(
27 | 'Only one of `phone_number` and `hashed_phone_number` can be set.'
28 | )
29 |
30 | if self.phone_number is None and self.hashed_phone_number is None:
31 | raise NetworkNumberVerificationError(
32 | 'One of `phone_number` and `hashed_phone_number` must be set.'
33 | )
34 |
35 | return self
36 |
--------------------------------------------------------------------------------
/video/src/vonage_video/errors.py:
--------------------------------------------------------------------------------
1 | from vonage_utils.errors import VonageError
2 |
3 |
4 | class VideoError(VonageError):
5 | """Indicates an error when using the Vonage Voice API."""
6 |
7 |
8 | class InvalidRoleError(VideoError):
9 | """The specified role was invalid."""
10 |
11 |
12 | class TokenExpiryError(VideoError):
13 | """The specified token expiry time was invalid."""
14 |
15 |
16 | class SipError(VideoError):
17 | """Error related to usage of SIP calls."""
18 |
19 |
20 | class NoAudioOrVideoError(VideoError):
21 | """Either an audio or video stream must be included."""
22 |
23 |
24 | class IndividualArchivePropertyError(VideoError):
25 | """The property cannot be set for `archive_mode: 'individual'`."""
26 |
27 |
28 | class LayoutStylesheetError(VideoError):
29 | """Error with the `stylesheet` property when setting a layout."""
30 |
31 |
32 | class LayoutScreenshareTypeError(VideoError):
33 | """Error with the `screenshare_type` property when setting a layout."""
34 |
35 |
36 | class InvalidArchiveStateError(VideoError):
37 | """The archive state was invalid for the specified operation."""
38 |
39 |
40 | class InvalidHlsOptionsError(VideoError):
41 | """The HLS options were invalid."""
42 |
43 |
44 | class InvalidOutputOptionsError(VideoError):
45 | """The output options were invalid."""
46 |
47 |
48 | class InvalidBroadcastStateError(VideoError):
49 | """The broadcast state was invalid for the specified operation."""
50 |
51 |
52 | class RoutedSessionRequiredError(VideoError):
53 | """The operation requires a session with `media_mode=routed`."""
54 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ---
11 | name: Bug report
12 | about: Create a report to help us improve
13 | title: ''
14 | labels: ''
15 | assignees: ''
16 |
17 | ---
18 |
19 |
20 |
21 | ## Expected Behavior
22 |
23 |
24 |
25 | ## Current Behavior
26 |
27 |
28 |
29 | ## Possible Solution
30 |
31 |
32 |
33 | ## Steps to Reproduce (for bugs)
34 |
35 |
36 | 1.
37 | 2.
38 | 3.
39 | 4.
40 |
41 | ## Context
42 |
43 |
44 |
45 | ## Your Environment
46 |
47 | * Version used:
48 | * Environment name and version (e.g. language and server version):
49 | * Operating System and version:
50 |
--------------------------------------------------------------------------------
/vonage/README.md:
--------------------------------------------------------------------------------
1 | # Vonage Python SDK
2 |
3 | The Vonage Python SDK Package `vonage` provides a streamlined interface for using Vonage APIs in Python projects. This package includes the `Vonage` class, which simplifies API interactions.
4 |
5 | The Vonage class in this package serves as the main entry point for using Vonage APIs. It abstracts away complexities with authentication, HTTP requests and more.
6 |
7 | For full API documentation refer to the [Vonage Developer documentation](https://developer.vonage.com).
8 |
9 | ## Installation
10 |
11 | Install the package using pip:
12 |
13 | ```bash
14 | pip install vonage
15 | ```
16 |
17 | ## Usage
18 |
19 | ```python
20 | from vonage import Vonage, Auth, HttpClientOptions
21 |
22 | # Create an Auth instance
23 | auth = Auth(api_key='your_api_key', api_secret='your_api_secret')
24 |
25 | # Create HttpClientOptions instance
26 | # (not required unless you want to change options from the defaults)
27 | options = HttpClientOptions(api_host='api.nexmo.com', timeout=30)
28 |
29 | # Create a Vonage instance
30 | vonage = Vonage(auth=auth, http_client_options=options)
31 | ```
32 |
33 | The Vonage class provides access to various Vonage APIs through its properties. For example, to use methods to call the SMS API:
34 |
35 | ```python
36 | from vonage_sms import SmsMessage
37 |
38 | message = SmsMessage(to='1234567890', from_='Vonage', text='Hello World')
39 | response = client.sms.send(message)
40 | print(response.model_dump_json(exclude_unset=True))
41 | ```
42 |
43 | You can also access the underlying `HttpClient` instance through the `http_client` property:
44 |
45 | ```python
46 | user_agent = vonage.http_client.user_agent
47 | ```
--------------------------------------------------------------------------------
/account/tests/data/get_multiple_countries_pricing.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "countries": [
4 | {
5 | "dialingPrefix": "39",
6 | "defaultPrice": "0.08270000",
7 | "currency": "EUR",
8 | "countryDisplayName": "Italy",
9 | "countryCode": "IT",
10 | "countryName": "Italy",
11 | "networks": [
12 | {
13 | "type": "mobile",
14 | "price": "0.08270000",
15 | "currency": "EUR",
16 | "mcc": "222",
17 | "mnc": "07",
18 | "networkCode": "22207",
19 | "networkName": "Noverca Italia S.r.l."
20 | },
21 | {
22 | "type": "mobile",
23 | "price": "0.08270000",
24 | "currency": "EUR",
25 | "mcc": "222",
26 | "mnc": "08",
27 | "networkCode": "22208",
28 | "networkName": "FastWeb S.p.A."
29 | },
30 | {
31 | "type": "landline_premium",
32 | "price": "0.08270000",
33 | "currency": "EUR",
34 | "networkCode": "IT-PREMIUM",
35 | "networkName": "Italy Premium"
36 | }
37 | ]
38 | },
39 | {
40 | "dialingPrefix": "39",
41 | "currency": "EUR",
42 | "countryDisplayName": "Vatican City",
43 | "countryCode": "VA",
44 | "countryName": "Vatican City"
45 | }
46 | ]
47 | }
--------------------------------------------------------------------------------
/video/tests/data/list_experience_composers.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 3,
3 | "items": [
4 | {
5 | "id": "be7712a4-3a63-4ed7-a2c6-7ffaebefd4a6",
6 | "sessionId": "test_session_id",
7 | "createdAt": 1727784741000,
8 | "updatedAt": 1727784744000,
9 | "url": "https://developer.vonage.com",
10 | "status": "started",
11 | "streamId": "C1B0E149-8169-4AFD-9397-882516EE9430",
12 | "event": "render",
13 | "applicationId": "test_application_id",
14 | "resolution": "1280x720"
15 | },
16 | {
17 | "id": "89559e73-0d49-4388-b373-ddef191e4373",
18 | "sessionId": "test_session_id",
19 | "createdAt": 1727784421000,
20 | "updatedAt": 1727784424000,
21 | "url": "https://example.com",
22 | "status": "started",
23 | "streamId": "F9C3BCD5-850F-4DB7-B6C1-97F615CA9E79",
24 | "event": "render",
25 | "applicationId": "test_application_id",
26 | "resolution": "1280x720"
27 | },
28 | {
29 | "id": "80c3d2d8-0848-41b2-be14-1a5b8936c87d",
30 | "sessionId": "test_session_id",
31 | "createdAt": 1727781191000,
32 | "updatedAt": 1727784793000,
33 | "url": "https://example.com",
34 | "status": "stopped",
35 | "streamId": "95F83A10-D767-4F21-9270-DC6E88067FAC",
36 | "reason": "Max duration exceeded",
37 | "event": "render",
38 | "applicationId": "test_application_id",
39 | "resolution": "1280x720"
40 | }
41 | ]
42 | }
--------------------------------------------------------------------------------
/messages/tests/test_sms_models.py:
--------------------------------------------------------------------------------
1 | from vonage_messages.models import Sms, SmsOptions
2 | from vonage_messages.models.enums import EncodingType, WebhookVersion
3 |
4 |
5 | def test_create_sms():
6 | sms_model = Sms(
7 | to='1234567890',
8 | from_='1234567890',
9 | text='Hello, World!',
10 | )
11 | sms_dict = {
12 | 'to': '1234567890',
13 | 'from': '1234567890',
14 | 'text': 'Hello, World!',
15 | 'channel': 'sms',
16 | 'message_type': 'text',
17 | }
18 |
19 | assert sms_model.model_dump(by_alias=True, exclude_none=True) == sms_dict
20 |
21 |
22 | def test_create_sms_all_fields():
23 | sms_model = Sms(
24 | to='1234567890',
25 | from_='1234567890',
26 | text='Hello, World!',
27 | sms=SmsOptions(
28 | encoding_type=EncodingType.TEXT,
29 | content_id='content-id',
30 | entity_id='entity-id',
31 | ),
32 | client_ref='client-ref',
33 | webhook_url='https://example.com',
34 | webhook_version=WebhookVersion.V1,
35 | ttl=600,
36 | )
37 | sms_dict = {
38 | 'to': '1234567890',
39 | 'from': '1234567890',
40 | 'text': 'Hello, World!',
41 | 'sms': {
42 | 'encoding_type': 'text',
43 | 'content_id': 'content-id',
44 | 'entity_id': 'entity-id',
45 | },
46 | 'client_ref': 'client-ref',
47 | 'webhook_url': 'https://example.com',
48 | 'webhook_version': 'v1',
49 | 'ttl': 600,
50 | 'channel': 'sms',
51 | 'message_type': 'text',
52 | }
53 |
54 | assert sms_model.model_dump(by_alias=True) == sms_dict
55 |
--------------------------------------------------------------------------------
/video/src/vonage_video/models/stream.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel, Field
4 |
5 |
6 | class StreamInfo(BaseModel):
7 | """The stream information.
8 |
9 | Args:
10 | id (str): The stream ID.
11 | video_type (str): Set to "camera", "screen", or "custom". A "screen" video uses
12 | screen sharing on the publisher as the video source; a "custom" video is
13 | published by a web client using an HTML VideoTrack element as the video
14 | source.
15 | name (str): An array of the layout classes for the stream.
16 | layout_class_list (list[str]): An array of the layout classes for the stream.
17 | """
18 |
19 | id: Optional[str] = Field(None, validation_alias='id')
20 | video_type: Optional[str] = Field(None, validation_alias='videoType')
21 | name: Optional[str] = Field(None, validation_alias='name')
22 | layout_class_list: Optional[list[str]] = Field(
23 | None, validation_alias='layoutClassList'
24 | )
25 |
26 |
27 | class StreamLayout(BaseModel):
28 | """The stream layout.
29 |
30 | Args:
31 | id (str): The stream ID.
32 | layout_class_list (list[str]): An array of the layout classes for the stream.
33 | """
34 |
35 | id: str
36 | layout_class_list: list[str] = Field(..., serialization_alias='layoutClassList')
37 |
38 |
39 | class StreamLayoutOptions(BaseModel):
40 | """The options for the stream layout.
41 |
42 | Args:
43 | items (list[[StreamLayout]]): An array of the stream layout items. Each item is a StreamLayout
44 | object. See StreamLayout.
45 | """
46 |
47 | items: list[StreamLayout]
48 |
--------------------------------------------------------------------------------
/network_sim_swap/README.md:
--------------------------------------------------------------------------------
1 | # Vonage Sim Swap Network API Client
2 |
3 | This package (`vonage-network-sim-swap`) allows you to check whether a SIM card has been swapped, and the last swap date.
4 |
5 | This package is not intended to be used directly, instead being accessed from an enclosing SDK package. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK.
6 |
7 | For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com).
8 |
9 | ## Registering to Use the Sim Swap API
10 |
11 | To use this API, you must first create and register your business profile with the Vonage Network Registry. [This documentation page](https://developer.vonage.com/en/getting-started-network/registration) explains how this can be done. You need to obtain approval for each network and region you want to use the APIs in.
12 |
13 | ## Installation
14 |
15 | Install from the Python Package Index with pip:
16 |
17 | ```bash
18 | pip install vonage-network-sim-swap
19 | ```
20 |
21 | ## Usage
22 |
23 | It is recommended to use this as part of the `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`.
24 |
25 | ### Check if a SIM Has Been Swapped
26 |
27 | ```python
28 | from vonage_network_sim_swap import SwapStatus
29 | swap_status: SwapStatus = vonage_client.sim_swap.check(phone_number='MY_NUMBER')
30 | print(swap_status.swapped)
31 | ```
32 |
33 | ### Get the Date of the Last SIM Swap
34 |
35 | ```python
36 | from vonage_network_sim_swap import LastSwapDate
37 | swap_date: LastSwapDate = vonage_client.sim_swap.get_last_swap_date
38 | print(swap_date.last_swap_date)
39 | ```
--------------------------------------------------------------------------------
/network_auth/tests/data/token_request.json:
--------------------------------------------------------------------------------
1 | {
2 | "access_token": "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vYW51YmlzLWNlcnRzLWMxLWV1dzEucHJvZC52MS52b25hZ2VuZXR3b3Jrcy5uZXQvandrcyIsImtpZCI6IkNOPVZvbmFnZSAxdmFwaWd3IEludGVybmFsIENBOjoxOTUxODQ2ODA3NDg1NTYwNjYzODY3MTM0NjE2MjU2MTU5MjU2NDkiLCJ0eXAiOiJKV1QiLCJ4NXUiOiJodHRwczovL2FudWJpcy1jZXJ0cy1jMS1ldXcxLnByb2QudjEudm9uYWdlbmV0d29ya3MubmV0L3YxL2NlcnRzLzA4NjliNDMyZTEzZmIyMzcwZTk2ZGI4YmUxMDc4MjJkIn0.eyJwcmluY2lwYWwiOnsiYXBpS2V5IjoiNGI1MmMwMGUiLCJhcHBsaWNhdGlvbklkIjoiMmJlZTViZWQtNmZlZS00ZjM2LTkxNmQtNWUzYjRjZDI1MjQzIiwibWFzdGVyQWNjb3VudElkIjoiNGI1MmMwMGUiLCJjYXBhYmlsaXRpZXMiOlsibmV0d29yay1hcGktZmVhdHVyZXMiXSwiZXh0cmFDb25maWciOnsiY2FtYXJhU3RhdGUiOiJmb0ZyQndnOFNmeGMydnd2S1o5Y3UrMlgrT0s1K2FvOWhJTTVGUGZMQ1dOeUlMTHR3WmY1dFRKbDdUc1p4QnY4QWx3aHM2bFNWcGVvVkhoWngvM3hUenFRWVkwcHpIZE5XL085ZEdRN1RKOE9sU1lDdTFYYXFEcnNFbEF4WEJVcUpGdnZTTkp5a1A5ZDBYWVN4ajZFd0F6UUFsNGluQjE1c3VMRFNsKy82U1FDa29Udnpld0tvcFRZb0F5MVg2dDJVWXdEVWFDNjZuOS9kVWxIemN3V0NGK3QwOGNReGxZVUxKZyt3T0hwV2xvWGx1MGc3REx0SCtHd0pvRGJoYnMyT2hVY3BobGZqajBpeHQ1OTRsSG5sQ1NYNkZrMmhvWEhKUW01S3JtOVBKSmttK0xTRjVsRTd3NUxtWTRvYTFXSGpkY0dwV1VsQlNQY000YnprOGU0bVE9PSJ9fSwiZmVkZXJhdGVkQXNzZXJ0aW9ucyI6e30sImF1ZCI6ImFwaS1ldS52b25hZ2UuY29tIiwiZXhwIjoxNzE3MDkyODY4LCJqdGkiOiJmNDZhYTViOC1hODA2LTRjMzctODQyMS02OGYwMzJjNDlhMWYiLCJpYXQiOjE3MTcwOTE5NzAsImlzcyI6IlZJQU0tSUFQIiwibmJmIjoxNzE3MDkxOTU1fQ.iLUbyDPR1HGLKh29fy6fqK65Q1O7mjWOletAEPJD4eu7gb0E85EL4M9R7ckJq5lIvgedQt3vBheTaON9_u-VYjMqo8ulPoEoGUDHbOzNbs4MmCW0_CRdDPGyxnUhvcbuJhPgnEHxmfHjJBljncUnk-Z7XCgyNajBNXeQQnHkRF_6NMngxJ-qjjhqbYL0VsF_JS7-TXxixNL0KAFl0SeN2DjkfwRBCclP-69CTExDjyOvouAcchqi-6ZYj_tXPCrTADuzUrQrW8C5nHp2-XjWJSFKzyvi48n8V1U6KseV-eYzBzvy7bJf0tRMX7G6gctTYq3DxdC_eXvXlnp1zx16mg",
3 | "token_type": "bearer",
4 | "expires_in": 29
5 | }
--------------------------------------------------------------------------------
/voice/tests/data/list_calls_filter.json:
--------------------------------------------------------------------------------
1 | {
2 | "page_size": 1,
3 | "record_index": 1,
4 | "count": 3,
5 | "_embedded": {
6 | "calls": [
7 | {
8 | "uuid": "1acdf499-83ae-4861-a694-9e47a98c505d",
9 | "status": "completed",
10 | "direction": "outbound",
11 | "rate": "0.10000000",
12 | "price": "0.00333333",
13 | "duration": "2",
14 | "network": "23420",
15 | "conversation_uuid": "CON-ee83ad86-ee21-4c28-bf7d-4ae67692721e",
16 | "start_time": "2024-04-18T16:01:51.000Z",
17 | "end_time": "2024-04-18T16:01:53.000Z",
18 | "to": {
19 | "type": "phone",
20 | "number": "1234567890"
21 | },
22 | "from": {
23 | "type": "phone",
24 | "number": "9876543210"
25 | },
26 | "_links": {
27 | "self": {
28 | "href": "/v1/calls/1acdf499-83ae-4861-a694-9e47a98c505d"
29 | }
30 | }
31 | }
32 | ]
33 | },
34 | "_links": {
35 | "self": {
36 | "href": "/v1/calls?page_size=1&record_index=1"
37 | },
38 | "first": {
39 | "href": "/v1/calls?page_size=1"
40 | },
41 | "last": {
42 | "href": "/v1/calls?page_size=1&record_index=2"
43 | },
44 | "next": {
45 | "href": "/v1/calls?page_size=1&record_index=2"
46 | },
47 | "prev": {
48 | "href": "/v1/calls?page_size=1&record_index=0"
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/network_number_verification/tests/data/token_request.json:
--------------------------------------------------------------------------------
1 | {
2 | "access_token": "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vYW51YmlzLWNlcnRzLWMxLWV1dzEucHJvZC52MS52b25hZ2VuZXR3b3Jrcy5uZXQvandrcyIsImtpZCI6IkNOPVZvbmFnZSAxdmFwaWd3IEludGVybmFsIENBOjoxOTUxODQ2ODA3NDg1NTYwNjYzODY3MTM0NjE2MjU2MTU5MjU2NDkiLCJ0eXAiOiJKV1QiLCJ4NXUiOiJodHRwczovL2FudWJpcy1jZXJ0cy1jMS1ldXcxLnByb2QudjEudm9uYWdlbmV0d29ya3MubmV0L3YxL2NlcnRzLzA4NjliNDMyZTEzZmIyMzcwZTk2ZGI4YmUxMDc4MjJkIn0.eyJwcmluY2lwYWwiOnsiYXBpS2V5IjoiNGI1MmMwMGUiLCJhcHBsaWNhdGlvbklkIjoiMmJlZTViZWQtNmZlZS00ZjM2LTkxNmQtNWUzYjRjZDI1MjQzIiwibWFzdGVyQWNjb3VudElkIjoiNGI1MmMwMGUiLCJjYXBhYmlsaXRpZXMiOlsibmV0d29yay1hcGktZmVhdHVyZXMiXSwiZXh0cmFDb25maWciOnsiY2FtYXJhU3RhdGUiOiJmb0ZyQndnOFNmeGMydnd2S1o5Y3UrMlgrT0s1K2FvOWhJTTVGUGZMQ1dOeUlMTHR3WmY1dFRKbDdUc1p4QnY4QWx3aHM2bFNWcGVvVkhoWngvM3hUenFRWVkwcHpIZE5XL085ZEdRN1RKOE9sU1lDdTFYYXFEcnNFbEF4WEJVcUpGdnZTTkp5a1A5ZDBYWVN4ajZFd0F6UUFsNGluQjE1c3VMRFNsKy82U1FDa29Udnpld0tvcFRZb0F5MVg2dDJVWXdEVWFDNjZuOS9kVWxIemN3V0NGK3QwOGNReGxZVUxKZyt3T0hwV2xvWGx1MGc3REx0SCtHd0pvRGJoYnMyT2hVY3BobGZqajBpeHQ1OTRsSG5sQ1NYNkZrMmhvWEhKUW01S3JtOVBKSmttK0xTRjVsRTd3NUxtWTRvYTFXSGpkY0dwV1VsQlNQY000YnprOGU0bVE9PSJ9fSwiZmVkZXJhdGVkQXNzZXJ0aW9ucyI6e30sImF1ZCI6ImFwaS1ldS52b25hZ2UuY29tIiwiZXhwIjoxNzE3MDkyODY4LCJqdGkiOiJmNDZhYTViOC1hODA2LTRjMzctODQyMS02OGYwMzJjNDlhMWYiLCJpYXQiOjE3MTcwOTE5NzAsImlzcyI6IlZJQU0tSUFQIiwibmJmIjoxNzE3MDkxOTU1fQ.iLUbyDPR1HGLKh29fy6fqK65Q1O7mjWOletAEPJD4eu7gb0E85EL4M9R7ckJq5lIvgedQt3vBheTaON9_u-VYjMqo8ulPoEoGUDHbOzNbs4MmCW0_CRdDPGyxnUhvcbuJhPgnEHxmfHjJBljncUnk-Z7XCgyNajBNXeQQnHkRF_6NMngxJ-qjjhqbYL0VsF_JS7-TXxixNL0KAFl0SeN2DjkfwRBCclP-69CTExDjyOvouAcchqi-6ZYj_tXPCrTADuzUrQrW8C5nHp2-XjWJSFKzyvi48n8V1U6KseV-eYzBzvy7bJf0tRMX7G6gctTYq3DxdC_eXvXlnp1zx16mg",
3 | "token_type": "bearer",
4 | "expires_in": 29
5 | }
--------------------------------------------------------------------------------
/application/tests/data/list_applications_basic.json:
--------------------------------------------------------------------------------
1 | {
2 | "page_size": 100,
3 | "page": 1,
4 | "total_items": 1,
5 | "total_pages": 1,
6 | "_embedded": {
7 | "applications": [
8 | {
9 | "id": "1b1b1b1b-1b1b-1b1b-1b1b-1b1b1b1b1b1b",
10 | "name": "dev-application",
11 | "keys": {
12 | "public_key": "-----BEGIN PUBLIC KEY-----\npublic_key_info_goes_here\n-----END PUBLIC KEY-----\n"
13 | },
14 | "privacy": {
15 | "improve_ai": true
16 | },
17 | "capabilities": {
18 | "voice": {
19 | "webhooks": {
20 | "event_url": {
21 | "address": "http://example.com",
22 | "http_method": "POST"
23 | },
24 | "answer_url": {
25 | "address": "http://example.com",
26 | "http_method": "GET"
27 | }
28 | },
29 | "signed_callbacks": true,
30 | "conversations_ttl": 9000,
31 | "leg_persistence_time": 7
32 | }
33 | }
34 | }
35 | ]
36 | },
37 | "_links": {
38 | "self": {
39 | "href": "/v2/applications?page_size=100&page=1"
40 | },
41 | "first": {
42 | "href": "/v2/applications?page_size=100"
43 | },
44 | "last": {
45 | "href": "/v2/applications?page_size=100&page=1"
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/voice/src/vonage_voice/models/__init__.py:
--------------------------------------------------------------------------------
1 | from .common import AdvancedMachineDetection, Phone, Sip, Vbc, Websocket
2 | from .connect_endpoints import (
3 | AppEndpoint,
4 | OnAnswer,
5 | PhoneEndpoint,
6 | SipEndpoint,
7 | VbcEndpoint,
8 | WebsocketEndpoint,
9 | )
10 | from .enums import (
11 | CallState,
12 | Channel,
13 | ConnectEndpointType,
14 | NccoActionType,
15 | TtsLanguageCode,
16 | )
17 | from .input_types import Dtmf, Speech
18 | from .ncco import Connect, Conversation, Input, NccoAction, Notify, Record, Stream, Talk
19 | from .requests import (
20 | AudioStreamOptions,
21 | CreateCallRequest,
22 | ListCallsFilter,
23 | ToPhone,
24 | TtsStreamOptions,
25 | )
26 | from .responses import (
27 | CallInfo,
28 | CallList,
29 | CallMessage,
30 | CreateCallResponse,
31 | Embedded,
32 | HalLinks,
33 | )
34 |
35 | __all__ = [
36 | 'AdvancedMachineDetection',
37 | 'AppEndpoint',
38 | 'AudioStreamOptions',
39 | 'CallInfo',
40 | 'CallList',
41 | 'CallMessage',
42 | 'CallState',
43 | 'Channel',
44 | 'Connect',
45 | 'ConnectEndpointType',
46 | 'Conversation',
47 | 'CreateCallRequest',
48 | 'CreateCallResponse',
49 | 'Dtmf',
50 | 'Embedded',
51 | 'Input',
52 | 'ListCallsFilter',
53 | 'HalLinks',
54 | 'NccoAction',
55 | 'NccoActionType',
56 | 'Notify',
57 | 'OnAnswer',
58 | 'Phone',
59 | 'PhoneEndpoint',
60 | 'Record',
61 | 'Sip',
62 | 'SipEndpoint',
63 | 'Speech',
64 | 'Stream',
65 | 'Talk',
66 | 'ToPhone',
67 | 'TtsLanguageCode',
68 | 'TtsStreamOptions',
69 | 'Vbc',
70 | 'VbcEndpoint',
71 | 'Websocket',
72 | 'WebsocketEndpoint',
73 | ]
74 |
--------------------------------------------------------------------------------
/network_sim_swap/tests/test_sim_swap.py:
--------------------------------------------------------------------------------
1 | from os.path import abspath
2 | from unittest.mock import MagicMock, patch
3 |
4 | import responses
5 | from vonage_http_client.http_client import HttpClient
6 | from vonage_network_sim_swap import NetworkSimSwap
7 | from vonage_network_sim_swap.requests import SimSwapCheckRequest
8 |
9 | from testutils import build_response, get_mock_jwt_auth
10 |
11 | path = abspath(__file__)
12 |
13 | sim_swap = NetworkSimSwap(HttpClient(get_mock_jwt_auth()))
14 |
15 |
16 | def test_http_client_property():
17 | http_client = sim_swap.http_client
18 | assert isinstance(http_client, HttpClient)
19 |
20 |
21 | @patch('vonage_network_auth.NetworkAuth.get_sim_swap_camara_token')
22 | @responses.activate
23 | def test_check_sim_swap(mock_get_oauth2_user_token: MagicMock):
24 | build_response(
25 | path,
26 | 'POST',
27 | 'https://api-eu.vonage.com/camara/sim-swap/v040/check',
28 | 'check_sim_swap.json',
29 | )
30 | mock_get_oauth2_user_token.return_value = 'token'
31 |
32 | response = sim_swap.check(
33 | SimSwapCheckRequest(phone_number='447700900000', max_age=24)
34 | )
35 |
36 | assert response['swapped'] == True
37 |
38 |
39 | @patch('vonage_network_auth.NetworkAuth.get_sim_swap_camara_token')
40 | @responses.activate
41 | def test_get_last_swap_date(mock_get_oauth2_user_token: MagicMock):
42 | build_response(
43 | path,
44 | 'POST',
45 | 'https://api-eu.vonage.com/camara/sim-swap/v040/retrieve-date',
46 | 'get_swap_date.json',
47 | )
48 | mock_get_oauth2_user_token.return_value = 'token'
49 |
50 | response = sim_swap.get_last_swap_date('447700900000')
51 |
52 | assert response['latestSimChange'] == '2023-12-22T04:00:44.000Z'
53 |
--------------------------------------------------------------------------------
/verify_legacy/src/vonage_verify_legacy/language_codes.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 |
4 | class LanguageCode(str, Enum):
5 | """Language code used in a specific Verify request."""
6 |
7 | ar_xa = 'ar-xa'
8 | cs_cz = 'cs-cz'
9 | cy_cy = 'cy-cy'
10 | cy_gb = 'cy-gb'
11 | da_dk = 'da-dk'
12 | de_de = 'de-de'
13 | el_gr = 'el-gr'
14 | en_au = 'en-au'
15 | en_gb = 'en-gb'
16 | en_in = 'en-in'
17 | en_us = 'en-us'
18 | es_es = 'es-es'
19 | es_mx = 'es-mx'
20 | es_us = 'es-us'
21 | fi_fi = 'fi-fi'
22 | fil_ph = 'fil-ph'
23 | fr_ca = 'fr-ca'
24 | fr_fr = 'fr-fr'
25 | hi_in = 'hi-in'
26 | hu_hu = 'hu-hu'
27 | id_id = 'id-id'
28 | is_is = 'is-is'
29 | it_it = 'it-it'
30 | ja_jp = 'ja-jp'
31 | ko_kr = 'ko-kr'
32 | nb_no = 'nb-no'
33 | nl_nl = 'nl-nl'
34 | pl_pl = 'pl-pl'
35 | pt_br = 'pt-br'
36 | pt_pt = 'pt-pt'
37 | ro_ro = 'ro-ro'
38 | ru_ru = 'ru-ru'
39 | sv_se = 'sv-se'
40 | th_th = 'th-th'
41 | tr_tr = 'tr-tr'
42 | vi_vn = 'vi-vn'
43 | yue_cn = 'yue-cn'
44 | zh_cn = 'zh-cn'
45 | zh_tw = 'zh-tw'
46 |
47 |
48 | class Psd2LanguageCode(str, Enum):
49 | """Language code used in a specific Verify PSD2 request."""
50 |
51 | en_gb = 'en-gb'
52 | bg_bg = 'bg-bg'
53 | cs_cz = 'cs-cz'
54 | da_dk = 'da-dk'
55 | de_de = 'de-de'
56 | ee_et = 'ee-et'
57 | el_gr = 'el-gr'
58 | es_es = 'es-es'
59 | fi_fi = 'fi-fi'
60 | fr_fr = 'fr-fr'
61 | ga_ie = 'ga-ie'
62 | hu_hu = 'hu-hu'
63 | it_it = 'it-it'
64 | lv_lv = 'lv-lv'
65 | lt_lt = 'lt-lt'
66 | mt_mt = 'mt-mt'
67 | nl_nl = 'nl-nl'
68 | pl_pl = 'pl-pl'
69 | sk_sk = 'sk-sk'
70 | sl_si = 'sl-si'
71 | sv_se = 'sv-se'
72 |
--------------------------------------------------------------------------------
/jwt/tests/data/private_key.txt:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQdAHqJHs/a+Ra
3 | 2ubvSd1vz/aWlJ9BqnMUtB7guTlyggdENAbleIkzep6mUHepDJdQh8Qv6zS3lpUe
4 | K0UkDfr1/FvsvxurGw/YYPagUEhP/HxMbs2rnQTiAdWOT+Ux9vPABoyNYvZB90xN
5 | IVhBDRWgkz1HPQBRNjFcm3NOol83h5Uwp5YroGTWx+rpmIiRhQj3mv6luk102d95
6 | 4ulpPpzcYWKIpJNdclJrEkBZaghDZTOpbv79qd+ds9AVp1j8i9cG/owBJpsJWxfw
7 | StMDpNeEZqopeQWmA121sSEsxpAbKJ5DA7F/lmckx74sulKHX1fDWT76cRhloaEQ
8 | VmETdj0VAgMBAAECggEAZ+SBtchz8vKbsBqtAbM/XcR5Iqi1TR2eWMHDJ/65HpSm
9 | +XuyujjerN0e6EZvtT4Uxmq8QaPJNP0kmhI31hXvsB0UVcUUDa4hshb1pIYO3Gq7
10 | Kr8I29EZB2mhndm9Ii9yYhEBiVA66zrNeR225kkWr97iqjhBibhoVr8Vc6oiqcIP
11 | nFy5zSFtQSkhucaPge6rW00JSOD3wg2GM+rgS6r22t8YmqTzAwvwfil5pQfUngal
12 | oywqLOf6CUYXPBleJc1KgaIIP/cSvqh6b/t25o2VXnI4rpRhtleORvYBbH6K6xLa
13 | OWgg6B58T+0/QEqtZIAn4miYtVCkYLB78Ormc7Q9ewKBgQDuSytuYqxdZh/L/RDU
14 | CErFcNO5I1e9fkLAs5dQEBvvdQC74+oA1MsDEVv0xehFa1JwPKSepmvB2UznZg9L
15 | CtR7QKMDZWvS5xx4j0E/b+PiNQ/tlcFZB2UZ0JwviSxdd7omOTscq9c3RIhFHar1
16 | Y38Fixkfm44Ij/K3JqIi2v2QMwKBgQDf8TYOOmAr9UuipUDxMsRSqTGVIY8B+aEJ
17 | W+2aLrqJVkLGTRfrbjzXWYo3+n7kNJjFgNkltDq6HYtufHMYRs/0PPtNR0w0cDPS
18 | Xr7m2LNHTDcBalC/AS4yKZJLNLm+kXA84vkw4qiTjc0LSFxJkouTQzkea0l8EWHt
19 | zRMv/qYVlwKBgBaJOWRJJK/4lo0+M7c5yYh+sSdTNlsPc9Sxp1/FBj9RO26JkXne
20 | pgx2OdIeXWcjTTqcIZ13c71zhZhkyJF6RroZVNFfaCEcBk9IjQ0o0c504jq/7Pc0
21 | gdU9K2g7etykFBDFXNfLUKFDc/fFZIOskzi8/PVGStp4cqXrm23cdBqNAoGBAKtf
22 | A2bP9ViuVjsZCyGJIAPBxlfBXpa8WSe4WZNrvwPqJx9pT6yyp4yE0OkVoJUyStaZ
23 | S5M24NocUd8zDUC+r9TP9d+leAOI+Z87MgumOUuOX2mN2kzQsnFgrrsulhXnZmSx
24 | rNBkI20HTqobrcP/iSAgiU1l/M4c3zwDe3N3A9HxAoGBAM2hYu0Ij6htSNgo/WWr
25 | IEYYXuwf8hPkiuwzlaiWhD3eocgd4S8SsBu/bTCY19hQ2QbBPaYyFlNem+ynQyXx
26 | IOacrgIHCrYnRCxjPfFF/MxgUHJb8ZoiexprP/FME5p0PoRQIEFYa+jVht3hT5wC
27 | 9aedWufq4JJb+akO6MVUjTvs
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/testutils/data/fake_private_key.txt:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQdAHqJHs/a+Ra
3 | 2ubvSd1vz/aWlJ9BqnMUtB7guTlyggdENAbleIkzep6mUHepDJdQh8Qv6zS3lpUe
4 | K0UkDfr1/FvsvxurGw/YYPagUEhP/HxMbs2rnQTiAdWOT+Ux9vPABoyNYvZB90xN
5 | IVhBDRWgkz1HPQBRNjFcm3NOol83h5Uwp5YroGTWx+rpmIiRhQj3mv6luk102d95
6 | 4ulpPpzcYWKIpJNdclJrEkBZaghDZTOpbv79qd+ds9AVp1j8i9cG/owBJpsJWxfw
7 | StMDpNeEZqopeQWmA121sSEsxpAbKJ5DA7F/lmckx74sulKHX1fDWT76cRhloaEQ
8 | VmETdj0VAgMBAAECggEAZ+SBtchz8vKbsBqtAbM/XcR5Iqi1TR2eWMHDJ/65HpSm
9 | +XuyujjerN0e6EZvtT4Uxmq8QaPJNP0kmhI31hXvsB0UVcUUDa4hshb1pIYO3Gq7
10 | Kr8I29EZB2mhndm9Ii9yYhEBiVA66zrNeR225kkWr97iqjhBibhoVr8Vc6oiqcIP
11 | nFy5zSFtQSkhucaPge6rW00JSOD3wg2GM+rgS6r22t8YmqTzAwvwfil5pQfUngal
12 | oywqLOf6CUYXPBleJc1KgaIIP/cSvqh6b/t25o2VXnI4rpRhtleORvYBbH6K6xLa
13 | OWgg6B58T+0/QEqtZIAn4miYtVCkYLB78Ormc7Q9ewKBgQDuSytuYqxdZh/L/RDU
14 | CErFcNO5I1e9fkLAs5dQEBvvdQC74+oA1MsDEVv0xehFa1JwPKSepmvB2UznZg9L
15 | CtR7QKMDZWvS5xx4j0E/b+PiNQ/tlcFZB2UZ0JwviSxdd7omOTscq9c3RIhFHar1
16 | Y38Fixkfm44Ij/K3JqIi2v2QMwKBgQDf8TYOOmAr9UuipUDxMsRSqTGVIY8B+aEJ
17 | W+2aLrqJVkLGTRfrbjzXWYo3+n7kNJjFgNkltDq6HYtufHMYRs/0PPtNR0w0cDPS
18 | Xr7m2LNHTDcBalC/AS4yKZJLNLm+kXA84vkw4qiTjc0LSFxJkouTQzkea0l8EWHt
19 | zRMv/qYVlwKBgBaJOWRJJK/4lo0+M7c5yYh+sSdTNlsPc9Sxp1/FBj9RO26JkXne
20 | pgx2OdIeXWcjTTqcIZ13c71zhZhkyJF6RroZVNFfaCEcBk9IjQ0o0c504jq/7Pc0
21 | gdU9K2g7etykFBDFXNfLUKFDc/fFZIOskzi8/PVGStp4cqXrm23cdBqNAoGBAKtf
22 | A2bP9ViuVjsZCyGJIAPBxlfBXpa8WSe4WZNrvwPqJx9pT6yyp4yE0OkVoJUyStaZ
23 | S5M24NocUd8zDUC+r9TP9d+leAOI+Z87MgumOUuOX2mN2kzQsnFgrrsulhXnZmSx
24 | rNBkI20HTqobrcP/iSAgiU1l/M4c3zwDe3N3A9HxAoGBAM2hYu0Ij6htSNgo/WWr
25 | IEYYXuwf8hPkiuwzlaiWhD3eocgd4S8SsBu/bTCY19hQ2QbBPaYyFlNem+ynQyXx
26 | IOacrgIHCrYnRCxjPfFF/MxgUHJb8ZoiexprP/FME5p0PoRQIEFYa+jVht3hT5wC
27 | 9aedWufq4JJb+akO6MVUjTvs
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/http_client/tests/data/dummy_private_key.txt:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDQdAHqJHs/a+Ra
3 | 2ubvSd1vz/aWlJ9BqnMUtB7guTlyggdENAbleIkzep6mUHepDJdQh8Qv6zS3lpUe
4 | K0UkDfr1/FvsvxurGw/YYPagUEhP/HxMbs2rnQTiAdWOT+Ux9vPABoyNYvZB90xN
5 | IVhBDRWgkz1HPQBRNjFcm3NOol83h5Uwp5YroGTWx+rpmIiRhQj3mv6luk102d95
6 | 4ulpPpzcYWKIpJNdclJrEkBZaghDZTOpbv79qd+ds9AVp1j8i9cG/owBJpsJWxfw
7 | StMDpNeEZqopeQWmA121sSEsxpAbKJ5DA7F/lmckx74sulKHX1fDWT76cRhloaEQ
8 | VmETdj0VAgMBAAECggEAZ+SBtchz8vKbsBqtAbM/XcR5Iqi1TR2eWMHDJ/65HpSm
9 | +XuyujjerN0e6EZvtT4Uxmq8QaPJNP0kmhI31hXvsB0UVcUUDa4hshb1pIYO3Gq7
10 | Kr8I29EZB2mhndm9Ii9yYhEBiVA66zrNeR225kkWr97iqjhBibhoVr8Vc6oiqcIP
11 | nFy5zSFtQSkhucaPge6rW00JSOD3wg2GM+rgS6r22t8YmqTzAwvwfil5pQfUngal
12 | oywqLOf6CUYXPBleJc1KgaIIP/cSvqh6b/t25o2VXnI4rpRhtleORvYBbH6K6xLa
13 | OWgg6B58T+0/QEqtZIAn4miYtVCkYLB78Ormc7Q9ewKBgQDuSytuYqxdZh/L/RDU
14 | CErFcNO5I1e9fkLAs5dQEBvvdQC74+oA1MsDEVv0xehFa1JwPKSepmvB2UznZg9L
15 | CtR7QKMDZWvS5xx4j0E/b+PiNQ/tlcFZB2UZ0JwviSxdd7omOTscq9c3RIhFHar1
16 | Y38Fixkfm44Ij/K3JqIi2v2QMwKBgQDf8TYOOmAr9UuipUDxMsRSqTGVIY8B+aEJ
17 | W+2aLrqJVkLGTRfrbjzXWYo3+n7kNJjFgNkltDq6HYtufHMYRs/0PPtNR0w0cDPS
18 | Xr7m2LNHTDcBalC/AS4yKZJLNLm+kXA84vkw4qiTjc0LSFxJkouTQzkea0l8EWHt
19 | zRMv/qYVlwKBgBaJOWRJJK/4lo0+M7c5yYh+sSdTNlsPc9Sxp1/FBj9RO26JkXne
20 | pgx2OdIeXWcjTTqcIZ13c71zhZhkyJF6RroZVNFfaCEcBk9IjQ0o0c504jq/7Pc0
21 | gdU9K2g7etykFBDFXNfLUKFDc/fFZIOskzi8/PVGStp4cqXrm23cdBqNAoGBAKtf
22 | A2bP9ViuVjsZCyGJIAPBxlfBXpa8WSe4WZNrvwPqJx9pT6yyp4yE0OkVoJUyStaZ
23 | S5M24NocUd8zDUC+r9TP9d+leAOI+Z87MgumOUuOX2mN2kzQsnFgrrsulhXnZmSx
24 | rNBkI20HTqobrcP/iSAgiU1l/M4c3zwDe3N3A9HxAoGBAM2hYu0Ij6htSNgo/WWr
25 | IEYYXuwf8hPkiuwzlaiWhD3eocgd4S8SsBu/bTCY19hQ2QbBPaYyFlNem+ynQyXx
26 | IOacrgIHCrYnRCxjPfFF/MxgUHJb8ZoiexprP/FME5p0PoRQIEFYa+jVht3hT5wC
27 | 9aedWufq4JJb+akO6MVUjTvs
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/users/tests/data/list_users_options.json:
--------------------------------------------------------------------------------
1 | {
2 | "page_size": 2,
3 | "_embedded": {
4 | "users": [
5 | {
6 | "id": "USR-37a8299f-eaad-417c-a0b3-431b6555c4be",
7 | "name": "my_other_user_name",
8 | "display_name": "My Other User Name",
9 | "_links": {
10 | "self": {
11 | "href": "https://api-us-3.vonage.com/v1/users/USR-37a8299f-eaad-417c-a0b3-431b6555c4be"
12 | }
13 | }
14 | },
15 | {
16 | "id": "USR-5ab17d58-b8b3-427d-ac42-c31dab7ef422",
17 | "name": "my_user_name",
18 | "display_name": "My User Name",
19 | "_links": {
20 | "self": {
21 | "href": "https://api-us-3.vonage.com/v1/users/USR-5ab17d58-b8b3-427d-ac42-c31dab7ef422"
22 | }
23 | }
24 | }
25 | ]
26 | },
27 | "_links": {
28 | "first": {
29 | "href": "https://api-us-3.vonage.com/v1/users?page_size=2"
30 | },
31 | "self": {
32 | "href": "https://api-us-3.vonage.com/v1/users?page_size=2&cursor=ItiNOQpJ7IOaL%2FvgHcixE8j8yw8VV0viPWw9nZEeO4%2Fp2DrDr4Qa7CtLAi5ST94XVpiwIJvkUBJ1U%2BL4S%2BK3cSLht3QkP3hmL1pKgkNGW6IdOzHGkpr7v0WsMOY%3D"
33 | },
34 | "next": {
35 | "href": "https://api-us-3.vonage.com/v1/users?page_size=2&cursor=Rv1d7qE3lDuOuwSFjRGHJ2JpKG28CdI1iNjSKNwy0NIr7uicrn7SGpIyaDtvkEEBfyH5xyjSonpeoYNLdw19SQ%3D%3D"
36 | },
37 | "prev": {
38 | "href": "https://api-us-3.vonage.com/v1/users?page_size=2&cursor=6nFju6mYCT5FYbsnxvlJ4XFD1ekcwh6DP0%2BT5BVLvRdZTsqB0EA9j%2B0Bwfpr63xTF%2BZVe7R9QHqv2wH6nQhf7hFz%2B0Ux3g%3D%3D"
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/video/tests/data/list_archives.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "items": [
4 | {
5 | "id": "5b1521e6-115f-4efd-bed9-e527b87f0699",
6 | "status": "paused",
7 | "name": "first archive test",
8 | "reason": "",
9 | "sessionId": "test_session_id",
10 | "applicationId": "test_application_id",
11 | "createdAt": 1727871263000,
12 | "size": 0,
13 | "duration": 0,
14 | "outputMode": "composed",
15 | "streamMode": "manual",
16 | "hasAudio": true,
17 | "hasVideo": true,
18 | "hasTranscription": false,
19 | "sha256sum": "",
20 | "password": "",
21 | "updatedAt": 1727871264000,
22 | "multiArchiveTag": "my-multi-archive",
23 | "event": "archive",
24 | "resolution": "1280x720",
25 | "url": null
26 | },
27 | {
28 | "id": "a9cdeb69-f6cf-408b-9197-6f99e6eac5aa",
29 | "status": "available",
30 | "name": "first archive test",
31 | "reason": "session ended",
32 | "sessionId": "test_session_id",
33 | "applicationId": "test_application_id",
34 | "createdAt": 1727870435000,
35 | "size": 0,
36 | "duration": 134,
37 | "outputMode": "composed",
38 | "streamMode": "manual",
39 | "hasAudio": true,
40 | "hasVideo": true,
41 | "hasTranscription": false,
42 | "sha256sum": "test_sha256_sum",
43 | "password": "",
44 | "updatedAt": 1727870572000,
45 | "multiArchiveTag": "my-multi-archive",
46 | "event": "archive",
47 | "resolution": "1280x720",
48 | "url": "https://example.com/archive.mp4",
49 | "maxBitrate": 2000000
50 | }
51 | ]
52 | }
--------------------------------------------------------------------------------
/number_insight/src/vonage_number_insight/requests.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel
4 | from vonage_utils.types import PhoneNumber
5 |
6 |
7 | class BasicInsightRequest(BaseModel):
8 | """Model for a basic number insight request.
9 |
10 | Args:
11 | number (PhoneNumber): The phone number to get insight information for.
12 | country (str, Optional): The country code for the phone number.
13 | """
14 |
15 | number: PhoneNumber
16 | country: Optional[str] = None
17 |
18 |
19 | class StandardInsightRequest(BasicInsightRequest):
20 | """Model for a standard number insight request.
21 |
22 | Args:
23 | number (PhoneNumber): The phone number to get insight information for.
24 | country (str, Optional): The country code for the phone number.
25 | cnam (bool, Optional): Whether to include the Caller ID Name (CNAM) with the response.
26 | """
27 |
28 | cnam: Optional[bool] = None
29 |
30 |
31 | class AdvancedAsyncInsightRequest(StandardInsightRequest):
32 | """Model for an advanced asynchronous number insight request.
33 |
34 | Args:
35 | number (PhoneNumber): The phone number to get insight information for.
36 | callback (str): The URL to send the asynchronous response to.
37 | country (str, Optional): The country code for the phone number.
38 | cnam (bool, Optional): Whether to include the Caller ID Name (CNAM) with the response.
39 | """
40 |
41 | callback: str
42 |
43 |
44 | class AdvancedSyncInsightRequest(StandardInsightRequest):
45 | """Model for an advanced synchronous number insight request.
46 |
47 | Args:
48 | number (PhoneNumber): The phone number to get insight information for.
49 | country (str, Optional): The country code for the phone number.
50 | cnam (bool, Optional): Whether to include the Caller ID Name (CNAM) with the response.
51 | """
52 |
--------------------------------------------------------------------------------
/sms/src/vonage_sms/responses.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | from pydantic import BaseModel, Field
4 |
5 |
6 | class MessageResponse(BaseModel):
7 | """Individual message response model.
8 |
9 | Args:
10 | to (str): The recipient's phone number in E.164 format.
11 | message_id (str): The message ID.
12 | status (str): The status of the message.
13 | remaining_balance (str): The estimated remaining balance.
14 | message_price (str): The estimated message cost.
15 | network (str): The estimated ID of the network of the recipient
16 | client_ref (str, Optional): If a `client_ref` was included when sending the SMS,
17 | this field will be included and hold the value that was sent.
18 | account_ref (str, Optional): An optional string used to identify separate
19 | accounts using the SMS endpoint for billing purposes. To use this feature,
20 | please email support.
21 | """
22 |
23 | to: Optional[str] = None
24 | message_id: Optional[str] = Field(None, validation_alias='message-id')
25 | status: Optional[str] = None
26 | remaining_balance: Optional[str] = Field(None, validation_alias='remaining-balance')
27 | message_price: Optional[str] = Field(None, validation_alias='message-price')
28 | network: Optional[str] = None
29 | client_ref: Optional[str] = Field(None, validation_alias='client-ref')
30 | account_ref: Optional[str] = Field(None, validation_alias='account-ref')
31 |
32 |
33 | class SmsResponse(BaseModel):
34 | """Response recieved after sending an SMS.
35 |
36 | Args:
37 | message_count (str): The number of messages sent.
38 | messages (list[MessageResponse]): A list of individual message responses. See
39 | `MessageResponse` for more information.
40 | """
41 |
42 | message_count: str = Field(..., validation_alias='message-count')
43 | messages: list[MessageResponse]
44 |
--------------------------------------------------------------------------------
/vonage_utils/src/vonage_utils/utils.py:
--------------------------------------------------------------------------------
1 | from re import search
2 | from typing import Union
3 |
4 | from vonage_utils.errors import InvalidPhoneNumberError, InvalidPhoneNumberTypeError
5 |
6 |
7 | def format_phone_number(number: Union[str, int]) -> str:
8 | """Formats a phone number by removing all non-numeric characters and leading zeros.
9 |
10 | Args:
11 | number (str, int): The phone number to format.
12 |
13 | Returns:
14 | str: The formatted phone number.
15 |
16 | Raises:
17 | InvalidPhoneNumberError: If the phone number is invalid.
18 | InvalidPhoneNumberTypeError: If the phone number is not a string or an integer.
19 | """
20 | if type(number) is not str:
21 | if type(number) is int:
22 | number = str(number)
23 | else:
24 | raise InvalidPhoneNumberTypeError(
25 | f'The phone number provided has an invalid type. You provided: "{type(number)}". Must be a string or an integer.'
26 | )
27 |
28 | # Remove all non-numeric characters and leading zeros
29 | formatted_number = ''.join(filter(str.isdigit, number)).lstrip('0')
30 |
31 | if search(r'^[1-9]\d{6,14}$', formatted_number):
32 | return formatted_number
33 | raise InvalidPhoneNumberError(
34 | f'Invalid phone number provided. You provided: "{number}".\n'
35 | 'Use the E.164 format and start with the country code, e.g. "447700900000".'
36 | )
37 |
38 |
39 | def remove_none_values(my_dataclass) -> dict:
40 | """A dict_factory that can be passed into the dataclass.asdict() method to remove None
41 | values from a dict serialized from the dataclass my_dataclass.
42 |
43 | Args:
44 | my_dataclass (dataclass): A dataclass instance
45 |
46 | Returns:
47 | A dict based on the dataclass, excluding any key-value pairs where the
48 | value is None.
49 | """
50 | return {k: v for (k, v) in my_dataclass if v is not None}
51 |
--------------------------------------------------------------------------------
/jwt/README.md:
--------------------------------------------------------------------------------
1 | # Vonage JWT Generator for Python
2 |
3 | This package (`vonage-jwt`) provides functionality to generate a JWT in Python code.
4 |
5 | It is used by the [Vonage Python SDK](https://github.com/Vonage/vonage-python-sdk), specifically by the `vonage-http-client` package, to generate JWTs for authentication. Thus, it doesn't require manual installation or configuration unless you're using this package independently of an SDK.
6 |
7 | For full API documentation, refer to the [Vonage developer documentation](https://developer.vonage.com).
8 |
9 | - [Installation](#installation)
10 | - [Generating JWTs](#generating-jwts)
11 | - [Verifying a JWT signature](#verifying-a-jwt-signature)
12 |
13 | ## Installation
14 |
15 | Install from the Python Package Index with pip:
16 |
17 | ```bash
18 | pip install vonage-jwt
19 | ```
20 |
21 | ## Generating JWTs
22 |
23 | This 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.
24 |
25 | It can also be used as a standalone JWT generator for use with Vonage APIs, like so:
26 |
27 | ### Import the `JwtClient` object
28 |
29 | ```python
30 | from vonage_jwt import JwtClient
31 | ```
32 |
33 | ### Create a `JwtClient` object
34 |
35 | ```python
36 | jwt_client = JwtClient(application_id, private_key)
37 | ```
38 |
39 | ### Generate a JWT using the provided application id and private key
40 |
41 | ```python
42 | jwt_client.generate_application_jwt()
43 | ```
44 |
45 | Optional JWT claims can be provided in a python dictionary:
46 |
47 | ```python
48 | claims = {'jti': 'asdfzxcv1234', 'nbf': now + 100}
49 | jwt_client.generate_application_jwt(claims)
50 | ```
51 |
52 | ## Verifying a JWT signature
53 |
54 | You can use the `verify_jwt.verify_signature` method to verify a JWT signature is valid.
55 |
56 | ```python
57 | from vonage_jwt import verify_signature
58 |
59 | verify_signature(TOKEN, SIGNATURE_SECRET) # Returns a boolean
60 | ```
61 |
--------------------------------------------------------------------------------
/users/README.md:
--------------------------------------------------------------------------------
1 | # Vonage Users Package
2 |
3 | This package contains the code to use Vonage's Users API in Python.
4 |
5 | It includes methods for managing users.
6 |
7 | ## Usage
8 |
9 | It is recommended to use this as part of the main `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`.
10 |
11 | ### List Users
12 |
13 | With 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.
14 |
15 | ```python
16 | from vonage_users import ListUsersRequest
17 |
18 | users, _ = vonage_client.users.list_users()
19 |
20 | # With options
21 | params = ListUsersRequest(
22 | page_size=10,
23 | cursor=my_cursor,
24 | order='desc',
25 | )
26 | users, next_cursor = vonage_client.users.list_users(params)
27 | ```
28 |
29 | ### Create a New User
30 |
31 | ```python
32 | from vonage_users import User, Channels, SmsChannel
33 | user_options = User(
34 | name='my_user_name',
35 | display_name='My User Name',
36 | properties={'custom_key': 'custom_value'},
37 | channels=Channels(sms=[SmsChannel(number='1234567890')]),
38 | )
39 | user = vonage_client.users.create_user(user_options)
40 | ```
41 |
42 | ### Get a User
43 |
44 | ```python
45 | user = client.users.get_user('USR-87e3e6b0-cd7b-45ef-a0a7-bcd5566a672b')
46 | user_as_dict = user.model_dump(exclude_none=True)
47 | ```
48 |
49 | ### Update a User
50 | ```python
51 | from vonage_users import User, Channels, SmsChannel, WhatsappChannel
52 | user_options = User(
53 | name='my_user_name',
54 | display_name='My User Name',
55 | properties={'custom_key': 'custom_value'},
56 | channels=Channels(sms=[SmsChannel(number='1234567890')], whatsapp=[WhatsappChannel(number='9876543210')]),
57 | )
58 | user = vonage_client.users.update_user(id, user_options)
59 | ```
60 |
61 | ### Delete a User
62 |
63 | ```python
64 | vonage_client.users.delete_user(id)
65 | ```
--------------------------------------------------------------------------------
/testutils/testutils.py:
--------------------------------------------------------------------------------
1 | from os.path import dirname, join
2 | from typing import Literal
3 |
4 | import responses
5 | from pydantic import validate_call
6 |
7 |
8 | def _load_mock_data(caller_file_path: str, mock_path: str):
9 | """Load mock data from a file."""
10 |
11 | try:
12 | with open(join(dirname(caller_file_path), 'data', mock_path)) as file:
13 | return file.read()
14 | except UnicodeDecodeError:
15 | with open(join(dirname(caller_file_path), 'data', mock_path), 'rb') as file:
16 | return file.read()
17 |
18 |
19 | def _filter_none_values(data: dict) -> dict:
20 | """Filter out None values from a dictionary."""
21 |
22 | return {k: v for (k, v) in data.items() if v is not None}
23 |
24 |
25 | @validate_call
26 | def build_response(
27 | file_path: str,
28 | method: Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE'],
29 | url: str,
30 | mock_path: str = None,
31 | status_code: int = 200,
32 | content_type: str = 'application/json',
33 | match: list = None,
34 | ):
35 | """Build a response for a mock request.
36 |
37 | Args:
38 | file_path (str): The path to the file calling this function.
39 | method (Literal['GET', 'POST', 'PATCH', 'PUT', 'DELETE']): The HTTP method.
40 | url (str): The URL to match.
41 | mock_path (str, optional): The path to the mock data file.
42 | status_code (int, optional): The status code to return.
43 | content_type (str, optional): The content type to return.
44 | match (list, optional): The match parameters.
45 | """
46 |
47 | body = _load_mock_data(file_path, mock_path) if mock_path else None
48 | responses.add(
49 | **_filter_none_values(
50 | {
51 | 'method': method,
52 | 'url': url,
53 | 'body': body,
54 | 'status': status_code,
55 | 'content_type': content_type,
56 | 'match': match,
57 | }
58 | )
59 | )
60 |
--------------------------------------------------------------------------------
/verify/README.md:
--------------------------------------------------------------------------------
1 | # Vonage Verify Package
2 |
3 | This package contains the code to use [Vonage's Verify API](https://developer.vonage.com/en/verify/overview) in Python. This package includes methods for working with 2-factor authentication (2FA) messages sent via SMS, Voice, WhatsApp and Email. You can also make Silent Authentication requests with Verify to give your end user a more seamless experience.
4 |
5 | ## Usage
6 |
7 | It is recommended to use this as part of the main `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`.
8 |
9 | ### Make a Verify Request
10 |
11 | ```python
12 | from vonage_verify import VerifyRequest, SmsChannel
13 | # All channels have associated models
14 | sms_channel = SmsChannel(to='1234567890')
15 | params = {
16 | 'brand': 'Vonage',
17 | 'workflow': [sms_channel],
18 | }
19 | verify_request = VerifyRequest(**params)
20 |
21 | response = vonage_client.verify.start_verification(verify_request)
22 | ```
23 |
24 | If 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.
25 |
26 | ```python
27 | silent_auth_channel = SilentAuthChannel(channel=ChannelType.SILENT_AUTH, to='1234567890')
28 | sms_channel = SmsChannel(to='1234567890')
29 | params = {
30 | 'brand': 'Vonage',
31 | 'workflow': [silent_auth_channel, sms_channel],
32 | }
33 | verify_request = VerifyRequest(**params)
34 |
35 | response = vonage_client.verify.start_verification(verify_request)
36 | ```
37 |
38 | ### Check a Verification Code
39 |
40 | ```python
41 | vonage_client.verify.check_code(request_id='my_request_id', code='1234')
42 | ```
43 |
44 | ### Cancel a Verification
45 |
46 | ```python
47 | vonage_client.verify.cancel_verification('my_request_id')
48 | ```
49 |
50 | ### Trigger the Next Workflow Event
51 |
52 | ```python
53 | vonage_client.verify.trigger_next_workflow('my_request_id')
54 | ```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/python
2 |
3 | ### Python ###
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | env/
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | wheels/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .coverage
45 | .coverage.*
46 | .coveralls.*
47 | .cache
48 | nosetests.xml
49 | coverage.xml
50 | *,cover
51 | .hypothesis/
52 |
53 | # Translations
54 | *.mo
55 | *.pot
56 |
57 | # Django stuff:
58 | *.log
59 | local_settings.py
60 |
61 | # Flask stuff:
62 | instance/
63 | .webassets-cache
64 |
65 | # Scrapy stuff:
66 | .scrapy
67 |
68 | # Sphinx documentation
69 | docs/_build/
70 |
71 | # PyBuilder
72 | target/
73 |
74 | # Jupyter Notebook
75 | .ipynb_checkpoints
76 |
77 | # pyenv
78 | .python-version
79 |
80 | # celery beat schedule file
81 | celerybeat-schedule
82 |
83 | # SageMath parsed files
84 | *.sage.py
85 |
86 | # dotenv
87 | .env
88 |
89 | # virtualenv
90 | .venv*
91 | venv*
92 | ENV*
93 |
94 | # Spyder project settings
95 | .spyderproject
96 | .spyproject
97 |
98 | # Rope project settings
99 | .ropeproject
100 |
101 | # mkdocs documentation
102 | /site
103 |
104 | .requirements.txt
105 | *_quickstart*
106 |
107 | .DS_Store
108 | .vscode
109 | .idea
110 | .pypirc
111 | .pytest_cache
112 | html/
113 | .mutmut-cache
114 | _test_scripts/
115 | _dev_scripts/
116 |
117 | # Pants workspace files
118 | /.pants.*
119 | /dist/
120 | /.pids
121 |
--------------------------------------------------------------------------------