Skip to content

Commit b4a8145

Browse files
committed
feat: Add Identity Insights API
1 parent ea251fe commit b4a8145

File tree

18 files changed

+772
-0
lines changed

18 files changed

+772
-0
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ This is the Python server SDK to help you use Vonage APIs in your Python applica
2020
- [Application API](#application-api)
2121
- [HTTP Client](#http-client)
2222
- [JWT Client](#jwt-client)
23+
- [Identity Insights](#identity-insights)
2324
- [Messages API](#messages-api)
2425
- [Network Number Verification API](#network-number-verification-api)
2526
- [Network Sim Swap API](#network-sim-swap-api)
@@ -403,6 +404,34 @@ from vonage_jwt import verify_signature
403404
verify_signature(TOKEN, SIGNATURE_SECRET) # Returns a boolean
404405
```
405406

407+
## Identity Insights
408+
409+
### Get Insights
410+
411+
```python
412+
from vonage_identity_insights import (
413+
IdentityInsightsRequest,
414+
InsightsRequest,
415+
EmptyInsight,
416+
SimSwapInsight,
417+
)
418+
419+
options = HttpClientOptions(api_host='api-eu.vonage.com', timeout=30)
420+
421+
client = Vonage(auth=auth, http_client_options=options)
422+
423+
request = IdentityInsightsRequest(
424+
phone_number='1234567890',
425+
purpose='FraudPreventionAndDetection',
426+
insights=InsightsRequest(
427+
format=EmptyInsight(),
428+
sim_swap=SimSwapInsight(period=240)
429+
)
430+
)
431+
432+
response = client.identity_insights.get_insights(request)
433+
```
434+
406435
## Messages API
407436

408437
### How to Construct a Message
@@ -1436,6 +1465,7 @@ The following is a list of Vonage APIs and whether the Python SDK provides suppo
14361465
| External Accounts API | Beta ||
14371466
| Media API | Beta ||
14381467
| Messages API | General Availability ||
1468+
| Identity Insights API | General Availability ||
14391469
| Number Insight API | General Availability ||
14401470
| Number Management API | General Availability ||
14411471
| Pricing API | General Availability ||

identity_insights/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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-identity-insights',
8+
dependencies=[
9+
':pyproject',
10+
':readme',
11+
'identity_insights/src/vonage_identity_insights',
12+
],
13+
provides=python_artifact(),
14+
generate_setup=False,
15+
repositories=['@pypi'],
16+
)

identity_insights/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# 1.0.0
2+
- Initial upload

identity_insights/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Vonage Identity Insights Package
2+
3+
This package contains the code to use the [Vonage Identity Insights API](https://developer.vonage.com/en/identity-insights/overview) in Python. The API provides real-time access to a broad range of attributes related to the carrier, subscriber, or device associated with a phone number. To use it you will need a Vonage account. Sign up [for free at vonage.com][signup].
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 Standard Identity Insights Request
10+
11+
```python
12+
from vonage import Vonage, Auth, HttpClientOptions
13+
from vonage_identity_insights import (
14+
IdentityInsightsRequest,
15+
InsightsRequest,
16+
EmptyInsight,
17+
SimSwapInsight,
18+
)
19+
20+
options = HttpClientOptions(api_host="api-eu.vonage.com", timeout=30)
21+
22+
client = Vonage(auth=auth, http_client_options=options)
23+
24+
request = IdentityInsightsRequest(
25+
phone_number="1234567890",
26+
purpose="FraudPreventionAndDetection",
27+
insights=InsightsRequest(
28+
format=EmptyInsight(), sim_swap=SimSwapInsight(period=240)
29+
),
30+
)
31+
32+
response = client.identity_insights.get_insights(request)
33+
34+
```
35+

identity_insights/pyproject.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[project]
2+
name = 'vonage-identity-insights'
3+
dynamic = ["version"]
4+
description = 'Vonage Identity Insights package'
5+
readme = "README.md"
6+
authors = [{ name = "Vonage", email = "[email protected]" }]
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_identity_insights._version.__version__" }
29+
30+
[build-system]
31+
requires = ["setuptools>=61.0", "wheel"]
32+
build-backend = "setuptools.build_meta"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python_sources()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from . import errors
2+
from .identity_insights import IdentityInsights
3+
from .requests import (
4+
IdentityInsightsRequest,
5+
InsightsRequest,
6+
EmptyInsight,
7+
SimSwapInsight,
8+
SubscriberMatchInsight,
9+
LocationVerificationInsight,
10+
Location,
11+
LocationCenter,
12+
)
13+
from .responses import (
14+
IdentityInsightsResponse,
15+
InsightStatus,
16+
)
17+
18+
__all__ = [
19+
"IdentityInsights",
20+
# Requests
21+
"IdentityInsightsRequest",
22+
"InsightsRequest",
23+
"EmptyInsight",
24+
"SimSwapInsight",
25+
"SubscriberMatchInsight",
26+
"LocationVerificationInsight",
27+
"Location",
28+
"LocationCenter",
29+
# Responses
30+
"IdentityInsightsResponse",
31+
"InsightStatus",
32+
"errors",
33+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = "1.0.0"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from vonage_utils.errors import VonageError
2+
3+
4+
class IdentityInsightsError(VonageError):
5+
"""Indicates an error when using the Vonage Identity Insights API."""
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from logging import getLogger
2+
3+
from pydantic import validate_call
4+
from vonage_http_client.http_client import HttpClient
5+
6+
from .errors import IdentityInsightsError
7+
from .requests import IdentityInsightsRequest
8+
from .responses import IdentityInsightsResponse
9+
10+
logger = getLogger("vonage_identity_insights")
11+
12+
13+
class IdentityInsights:
14+
"""Calls Vonage's Identity Insights API."""
15+
16+
def __init__(self, http_client: HttpClient) -> None:
17+
"""Initialize the IdentityInsights client.
18+
19+
Args:
20+
http_client (HttpClient): Configured HTTP client used to make
21+
authenticated requests to the Vonage API.
22+
"""
23+
self._http_client = http_client
24+
self._auth_type = "jwt"
25+
26+
@property
27+
def http_client(self) -> HttpClient:
28+
"""The HTTP client used to make requests to the Vonage Indentity Insights API.
29+
30+
Returns:
31+
HttpClient: The HTTP client used to make requests to the Identity Insights API.
32+
"""
33+
return self._http_client
34+
35+
@validate_call
36+
def get_insights(
37+
self, insights_request: IdentityInsightsRequest
38+
) -> IdentityInsightsResponse:
39+
"""Retrieve identity insights for a phone number.
40+
41+
Sends an aggregated request to the Identity Insights API and returns
42+
the results for each requested insight.
43+
44+
Args:
45+
insights_request (IdentityInsightsRequest): The request object
46+
containing the phone number and the set of identity insights
47+
to retrieve.
48+
49+
Returns:
50+
IdentityInsightsResponse: The response object containing the results
51+
and status of each requested insight.
52+
53+
Raises:
54+
IdentityInsightsError: If the API returns an error response in
55+
`application/problem+json` format.
56+
"""
57+
payload = insights_request.model_dump(exclude_none=True)
58+
59+
response = self._http_client.post(
60+
self._http_client.api_host,
61+
"/v0.1/identity-insights",
62+
payload,
63+
auth_type=self._auth_type,
64+
)
65+
self._check_for_error(response)
66+
67+
return IdentityInsightsResponse(**response)
68+
69+
def _check_for_error(self, response: dict) -> None:
70+
"""Check whether the API response represents an error.
71+
72+
The Identity Insights API returns errors using the
73+
`application/problem+json` format. If such an error is detected, this
74+
method raises an IdentityInsightsError.
75+
76+
Args:
77+
response (dict): Raw response returned by the HTTP client.
78+
79+
Raises:
80+
IdentityInsightsError: If the response contains an error payload.
81+
"""
82+
if "title" in response and "detail" in response:
83+
error_message = f"Error with the following details: {response}"
84+
raise IdentityInsightsError(error_message)

0 commit comments

Comments
 (0)