diff --git a/.changeset/error-response-503-events-search.md b/.changeset/error-response-503-events-search.md new file mode 100644 index 000000000..71371fef7 --- /dev/null +++ b/.changeset/error-response-503-events-search.md @@ -0,0 +1,5 @@ +--- +'@fingerprint/php-sdk': minor +--- + +**events-search**: Add `503` Service Temporarily Unavailable response to the Events Search endpoint diff --git a/.changeset/error-response-503-events.md b/.changeset/error-response-503-events.md new file mode 100644 index 000000000..99ed7aedb --- /dev/null +++ b/.changeset/error-response-503-events.md @@ -0,0 +1,5 @@ +--- +'@fingerprint/php-sdk': minor +--- + +**events**: Add `503` Service Temporarily Unavailable response to the Get Event endpoint diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..f692d6f80 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,8 @@ +{ + "mode": "pre", + "tag": "beta", + "initialVersions": { + "@fingerprint/php-sdk": "7.7.0" + }, + "changesets": [] +} diff --git a/.schema-version b/.schema-version index ea535dc59..65aee83a0 100644 --- a/.schema-version +++ b/.schema-version @@ -1 +1 @@ -v3.8.0 \ No newline at end of file +v3.9.0 \ No newline at end of file diff --git a/docs/Model/DeviceDetails.md b/docs/Model/DeviceDetails.md index a27d1b1bd..7d8d11d76 100644 --- a/docs/Model/DeviceDetails.md +++ b/docs/Model/DeviceDetails.md @@ -7,7 +7,7 @@ Native, SDK-collected mobile device identification signals (manufacturer, model, Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **device_manufacturer** | **string** | 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** | **string** | Raw device model identifier, as reported by the mobile OS. | [optional] +**device_model** | **string** | 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** | **string** | 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#endpoints) [[Back to README]](../../README.md) \ No newline at end of file diff --git a/res/fingerprint-server-api.yaml b/res/fingerprint-server-api.yaml index c71de8939..bc18d5b11 100644 --- a/res/fingerprint-server-api.yaml +++ b/res/fingerprint-server-api.yaml @@ -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: >- @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: diff --git a/scripts/sync.sh b/scripts/sync.sh index bad48ecb9..9421c64b8 100755 --- a/scripts/sync.sh +++ b/scripts/sync.sh @@ -41,6 +41,7 @@ examples=( 'errors/409_state_not_ready.json' 'errors/429_too_many_requests.json' 'errors/500_internal_server_error.json' + 'errors/503_service_unavailable.json' ) for example in "${examples[@]}"; do diff --git a/src/Api/FingerprintApi.php b/src/Api/FingerprintApi.php index ffa3cedde..d8f620a49 100644 --- a/src/Api/FingerprintApi.php +++ b/src/Api/FingerprintApi.php @@ -1858,6 +1858,15 @@ private function handleGetEventError(ApiException $e): never throw $e; + case 503: + $data = ObjectSerializer::deserialize( + $content, + '\Fingerprint\ServerSdk\Model\ErrorResponse' + ); + $e->setErrorDetails($data); + + throw $e; + case 504: $data = ObjectSerializer::deserialize( $content, @@ -1948,6 +1957,15 @@ private function handleSearchEventsError(ApiException $e): never throw $e; + case 503: + $data = ObjectSerializer::deserialize( + $content, + '\Fingerprint\ServerSdk\Model\ErrorResponse' + ); + $e->setErrorDetails($data); + + throw $e; + case 504: $data = ObjectSerializer::deserialize( $content, diff --git a/src/Model/DeviceDetails.php b/src/Model/DeviceDetails.php index dec2a042d..0c749ee65 100644 --- a/src/Model/DeviceDetails.php +++ b/src/Model/DeviceDetails.php @@ -294,7 +294,7 @@ public function getDeviceModel(): ?string /** * Sets device_model. * - * @param string $device_model raw device model identifier, as reported by the mobile OS + * @param string $device_model 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`). * */ public function setDeviceModel(string $device_model): self diff --git a/test/Api/FingerprintApiTest.php b/test/Api/FingerprintApiTest.php index 148671a19..cbf2ba5c9 100644 --- a/test/Api/FingerprintApiTest.php +++ b/test/Api/FingerprintApiTest.php @@ -378,6 +378,33 @@ public function testGetEvent500Error() } } + /** + * Verifies getEvent throws 503. + * + * @throws GuzzleException + * @throws \DateMalformedStringException + */ + public function testGetEvent503Error() + { + $this->mockHandler->append(MockHelper::getMockResponse(MockHelper::OPERATION_ERROR_503_SERVICE_UNAVAILABLE)); + + $this->expectException(ApiException::class); + $this->expectExceptionCode(503); + + try { + $this->api->getEvent(MockHelper::MOCK_EVENT_ID); + } catch (ApiException $e) { + $this->assertEquals(ErrorResponse::class, get_class($e->getErrorDetails())); + + /** @var ErrorResponse $errorDetails */ + $errorDetails = $e->getErrorDetails(); + $this->assertEquals(ErrorCode::SERVICE_UNAVAILABLE, $errorDetails->getError()->getCode()); + $this->assertEquals('service temporarily unavailable', $errorDetails->getError()->getMessage()); + + throw $e; + } + } + /** * Verifies getEvent throws 504. * @@ -1011,6 +1038,33 @@ public function testSearchEvents500Error() } } + /** + * Verifies searchEvents throws 503. + * + * @throws GuzzleException + * @throws \DateMalformedStringException + */ + public function testSearchEvents503Error() + { + $this->mockHandler->append(MockHelper::getMockResponse(MockHelper::OPERATION_ERROR_503_SERVICE_UNAVAILABLE)); + + $this->expectException(ApiException::class); + $this->expectExceptionCode(503); + + try { + $this->api->searchEvents(); + } catch (ApiException $e) { + $this->assertEquals(ErrorResponse::class, get_class($e->getErrorDetails())); + + /** @var ErrorResponse $errorDetails */ + $errorDetails = $e->getErrorDetails(); + $this->assertEquals(ErrorCode::SERVICE_UNAVAILABLE, $errorDetails->getError()->getCode()); + $this->assertEquals('service temporarily unavailable', $errorDetails->getError()->getMessage()); + + throw $e; + } + } + /** * Verifies searchEvents throws 504. * diff --git a/test/MockHelper.php b/test/MockHelper.php index 21ce5166c..864f1b746 100644 --- a/test/MockHelper.php +++ b/test/MockHelper.php @@ -54,6 +54,8 @@ final class MockHelper public const OPERATION_ERROR_500_INTERNAL_SERVER_ERROR = 'OPERATION_ERROR_500_INTERNAL_SERVER_ERROR'; + public const OPERATION_ERROR_503_SERVICE_UNAVAILABLE = 'OPERATION_ERROR_503_SERVICE_UNAVAILABLE'; + public const OPERATION_ERROR_504_GATEWAY_TIMEOUT = 'OPERATION_ERROR_504_GATEWAY_TIMEOUT'; /** @@ -132,6 +134,10 @@ final class MockHelper 'file' => ['errors', '500_internal_server_error.json'], 'status' => 500, ], + self::OPERATION_ERROR_503_SERVICE_UNAVAILABLE => [ + 'file' => ['errors', '503_service_unavailable.json'], + 'status' => 503, + ], self::OPERATION_ERROR_504_GATEWAY_TIMEOUT => [ 'file' => ['errors', '504_search_timeout_exceeded.json'], 'status' => 504, diff --git a/test/mocks/errors/503_service_unavailable.json b/test/mocks/errors/503_service_unavailable.json new file mode 100644 index 000000000..aebf5cdd1 --- /dev/null +++ b/test/mocks/errors/503_service_unavailable.json @@ -0,0 +1,6 @@ +{ + "error": { + "code": "service_unavailable", + "message": "service temporarily unavailable" + } +}