Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/deprecate-504-events-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fingerprint/python-sdk': minor
---

**events-search**: The `504` response for the Events Search endpoint is deprecated and will no longer be generated by the Server API.
5 changes: 5 additions & 0 deletions .changeset/deprecate-504-events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fingerprint/python-sdk': minor
---

**events**: The `504` response for the Get Event endpoint is deprecated and will no longer be generated by the Server API.
5 changes: 5 additions & 0 deletions .changeset/error-response-503-events-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fingerprint/python-sdk': minor
---

**events-search**: Add `503` Service Temporarily Unavailable response to the Events Search endpoint
5 changes: 5 additions & 0 deletions .changeset/error-response-503-events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@fingerprint/python-sdk': minor
---

**events**: Add `503` Service Temporarily Unavailable response to the Get Event endpoint
8 changes: 8 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"mode": "pre",
"tag": "rc",
Comment thread
erayaydin marked this conversation as resolved.
"initialVersions": {
"@fingerprint/python-sdk": "9.8.0"
},
"changesets": []
}
2 changes: 1 addition & 1 deletion .schema-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v3.8.0
v3.9.0
2 changes: 1 addition & 1 deletion docs/DeviceDetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Native, SDK-collected mobile device identification signals (manufacturer, model,
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**device_manufacturer** | **str** | Raw device manufacturer string as reported by the device OS. Not normalized: casing is vendor-defined (samsung, Xiaomi, OPPO, HUAWEI). Always `Apple` on iOS. | [optional]
**device_model** | **str** | Raw device model identifier, as reported by the mobile OS. | [optional]
**device_model** | **str** | Raw device model identifier, as reported by the mobile OS. On Android, this is the vendor-defined model string (e.g., `SM-G991U`). On iOS, this is an Apple board code (e.g., `D84AP`). | [optional]
**os_version** | **str** | Mobile operating system version. Component count is not fixed and must not be assumed by consumers: iOS always reports `major.minor.patch` (e.g. `17.4.1`), while Android's precision varies by OS era and which raw signal resolved it — `major` only (`9`, `13`) since Android 10 dropped point releases, `major.minor` (`16.1`) from Android 16 (API 36+) reintroducing a minor component, or a genuine `major.minor.patch` (`8.1.0`) on pre-Android 10 devices that shipped real point releases. Never a fabricated/zero-padded component. | [optional]

[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
Expand Down
10 changes: 6 additions & 4 deletions docs/FingerprintApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,10 @@ Name | Type | Description | Notes
**400** | Bad request. The event ID provided is not valid. | - |
**403** | Forbidden. Access to this API is denied. | - |
**404** | Not found. The event ID cannot be found in this workspace's data. | - |
**429** | Too Many Requests. The request is throttled. To protect service stability during rare periods of extreme load, we may return HTTP 429 responses with message `too many search requests` even if you are within your assigned rate limits. | - |
**429** | Too Many Requests. The request is throttled. | - |
**500** | Workspace error. | - |
**504** | Gateway Timeout. Search execution exceeded the allowed timeout window. | - |
**503** | Service Temporarily Unavailable. | - |
**504** | Gateway Timeout. | - |

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

Expand Down Expand Up @@ -404,9 +405,10 @@ Name | Type | Description | Notes
**400** | Bad request. One or more supplied search parameters are invalid, or a required parameter is missing. | - |
**403** | Forbidden. Access to this API is denied. | - |
**404** | Not found. The requested visitor does not exist in this workspace's data. | - |
**429** | Too Many Requests. The request is throttled. To protect service stability during rare periods of extreme load, we may return HTTP 429 responses with message `too many search requests` even if you are within your assigned rate limits. | - |
**429** | Too Many Requests. The request is throttled. | - |
**500** | Workspace error. | - |
**504** | Gateway Timeout. Search execution exceeded the allowed timeout window. | - |
**503** | Service Temporarily Unavailable. | - |
**504** | Gateway Timeout. | - |

[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

Expand Down
6 changes: 6 additions & 0 deletions fingerprint_server_sdk/api/fingerprint_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ def get_event(
'404': 'ErrorResponse',
'429': 'ErrorResponse',
'500': 'ErrorResponse',
'503': 'ErrorResponse',
'504': 'ErrorResponse',
}

Expand Down Expand Up @@ -438,6 +439,7 @@ def get_event_with_http_info(
'404': 'ErrorResponse',
'429': 'ErrorResponse',
'500': 'ErrorResponse',
'503': 'ErrorResponse',
'504': 'ErrorResponse',
}

Expand Down Expand Up @@ -513,6 +515,7 @@ def get_event_without_preload_content(
'404': 'ErrorResponse',
'429': 'ErrorResponse',
'500': 'ErrorResponse',
'503': 'ErrorResponse',
'504': 'ErrorResponse',
}

Expand Down Expand Up @@ -1082,6 +1085,7 @@ def search_events(
'404': 'ErrorResponse',
'429': 'ErrorResponse',
'500': 'ErrorResponse',
'503': 'ErrorResponse',
'504': 'ErrorResponse',
}

Expand Down Expand Up @@ -1605,6 +1609,7 @@ def search_events_with_http_info(
'404': 'ErrorResponse',
'429': 'ErrorResponse',
'500': 'ErrorResponse',
'503': 'ErrorResponse',
'504': 'ErrorResponse',
}

Expand Down Expand Up @@ -2128,6 +2133,7 @@ def search_events_without_preload_content(
'404': 'ErrorResponse',
'429': 'ErrorResponse',
'500': 'ErrorResponse',
'503': 'ErrorResponse',
'504': 'ErrorResponse',
}

Expand Down
3 changes: 2 additions & 1 deletion fingerprint_server_sdk/models/device_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class DeviceDetails(BaseModel):
description='Raw device manufacturer string as reported by the device OS. Not normalized: casing is vendor-defined (samsung, Xiaomi, OPPO, HUAWEI). Always `Apple` on iOS.',
)
device_model: Optional[StrictStr] = Field(
default=None, description='Raw device model identifier, as reported by the mobile OS.'
default=None,
description='Raw device model identifier, as reported by the mobile OS. On Android, this is the vendor-defined model string (e.g., `SM-G991U`). On iOS, this is an Apple board code (e.g., `D84AP`).',
)
os_version: Optional[StrictStr] = Field(
default=None,
Expand Down
44 changes: 24 additions & 20 deletions res/fingerprint-server-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ info:
email: support@fingerprint.com
license:
name: MIT
url: >-
https://github.com/fingerprintjs/fingerprint-pro-server-api-openapi/blob/main/LICENSE
url: https://github.com/fingerprintjs/openapi/blob/main/LICENSE
tags:
- name: Fingerprint
description: >-
Expand Down Expand Up @@ -104,12 +103,8 @@ paths:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: >
description: |
Too Many Requests. The request is throttled.

To protect service stability during rare periods of extreme load, we
may return HTTP 429 responses with message `too many search
requests` even if you are within your assigned rate limits.
content:
application/json:
schema:
Expand All @@ -120,10 +115,15 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service Temporarily Unavailable.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'504':
description: >-
Gateway Timeout. Search execution exceeded the allowed timeout
window.
description: Gateway Timeout.
x-deprecated-response: true
content:
application/json:
schema:
Expand Down Expand Up @@ -1005,12 +1005,8 @@ paths:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: >
description: |
Too Many Requests. The request is throttled.

To protect service stability during rare periods of extreme load, we
may return HTTP 429 responses with message `too many search
requests` even if you are within your assigned rate limits.
content:
application/json:
schema:
Expand All @@ -1021,10 +1017,15 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: Service Temporarily Unavailable.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'504':
description: >-
Gateway Timeout. Search execution exceeded the allowed timeout
window.
description: Gateway Timeout.
x-deprecated-response: true
content:
application/json:
schema:
Expand Down Expand Up @@ -2088,8 +2089,11 @@ components:
type: string
examples:
- SM-G991U
- iPhone14,5
description: Raw device model identifier, as reported by the mobile OS.
- D84AP
description: >-
Raw device model identifier, as reported by the mobile OS. On
Android, this is the vendor-defined model string (e.g., `SM-G991U`).
On iOS, this is an Apple board code (e.g., `D84AP`).
os_version:
type: string
examples:
Expand Down
1 change: 1 addition & 0 deletions sync.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ examples=(
'errors/404_visitor_not_found.json'
'errors/409_state_not_ready.json'
'errors/429_too_many_requests.json'
'errors/503_service_unavailable.json'
)

for example in "${examples[@]}"; do
Expand Down
6 changes: 6 additions & 0 deletions test/mocks/errors/503_service_unavailable.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"error": {
"code": "service_unavailable",
"message": "service temporarily unavailable"
}
}
50 changes: 50 additions & 0 deletions test/test_fingerprint_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
SearchEventsSdkPlatform,
SearchEventsSource,
SearchEventsVpnConfidence,
ServiceException,
TooManyRequestsException,
__version__,
)
Expand Down Expand Up @@ -332,6 +333,30 @@ def test_get_event_too_many_requests(self) -> None:
self.assertIsInstance(context.exception.data, ErrorResponse)
self.assertEqual(context.exception.data.error.code, ErrorCode.TOO_MANY_REQUESTS)

def test_get_event_service_unavailable(self) -> None:
"""Test case for get_event with 503 Service Unavailable response"""
mock_pool = MockPoolManager(self)
self.api.api_client.rest_client.pool_manager = mock_pool
event_id = '0000000000000.XXXXX'
mock_pool.expect_request(
'GET',
TestFingerprintApi.get_event_path(event_id),
fields=[],
headers=self.request_headers,
preload_content=True,
timeout=None,
response_status_code=503,
response_data_file='errors/503_service_unavailable.json',
)

with self.assertRaises(ServiceException) as context:
self.api.get_event(event_id)

self.assertNotIsInstance(context.exception, GatewayTimeoutException)
self.assertEqual(context.exception.status, 503)
self.assertIsInstance(context.exception.data, ErrorResponse)
self.assertEqual(context.exception.data.error.code, ErrorCode.SERVICE_UNAVAILABLE)

def test_get_event_gateway_timeout(self) -> None:
"""Test case for get_event with 504 Gateway Timeout response"""
mock_pool = MockPoolManager(self)
Expand Down Expand Up @@ -580,6 +605,31 @@ def test_search_events_too_many_requests(self) -> None:
self.assertIsInstance(context.exception.data, ErrorResponse)
self.assertEqual(context.exception.data.error.code, ErrorCode.TOO_MANY_REQUESTS)

def test_search_events_service_unavailable(self) -> None:
"""Test case for search_events with 503 Service Unavailable response"""
params = {'limit': 2}

mock_pool = MockPoolManager(self)
self.api.api_client.rest_client.pool_manager = mock_pool
mock_pool.expect_request(
'GET',
TestFingerprintApi.get_search_events_path(params),
fields=[],
headers=self.request_headers,
preload_content=True,
timeout=None,
response_status_code=503,
response_data_file='errors/503_service_unavailable.json',
)

with self.assertRaises(ServiceException) as context:
self.api.search_events(**params)

self.assertNotIsInstance(context.exception, GatewayTimeoutException)
self.assertEqual(context.exception.status, 503)
self.assertIsInstance(context.exception.data, ErrorResponse)
self.assertEqual(context.exception.data.error.code, ErrorCode.SERVICE_UNAVAILABLE)

def test_search_events_gateway_timeout(self) -> None:
"""Test case for search_events with 504 Gateway Timeout response"""
params = {'limit': 2}
Expand Down
Loading