From 975d2559eacc8e46214f05907198638773cac259 Mon Sep 17 00:00:00 2001 From: Juraj Uhlar Date: Thu, 15 Oct 2026 22:28:57 +0100 Subject: [PATCH 1/3] feat: sync OpenAPI schema to v3.9.0 (published baseline) --- .../resources/mocks/errors/504_search_timeout_exceeded.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json diff --git a/sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json b/sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json new file mode 100644 index 0000000..cc5fcbd --- /dev/null +++ b/sdk/src/test/resources/mocks/errors/504_search_timeout_exceeded.json @@ -0,0 +1,6 @@ +{ + "error": { + "code": "failed", + "message": "gateway timeout" + } +} From 4fdf1f53272a9827f00e802ea3064a2693c0a0da Mon Sep 17 00:00:00 2001 From: Juraj Uhlar Date: Thu, 15 Oct 2026 22:29:06 +0100 Subject: [PATCH 2/3] feat: sync OpenAPI schema to 78d51f2 (flat Event from openapi#494) --- docs/Event.md | 2 +- res/fingerprint-server-api.yaml | 27 ++++++--- .../java/com/fingerprint/v4/model/Event.java | 2 +- .../mocks/webhook/webhook_event.json | 57 +++++++++++++++---- 4 files changed, 69 insertions(+), 19 deletions(-) diff --git a/docs/Event.md b/docs/Event.md index 87e4413..66037c9 100644 --- a/docs/Event.md +++ b/docs/Event.md @@ -2,7 +2,7 @@ # Event -Contains results from Fingerprint Identification and all active Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. +Contains results from Fingerprint Identification and all active Smart Signals, or from the Automation Intelligence API. Check `source` to see which properties can be present: - `device` - generated by the JS agent or a mobile SDK running on an end-user device. Contains Identification (`visitor_id`) and Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. - `edge` - generated by the Automation Intelligence API (`/edge` endpoint). Contains only IP and bot analysis, never Identification or Smart Signals derived from device telemetry. Events stored before `source` was added don't have it; treat them as `device`. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. ## Properties diff --git a/res/fingerprint-server-api.yaml b/res/fingerprint-server-api.yaml index 531bdae..cddd349 100644 --- a/res/fingerprint-server-api.yaml +++ b/res/fingerprint-server-api.yaml @@ -1204,6 +1204,11 @@ components: enum: - device - edge + EnvironmentId: + type: string + examples: + - ae_47abaca3db2c7c43 + description: Environment ID of the event. Url: type: string examples: @@ -1720,11 +1725,6 @@ components: enum: - partially_completed - completed - EnvironmentId: - type: string - examples: - - ae_47abaca3db2c7c43 - description: Environment ID of the event. Suspect: type: boolean description: >- @@ -3146,11 +3146,24 @@ components: team](https://fingerprint.com/support/). Event: type: object - description: >- + description: > Contains results from Fingerprint Identification and all active Smart + Signals, or from the Automation Intelligence API. Check `source` to see + which properties can be present: + + - `device` - generated by the JS agent or a mobile SDK running on an + end-user device. Contains Identification (`visitor_id`) and Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported - devices. Consult the [Smart Signals + devices. + + - `edge` - generated by the Automation Intelligence API (`/edge` + endpoint). Contains only IP and bot analysis, never Identification or + Smart Signals derived from device telemetry. + + + Events stored before `source` was added don't have it; treat them as + `device`. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. required: diff --git a/sdk/src/main/java/com/fingerprint/v4/model/Event.java b/sdk/src/main/java/com/fingerprint/v4/model/Event.java index b49f204..ff632a2 100644 --- a/sdk/src/main/java/com/fingerprint/v4/model/Event.java +++ b/sdk/src/main/java/com/fingerprint/v4/model/Event.java @@ -22,7 +22,7 @@ import java.util.Objects; /** - * Contains results from Fingerprint Identification and all active Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. + * Contains results from Fingerprint Identification and all active Smart Signals, or from the Automation Intelligence API. Check `source` to see which properties can be present: - `device` - generated by the JS agent or a mobile SDK running on an end-user device. Contains Identification (`visitor_id`) and Smart Signals. Some Smart Signals are only supported for certain device types, these fields will be omitted for events not generated from the supported devices. - `edge` - generated by the Automation Intelligence API (`/edge` endpoint). Contains only IP and bot analysis, never Identification or Smart Signals derived from device telemetry. Events stored before `source` was added don't have it; treat them as `device`. Consult the [Smart Signals reference](https://docs.fingerprint.com/docs/smart-signals-reference) for more details. */ @JsonPropertyOrder({ Event.JSON_PROPERTY_EVENT_ID, diff --git a/sdk/src/test/resources/mocks/webhook/webhook_event.json b/sdk/src/test/resources/mocks/webhook/webhook_event.json index 3556791..c50663b 100644 --- a/sdk/src/test/resources/mocks/webhook/webhook_event.json +++ b/sdk/src/test/resources/mocks/webhook/webhook_event.json @@ -3,9 +3,14 @@ "tags": {}, "timestamp": 1708102555327, "event_id": "1708102555327.NLOjmg", + "source": "device", + "incremental_identification_status": "completed", "url": "https://www.example.com/login?hope{this{works[!", "ip_address": "61.127.217.15", "user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) ....", + "device": "Other", + "os": "Windows", + "os_version": "7", "client_referrer": "https://example.com/blog/my-article", "browser_details": { "browser_name": "Chrome", @@ -26,14 +31,14 @@ "last_seen_at": 1708102555327 }, "supplementary_id_high_recall": { - "visitor_id": "3HNey93AkBW6CRbxV6xP", + "visitor_id": "0jnGMkPYXX37DqVa4ZIO3f_hr", "visitor_found": true, "confidence": { - "score": 0.97, - "version": "1.1" + "score": 0, + "version": "Not Supported" }, - "first_seen_at": 1708102555327, - "last_seen_at": 1708102555327 + "first_seen_at": 1778086556130, + "last_seen_at": 1778604975494 }, "proximity": { "id": "w1aTfd4MCvl", @@ -111,8 +116,10 @@ "last_seen_at": 1708102555327, "provider": "Massive" }, + "proxy_ml_score": 0.2, "vpn": false, "vpn_confidence": "high", + "vpn_ml_score": 0.2, "vpn_origin_timezone": "Europe/Berlin", "vpn_origin_country": "unknown", "vpn_methods": { @@ -120,10 +127,13 @@ "public_vpn": false, "auxiliary_mobile": false, "os_mismatch": false, - "relay": false + "relay": false, + "ml_prediction": false }, "incognito": false, "tampering": false, + "tampering_confidence": "high", + "tampering_ml_score": 0.3231, "tampering_details": { "anomaly_score": 0.1955, "anti_detect_browser": false @@ -143,6 +153,11 @@ "1_hour": 1, "24_hours": 1 }, + "distinct_linked_id": { + "5_minutes": 1, + "1_hour": 5, + "24_hours": 5 + }, "distinct_country": { "5_minutes": 1, "1_hour": 2, @@ -170,6 +185,11 @@ } }, "developer_tools": false, + "device_details": { + "device_manufacturer": "samsung", + "device_model": "SM-G991U", + "os_version": "13" + }, "mitm_attack": false, "sdk": { "platform": "js", @@ -187,8 +207,6 @@ }, "replayed": false, "high_activity_device": false, - "rare_device": false, - "rare_device_percentile_bucket": " Date: Thu, 15 Oct 2026 22:29:51 +0100 Subject: [PATCH 3/3] test: cover Event without source, edge source and unknown source --- .../com/fingerprint/v4/SerializationTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java b/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java index 8bfe068..dc25547 100644 --- a/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java +++ b/sdk/src/test/java/com/fingerprint/v4/SerializationTest.java @@ -2,9 +2,11 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -14,6 +16,7 @@ import com.fingerprint.v4.model.ErrorResponse; import com.fingerprint.v4.model.Event; import com.fingerprint.v4.model.EventRuleAction; +import com.fingerprint.v4.model.EventSource; import com.fingerprint.v4.sdk.JSON; import java.io.File; import java.io.IOException; @@ -104,6 +107,54 @@ public void deserializeEventWithUnknownRuleActionTypeValue() throws IOException assertInstanceOf(EventRuleAction.UnknownEventRuleAction.class, event.getRuleAction()); } + @Test + public void deserializeEventWithoutSource() throws IOException { + ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); + + ObjectNode eventNode = + sdkObjectMapper.readValue( + getFileAsIOStream(EVENTS_DIR + "/get_event_200.json"), ObjectNode.class); + eventNode.remove("source"); + + Event event = sdkObjectMapper.treeToValue(eventNode, Event.class); + + assertNull(event.getSource()); + assertNotNull(event.getIdentification()); + assertEquals(eventNode.get("event_id").asText(), event.getEventId()); + assertFalse(sdkObjectMapper.writeValueAsString(event).contains("\"source\"")); + } + + @Test + public void deserializeEdgeEvent() throws IOException { + ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); + + Event event = + sdkObjectMapper.readValue( + getFileAsIOStream(EVENTS_DIR + "/get_event_with_edge_200.json"), Event.class); + + assertEquals(EventSource.EDGE, event.getSource()); + assertNull(event.getIdentification()); + assertNotNull(event.getIpInfo()); + assertNotNull(event.getBotInfo()); + assertEquals( + "edge", + sdkObjectMapper.readTree(sdkObjectMapper.writeValueAsString(event)).get("source").asText()); + } + + @Test + public void deserializeEventWithUnknownSource() throws IOException { + ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper(); + + ObjectNode eventNode = + sdkObjectMapper.readValue( + getFileAsIOStream(EVENTS_DIR + "/get_event_200.json"), ObjectNode.class); + eventNode.put("source", "something_new"); + + Event event = sdkObjectMapper.treeToValue(eventNode, Event.class); + + assertEquals(EventSource.UNSUPPORTED_VALUE_SDK_UPGRADE_REQUIRED, event.getSource()); + } + @TestFactory public Stream deserializeErrorResponses() { ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper();