Coverage for fingerprint_server_sdk/models/event.py: 72%
147 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-14 10:45 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-14 10:45 +0000
1"""
2Server API
3Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios.
4Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device.
5The API also supports collection of Automation Intelligence for requests to your server in edge, pre-origin, or middleware contexts.
7The version of the OpenAPI document: 4
8Contact: support@fingerprint.com
9Generated by OpenAPI Generator (https://openapi-generator.tech)
11Do not edit the class manually.
12""" # noqa: E501
14from __future__ import annotations
16import json
17import pprint
18import re # noqa: F401
19from typing import Annotated, Any, ClassVar, Optional, Union
21from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
22from typing_extensions import Self
24from fingerprint_server_sdk.models.bot_info import BotInfo
25from fingerprint_server_sdk.models.bot_result import BotResult
26from fingerprint_server_sdk.models.browser_details import BrowserDetails
27from fingerprint_server_sdk.models.event_rule_action import EventRuleAction
28from fingerprint_server_sdk.models.identification import Identification
29from fingerprint_server_sdk.models.incremental_identification_status import (
30 IncrementalIdentificationStatus,
31)
32from fingerprint_server_sdk.models.ip_block_list import IPBlockList
33from fingerprint_server_sdk.models.ip_info import IPInfo
34from fingerprint_server_sdk.models.labels_inner import LabelsInner
35from fingerprint_server_sdk.models.proximity import Proximity
36from fingerprint_server_sdk.models.proxy_confidence import ProxyConfidence
37from fingerprint_server_sdk.models.proxy_details import ProxyDetails
38from fingerprint_server_sdk.models.rare_device_percentile_bucket import RareDevicePercentileBucket
39from fingerprint_server_sdk.models.raw_device_attributes import RawDeviceAttributes
40from fingerprint_server_sdk.models.sdk import SDK
41from fingerprint_server_sdk.models.supplementary_id_high_recall import SupplementaryIDHighRecall
42from fingerprint_server_sdk.models.tampering_confidence import TamperingConfidence
43from fingerprint_server_sdk.models.tampering_details import TamperingDetails
44from fingerprint_server_sdk.models.velocity import Velocity
45from fingerprint_server_sdk.models.vpn_confidence import VpnConfidence
46from fingerprint_server_sdk.models.vpn_methods import VpnMethods
49class Event(BaseModel):
50 """
51 Contains results from Fingerprint Identification and all active Smart Signals.
52 """
54 event_id: StrictStr = Field(
55 description="Unique identifier of the user's request. The first portion of the event_id is a unix epoch milliseconds timestamp. "
56 )
57 timestamp: StrictInt = Field(
58 description='Timestamp of the event with millisecond precision in Unix time.'
59 )
60 incremental_identification_status: Optional[IncrementalIdentificationStatus] = None
61 linked_id: Optional[StrictStr] = Field(
62 default=None, description='A customer-provided id that was sent with the request.'
63 )
64 environment_id: Optional[StrictStr] = Field(
65 default=None, description='Environment Id of the event.'
66 )
67 suspect: Optional[StrictBool] = Field(
68 default=None,
69 description='Field is `true` if you have previously set the `suspect` flag for this event using the [Server API Update event endpoint](https://docs.fingerprint.com/reference/server-api-v4-update-event).',
70 )
71 sdk: Optional[SDK] = None
72 replayed: Optional[StrictBool] = Field(
73 default=None,
74 description='`true` if we determined that this payload was replayed, `false` otherwise. ',
75 )
76 identification: Optional[Identification] = None
77 supplementary_id_high_recall: Optional[SupplementaryIDHighRecall] = None
78 tags: Optional[dict[str, Any]] = Field(
79 default=None,
80 description='A customer-provided value or an object that was sent with the identification request or updated later.',
81 )
82 url: Optional[StrictStr] = Field(
83 default=None, description='Page URL from which the request was sent.'
84 )
85 bundle_id: Optional[StrictStr] = Field(
86 default=None,
87 description='Bundle Id of the iOS application integrated with the Fingerprint SDK for the event. ',
88 )
89 package_name: Optional[StrictStr] = Field(
90 default=None,
91 description='Package name of the Android application integrated with the Fingerprint SDK for the event. ',
92 )
93 ip_address: Optional[StrictStr] = Field(
94 default=None, description='IP address of the requesting browser or bot.'
95 )
96 user_agent: Optional[StrictStr] = Field(default=None, description='User Agent of the client.')
97 device: Optional[StrictStr] = Field(
98 default=None,
99 description='Device model or family extracted from the user agent string. On web, this field is also present inside `browser_details`. ',
100 )
101 os: Optional[StrictStr] = Field(
102 default=None,
103 description='Operating system family extracted from the user agent string. On web, this field is also present inside `browser_details`. ',
104 )
105 os_version: Optional[StrictStr] = Field(
106 default=None,
107 description='Operating system version string extracted from the user agent string. On web, this field is also present inside `browser_details`. ',
108 )
109 client_referrer: Optional[StrictStr] = Field(
110 default=None,
111 description='Client Referrer field corresponds to the `document.referrer` field gathered during an identification request. The value is an empty string if the user navigated to the page directly (not through a link, but, for example, by using a bookmark). ',
112 )
113 browser_details: Optional[BrowserDetails] = None
114 proximity: Optional[Proximity] = None
115 bot: Optional[BotResult] = None
116 bot_type: Optional[StrictStr] = Field(
117 default=None, description='Additional classification of the bot type if detected. '
118 )
119 bot_info: Optional[BotInfo] = None
120 cloned_app: Optional[StrictBool] = Field(
121 default=None,
122 description='Android specific cloned application detection. There are 2 values: * `true` - Presence of app cloners work detected (e.g. fully cloned application found or launch of it inside of a not main working profile detected). * `false` - No signs of cloned application detected or the client is not Android. ',
123 )
124 developer_tools: Optional[StrictBool] = Field(
125 default=None,
126 description='`true` if the browser has DevTools open (Chrome, Firefox) or the Android/iOS device has Developer Tools enabled, `false` otherwise. ',
127 )
128 emulator: Optional[StrictBool] = Field(
129 default=None,
130 description='Android specific emulator detection. There are 2 values: * `true` - Emulated environment detected (e.g. launch inside of AVD). * `false` - No signs of emulated environment detected or the client is not Android. ',
131 )
132 factory_reset_timestamp: Optional[StrictInt] = Field(
133 default=None,
134 description='The time of the most recent factory reset that happened on the **mobile device** is expressed as Unix epoch time. When a factory reset cannot be detected on the mobile device or when the request is initiated from a browser, this field will correspond to the *epoch* time (i.e 1 Jan 1970 UTC) as a value of 0. See [Factory Reset Detection](https://docs.fingerprint.com/docs/smart-signals-reference#factory-reset-detection) to learn more about this Smart Signal. ',
135 )
136 frida: Optional[StrictBool] = Field(
137 default=None,
138 description='[Frida](https://frida.re/docs/) detection for Android and iOS devices. There are 2 values: * `true` - Frida detected * `false` - No signs of Frida or the client is not a mobile device. ',
139 )
140 ip_blocklist: Optional[IPBlockList] = None
141 ip_info: Optional[IPInfo] = None
142 proxy: Optional[StrictBool] = Field(
143 default=None,
144 description='IP address was used by a public proxy provider or belonged to a known recent residential proxy ',
145 )
146 proxy_confidence: Optional[ProxyConfidence] = None
147 proxy_details: Optional[ProxyDetails] = None
148 proxy_ml_score: Optional[
149 Union[
150 Annotated[float, Field(le=1, strict=True, ge=0)],
151 Annotated[int, Field(le=1, strict=True, ge=0)],
152 ]
153 ] = Field(
154 default=None,
155 description='Machine learning–based proxy score, represented as a floating-point value between 0 and 1 (inclusive), with up to three decimal places of precision. A higher score means a higher confidence in the positive `proxy` detection result. This Smart Signal is currently in beta and only available to select customers. If you are interested, please [contact our support team](https://fingerprint.com/support/). ',
156 )
157 incognito: Optional[StrictBool] = Field(
158 default=None,
159 description='`true` if we detected incognito mode used in the browser, `false` otherwise. ',
160 )
161 jailbroken: Optional[StrictBool] = Field(
162 default=None,
163 description='iOS specific jailbreak detection. There are 2 values: * `true` - Jailbreak detected. * `false` - No signs of jailbreak or the client is not iOS. ',
164 )
165 location_spoofing: Optional[StrictBool] = Field(
166 default=None,
167 description='Flag indicating whether the request came from a mobile device with location spoofing enabled.',
168 )
169 mitm_attack: Optional[StrictBool] = Field(
170 default=None,
171 description="* `true` - When requests made from your users' mobile devices to Fingerprint servers have been intercepted and potentially modified. * `false` - Otherwise or when the request originated from a browser. See [MitM Attack Detection](https://docs.fingerprint.com/docs/smart-signals-reference#mitm-attack-detection) to learn more about this Smart Signal. ",
172 )
173 privacy_settings: Optional[StrictBool] = Field(
174 default=None,
175 description='`true` if the request is from a privacy aware browser (e.g. Tor) or from a browser in which fingerprinting is blocked. Otherwise `false`. ',
176 )
177 root_apps: Optional[StrictBool] = Field(
178 default=None,
179 description="Android specific root management apps detection. There are 2 values: * `true` - Root Management Apps detected (e.g. Magisk). * `false` - No Root Management Apps detected or the client isn't Android. ",
180 )
181 rule_action: Optional[EventRuleAction] = None
182 simulator: Optional[StrictBool] = Field(
183 default=None,
184 description='iOS specific simulator detection. There are 2 values: * `true` - Simulator environment detected. * `false` - No signs of simulator or the client is not iOS. ',
185 )
186 suspect_score: Optional[StrictInt] = Field(
187 default=None,
188 description='Suspect Score is an easy way to integrate Smart Signals into your fraud protection work flow. It is a weighted representation of all Smart Signals present in the payload that helps identify suspicious activity. The value range is [0; S] where S is sum of all Smart Signals weights. See more details here: https://docs.fingerprint.com/docs/suspect-score ',
189 )
190 tampering: Optional[StrictBool] = Field(
191 default=None,
192 description='The field can be used as a standalone flag for tampering detection. Alternatively, the more granular fields documented below can be used for workflows that require more context. * `true` if tampering is detected through an anomalous browser signature, anti-detect browser detection, or other tampering-related methods * `false` if none of the tampering checks return a positive result ',
193 )
194 tampering_confidence: Optional[TamperingConfidence] = None
195 tampering_ml_score: Optional[
196 Union[
197 Annotated[float, Field(le=1, strict=True, ge=0)],
198 Annotated[int, Field(le=1, strict=True, ge=0)],
199 ]
200 ] = Field(
201 default=None,
202 description='The output of this model is captured as tampering_ml_score, a number indicating how likely an event is coming from an anti detect browser. Values close to 1 signify higher confidence and we consider anything above the threshold of 0.8 to be actionable (the result and anti_detect_browser fields conveniently captures that fact) ',
203 )
204 tampering_details: Optional[TamperingDetails] = None
205 velocity: Optional[Velocity] = None
206 virtual_machine: Optional[StrictBool] = Field(
207 default=None,
208 description='`true` if the request came from a browser running inside a virtual machine (e.g. VMWare), `false` otherwise. ',
209 )
210 virtual_machine_ml_score: Optional[
211 Union[
212 Annotated[float, Field(le=1, strict=True, ge=0)],
213 Annotated[int, Field(le=1, strict=True, ge=0)],
214 ]
215 ] = Field(
216 default=None,
217 description='Machine learning–based virtual machine score, represented as a floating-point value between 0 and 1 (inclusive), with up to three decimal places of precision. A higher score means a higher confidence in the positive `virtual_machine` detection result. This Smart Signal is currently in beta and only available to select customers. If you are interested, please [contact our support team](https://fingerprint.com/support/). ',
218 )
219 vpn: Optional[StrictBool] = Field(
220 default=None,
221 description='VPN or other anonymizing service has been used when sending the request. ',
222 )
223 vpn_confidence: Optional[VpnConfidence] = None
224 vpn_ml_score: Optional[
225 Union[
226 Annotated[float, Field(le=1, strict=True, ge=0)],
227 Annotated[int, Field(le=1, strict=True, ge=0)],
228 ]
229 ] = Field(
230 default=None,
231 description='Machine learning–based VPN score, represented as a floating-point value between 0 and 1 (inclusive), with up to three decimal places of precision. A higher score means a higher confidence in the positive `vpn` detection result. This Smart Signal is currently in beta and only available to select customers. If you are interested, please [contact our support team](https://fingerprint.com/support/). ',
232 )
233 vpn_origin_timezone: Optional[StrictStr] = Field(
234 default=None, description='Local timezone which is used in timezone_mismatch method. '
235 )
236 vpn_origin_country: Optional[StrictStr] = Field(
237 default=None,
238 description='Country of the request (only for Android SDK version >= 2.4.0, ISO 3166 format or unknown). ',
239 )
240 vpn_methods: Optional[VpnMethods] = None
241 high_activity_device: Optional[StrictBool] = Field(
242 default=None,
243 description='Flag indicating if the request came from a high-activity visitor.',
244 )
245 rare_device: Optional[StrictBool] = Field(
246 default=None,
247 description='`true` if the device is considered rare based on its combination of hardware and software attributes. A device is classified as rare if it falls within the top 99.9 percentile (lowest-frequency segment) of observed traffic, or if its configuration has not been previously seen (`not_seen`). > This Smart Signal is currently in beta and only available to select customers. If you are interested, please [contact our support team](https://fingerprint.com/support/). ',
248 )
249 rare_device_percentile_bucket: Optional[RareDevicePercentileBucket] = None
250 raw_device_attributes: Optional[RawDeviceAttributes] = None
251 labels: Optional[list[LabelsInner]] = Field(
252 default=None,
253 description='Each label returns a prediction (true or false) for a specific use case (label field) based on a machine learning score. The machine learning score is determined by a model trained on customer data for that use case. This field is in the beta phase and only available to select customers. If you are interested, please [contact our support team](https://fingerprint.com/support/). ',
254 )
255 __properties: ClassVar[list[str]] = [
256 'event_id',
257 'timestamp',
258 'incremental_identification_status',
259 'linked_id',
260 'environment_id',
261 'suspect',
262 'sdk',
263 'replayed',
264 'identification',
265 'supplementary_id_high_recall',
266 'tags',
267 'url',
268 'bundle_id',
269 'package_name',
270 'ip_address',
271 'user_agent',
272 'device',
273 'os',
274 'os_version',
275 'client_referrer',
276 'browser_details',
277 'proximity',
278 'bot',
279 'bot_type',
280 'bot_info',
281 'cloned_app',
282 'developer_tools',
283 'emulator',
284 'factory_reset_timestamp',
285 'frida',
286 'ip_blocklist',
287 'ip_info',
288 'proxy',
289 'proxy_confidence',
290 'proxy_details',
291 'proxy_ml_score',
292 'incognito',
293 'jailbroken',
294 'location_spoofing',
295 'mitm_attack',
296 'privacy_settings',
297 'root_apps',
298 'rule_action',
299 'simulator',
300 'suspect_score',
301 'tampering',
302 'tampering_confidence',
303 'tampering_ml_score',
304 'tampering_details',
305 'velocity',
306 'virtual_machine',
307 'virtual_machine_ml_score',
308 'vpn',
309 'vpn_confidence',
310 'vpn_ml_score',
311 'vpn_origin_timezone',
312 'vpn_origin_country',
313 'vpn_methods',
314 'high_activity_device',
315 'rare_device',
316 'rare_device_percentile_bucket',
317 'raw_device_attributes',
318 'labels',
319 ]
321 model_config = ConfigDict(
322 populate_by_name=True,
323 validate_assignment=True,
324 protected_namespaces=(),
325 )
327 def to_str(self) -> str:
328 """Returns the string representation of the model using alias"""
329 return pprint.pformat(self.model_dump(by_alias=True))
331 def to_json(self) -> str:
332 """Returns the JSON representation of the model using alias"""
333 # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
334 return json.dumps(self.to_dict())
336 @classmethod
337 def from_json(cls, json_str: str) -> Optional[Self]:
338 """Create an instance of Event from a JSON string"""
339 return cls.from_dict(json.loads(json_str))
341 def to_dict(self) -> dict[str, Any]:
342 """Return the dictionary representation of the model using alias.
344 This has the following differences from calling pydantic's
345 `self.model_dump(by_alias=True)`:
347 * `None` is only added to the output dict for nullable fields that
348 were set at model initialization. Other fields with value `None`
349 are ignored.
350 """
351 excluded_fields: set[str] = set([])
353 _dict = self.model_dump(
354 by_alias=True,
355 exclude=excluded_fields,
356 exclude_none=True,
357 )
358 # override the default output from pydantic by calling `to_dict()` of sdk
359 if self.sdk:
360 _dict['sdk'] = self.sdk.to_dict()
361 # override the default output from pydantic by calling `to_dict()` of identification
362 if self.identification:
363 _dict['identification'] = self.identification.to_dict()
364 # override the default output from pydantic by calling `to_dict()` of supplementary_id_high_recall
365 if self.supplementary_id_high_recall:
366 _dict['supplementary_id_high_recall'] = self.supplementary_id_high_recall.to_dict()
367 # override the default output from pydantic by calling `to_dict()` of browser_details
368 if self.browser_details:
369 _dict['browser_details'] = self.browser_details.to_dict()
370 # override the default output from pydantic by calling `to_dict()` of proximity
371 if self.proximity:
372 _dict['proximity'] = self.proximity.to_dict()
373 # override the default output from pydantic by calling `to_dict()` of bot_info
374 if self.bot_info:
375 _dict['bot_info'] = self.bot_info.to_dict()
376 # override the default output from pydantic by calling `to_dict()` of ip_blocklist
377 if self.ip_blocklist:
378 _dict['ip_blocklist'] = self.ip_blocklist.to_dict()
379 # override the default output from pydantic by calling `to_dict()` of ip_info
380 if self.ip_info:
381 _dict['ip_info'] = self.ip_info.to_dict()
382 # override the default output from pydantic by calling `to_dict()` of proxy_details
383 if self.proxy_details:
384 _dict['proxy_details'] = self.proxy_details.to_dict()
385 # override the default output from pydantic by calling `to_dict()` of rule_action
386 if self.rule_action:
387 _dict['rule_action'] = self.rule_action.to_dict()
388 # override the default output from pydantic by calling `to_dict()` of tampering_details
389 if self.tampering_details:
390 _dict['tampering_details'] = self.tampering_details.to_dict()
391 # override the default output from pydantic by calling `to_dict()` of velocity
392 if self.velocity:
393 _dict['velocity'] = self.velocity.to_dict()
394 # override the default output from pydantic by calling `to_dict()` of vpn_methods
395 if self.vpn_methods:
396 _dict['vpn_methods'] = self.vpn_methods.to_dict()
397 # override the default output from pydantic by calling `to_dict()` of raw_device_attributes
398 if self.raw_device_attributes:
399 _dict['raw_device_attributes'] = self.raw_device_attributes.to_dict()
400 # override the default output from pydantic by calling `to_dict()` of each item in labels (list)
401 _items = []
402 if self.labels:
403 for _item_labels in self.labels:
404 if _item_labels:
405 _items.append(_item_labels.to_dict())
406 _dict['labels'] = _items
407 return _dict
409 @classmethod
410 def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]:
411 """Create an instance of Event from a dict"""
412 if obj is None:
413 return None
415 if not isinstance(obj, dict):
416 return cls.model_validate(obj)
418 _obj = cls.model_validate(
419 {
420 'event_id': obj.get('event_id'),
421 'timestamp': obj.get('timestamp'),
422 'incremental_identification_status': obj.get('incremental_identification_status'),
423 'linked_id': obj.get('linked_id'),
424 'environment_id': obj.get('environment_id'),
425 'suspect': obj.get('suspect'),
426 'sdk': SDK.from_dict(obj['sdk']) if obj.get('sdk') is not None else None,
427 'replayed': obj.get('replayed'),
428 'identification': Identification.from_dict(obj['identification'])
429 if obj.get('identification') is not None
430 else None,
431 'supplementary_id_high_recall': SupplementaryIDHighRecall.from_dict(
432 obj['supplementary_id_high_recall']
433 )
434 if obj.get('supplementary_id_high_recall') is not None
435 else None,
436 'tags': obj.get('tags'),
437 'url': obj.get('url'),
438 'bundle_id': obj.get('bundle_id'),
439 'package_name': obj.get('package_name'),
440 'ip_address': obj.get('ip_address'),
441 'user_agent': obj.get('user_agent'),
442 'device': obj.get('device'),
443 'os': obj.get('os'),
444 'os_version': obj.get('os_version'),
445 'client_referrer': obj.get('client_referrer'),
446 'browser_details': BrowserDetails.from_dict(obj['browser_details'])
447 if obj.get('browser_details') is not None
448 else None,
449 'proximity': Proximity.from_dict(obj['proximity'])
450 if obj.get('proximity') is not None
451 else None,
452 'bot': obj.get('bot'),
453 'bot_type': obj.get('bot_type'),
454 'bot_info': BotInfo.from_dict(obj['bot_info'])
455 if obj.get('bot_info') is not None
456 else None,
457 'cloned_app': obj.get('cloned_app'),
458 'developer_tools': obj.get('developer_tools'),
459 'emulator': obj.get('emulator'),
460 'factory_reset_timestamp': obj.get('factory_reset_timestamp'),
461 'frida': obj.get('frida'),
462 'ip_blocklist': IPBlockList.from_dict(obj['ip_blocklist'])
463 if obj.get('ip_blocklist') is not None
464 else None,
465 'ip_info': IPInfo.from_dict(obj['ip_info'])
466 if obj.get('ip_info') is not None
467 else None,
468 'proxy': obj.get('proxy'),
469 'proxy_confidence': obj.get('proxy_confidence'),
470 'proxy_details': ProxyDetails.from_dict(obj['proxy_details'])
471 if obj.get('proxy_details') is not None
472 else None,
473 'proxy_ml_score': obj.get('proxy_ml_score'),
474 'incognito': obj.get('incognito'),
475 'jailbroken': obj.get('jailbroken'),
476 'location_spoofing': obj.get('location_spoofing'),
477 'mitm_attack': obj.get('mitm_attack'),
478 'privacy_settings': obj.get('privacy_settings'),
479 'root_apps': obj.get('root_apps'),
480 'rule_action': EventRuleAction.from_dict(obj['rule_action'])
481 if obj.get('rule_action') is not None
482 else None,
483 'simulator': obj.get('simulator'),
484 'suspect_score': obj.get('suspect_score'),
485 'tampering': obj.get('tampering'),
486 'tampering_confidence': obj.get('tampering_confidence'),
487 'tampering_ml_score': obj.get('tampering_ml_score'),
488 'tampering_details': TamperingDetails.from_dict(obj['tampering_details'])
489 if obj.get('tampering_details') is not None
490 else None,
491 'velocity': Velocity.from_dict(obj['velocity'])
492 if obj.get('velocity') is not None
493 else None,
494 'virtual_machine': obj.get('virtual_machine'),
495 'virtual_machine_ml_score': obj.get('virtual_machine_ml_score'),
496 'vpn': obj.get('vpn'),
497 'vpn_confidence': obj.get('vpn_confidence'),
498 'vpn_ml_score': obj.get('vpn_ml_score'),
499 'vpn_origin_timezone': obj.get('vpn_origin_timezone'),
500 'vpn_origin_country': obj.get('vpn_origin_country'),
501 'vpn_methods': VpnMethods.from_dict(obj['vpn_methods'])
502 if obj.get('vpn_methods') is not None
503 else None,
504 'high_activity_device': obj.get('high_activity_device'),
505 'rare_device': obj.get('rare_device'),
506 'rare_device_percentile_bucket': obj.get('rare_device_percentile_bucket'),
507 'raw_device_attributes': RawDeviceAttributes.from_dict(
508 obj['raw_device_attributes']
509 )
510 if obj.get('raw_device_attributes') is not None
511 else None,
512 'labels': [LabelsInner.from_dict(_item) for _item in obj['labels']]
513 if obj.get('labels') is not None
514 else None,
515 }
516 )
517 return _obj