diff --git a/HISTORY b/HISTORY index 4c6d5e8..139520d 100644 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,8 @@ +=== 4.7.0 2026-08-27 +- Added support for $nationality, $year_of_birth fields on $create_account, $update_account events +- Added support for $kyc field on $create_account, $update_account, $transaction, $create_order, $update_order, $verification events +- Added support for $geo, $bot_identification fields on $create_account, $update_account, $login, $transaction, $create_order, $update_order events + === 4.6.0 2026-02-10 - Bump the minimum version of httparty to 0.23.3 to ensure protection against CVE-2025-68696 - Refactor Client to use dedicated internal HTTP clients for different API endpoints diff --git a/README.md b/README.md index 1b92c2d..2dcaf03 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,77 @@ response.api_error_message # Error message associated with status Error Code response = client.score(user_id) ``` +### New KYC Signals, Geo & Bot Detection + +```ruby +# $verification event with KYC outcome +response = client.track("$verification", { + "$user_id" => "23056", + "$verification_type" => "$kyc", + "$status" => "$success", + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$basic", + "$bin_nationality_match" => false, + "$provider" => "lexisnexis" + } +}) + +# $create_account with account-level identity attributes +response = client.track("$create_account", { + "$user_id" => "23056", + "$nationality" => "US", + "$year_of_birth" => 1985, + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$full", + "$provider" => "prove" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + } +}) + +# $login event with geo and bot-detection signals +response = client.track("$login", { + "$user_id" => "23056", + "$login_status" => "$success", + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + } +}) + +# $transaction event with KYC, geo, and bot-detection signals +response = client.track("$transaction", { + "$user_id" => "23056", + "$amount" => 15230000, + "$currency_code" => "USD", + "$kyc" => { + "$names_match" => true, + "$bin_nationality_match" => true, + "$provider" => "lexisnexis" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$suspected", + "$provider" => "human_security" + } +}) +``` + ## Decisions To learn more about the decisions endpoint visit our [developer docs](https://sift.com/developers/docs/ruby/decisions-api/get-decisions). diff --git a/lib/sift/version.rb b/lib/sift/version.rb index 9f7968d..29a1d22 100644 --- a/lib/sift/version.rb +++ b/lib/sift/version.rb @@ -1,5 +1,5 @@ module Sift - VERSION = "4.6.0" + VERSION = "4.7.0" API_VERSION = "205" VERIFICATION_API_VERSION = "1.1" end diff --git a/spec/unit/client_structured_fields_spec.rb b/spec/unit/client_structured_fields_spec.rb new file mode 100644 index 0000000..7f6f72a --- /dev/null +++ b/spec/unit/client_structured_fields_spec.rb @@ -0,0 +1,60 @@ +require_relative '../spec_helper' +require 'sift' + +describe Sift::Client do + + before :each do + Sift.api_key = nil + end + + it "Successfully submits a $create_account event with KYC, geo, and bot-detection structured fields" do + response_json = { :status => 0, :error_message => "OK" } + stub_request(:post, "https://api.siftscience.com/v205/events"). + with { |request| + parsed_body = JSON.parse(request.body) + expect(parsed_body["$nationality"]).to eq("US") + expect(parsed_body["$year_of_birth"]).to eq(1985) + expect(parsed_body["$kyc"]).to eq({ + "$names_match" => true, + "$kyc_level" => "$basic", + "$bin_nationality_match" => true, + "$provider" => "lexisnexis" + }) + expect(parsed_body["$geo"]).to eq({ + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }) + expect(parsed_body["$bot_identification"]).to eq({ + "$result" => "$human", + "$provider" => "datadome" + }) + }.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {}) + + api_key = "foobar" + properties = { + :$type => "$create_account", + :$user_id => "23056", + :$nationality => "US", + :$year_of_birth => 1985, + :$kyc => { + :$names_match => true, + :$kyc_level => "$basic", + :$bin_nationality_match => true, + :$provider => "lexisnexis" + }, + :$geo => { + :$uuid => "gc-abc-123", + :$provider => "geocomply" + }, + :$bot_identification => { + :$result => "$human", + :$provider => "datadome" + } + } + + response = Sift::Client.new(:api_key => api_key, :version => "205") + .track("$create_account", properties) + expect(response.ok?).to eq(true) + expect(response.api_status).to eq(0) + end +end diff --git a/test_integration_app/events_api/test_events_api.rb b/test_integration_app/events_api/test_events_api.rb index 299b39d..6817bee 100644 --- a/test_integration_app/events_api/test_events_api.rb +++ b/test_integration_app/events_api/test_events_api.rb @@ -24,7 +24,16 @@ def login() "$brand_name" => "sift", "$site_domain" => "sift.com", "$site_country" => "US", - + + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + }, + # Send this information with a login from a BROWSER client. "$browser" => { "$user_agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -107,13 +116,27 @@ def transaction() # For marketplaces, use $seller_user_id to identify the seller "$seller_user_id" => "slinkys_emporium", - + + "$kyc" => { + "$names_match" => true, + "$bin_nationality_match" => false, + "$provider" => "prove" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "human_security" + }, + # Sample Custom Fields "digital_wallet" => "apple_pay", # "google_wallet", etc. "coupon_code" => "dollarMadness", "shipping_choice" => "FedEx Ground Courier", "is_first_time_buyer" => false, - + # Send this information from a BROWSER client. "$browser" => { "$user_agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -121,7 +144,7 @@ def transaction() "$content_language" => "en-GB" } } - + return @@client.track("$transaction", properties, :warnings => 'true') end @@ -233,7 +256,21 @@ def create_order() "coupon_code" => "dollarMadness", "shipping_choice" => "FedEx Ground Courier", "is_first_time_buyer" => false, - + + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$basic", + "$provider" => "lexisnexis" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + }, + # Send this information from a BROWSER client. "$browser" => { "$user_agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -241,7 +278,7 @@ def create_order() "$content_language" => "en-GB" } } - + return @@client.track("$create_order", properties) end @@ -457,7 +494,23 @@ def update_account() "$social_sign_on_type" => "$twitter", "$account_types" => ["merchant", "premium"], - + + "$nationality" => "US", + "$year_of_birth" => 1985, + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$full", + "$provider" => "prove" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + }, + # Send this information from a BROWSER client. "$browser" => { "$user_agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -465,7 +518,7 @@ def update_account() "$content_language" => "en-GB" } } - + return @@client.track("$update_account", properties) end @@ -585,7 +638,23 @@ def create_account() "$social_sign_on_type" => "$twitter", "$account_types" => ["merchant", "premium"], - + + "$nationality" => "US", + "$year_of_birth" => 1985, + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$basic", + "$provider" => "lexisnexis" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + }, + # Suggested Custom Fields "twitter_handle" => "billyjones", "work_phone" => "1-347-555-5921", @@ -618,7 +687,14 @@ def verification() "$verified_event" => "$login", "$reason" => "$automated_rule", # Verification was triggered based on risk score "$verification_type" => "$sms", - "$verified_value" => "14155551212" + "$verified_value" => "14155551212", + + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$basic", + "$bin_nationality_match" => false, + "$provider" => "lexisnexis" + } } return @@client.track("$verification", properties) @@ -828,7 +904,21 @@ def update_order() "coupon_code" => "dollarMadness", "shipping_choice" => "FedEx Ground Courier", "is_first_time_buyer" => false, - + + "$kyc" => { + "$names_match" => true, + "$kyc_level" => "$basic", + "$provider" => "lexisnexis" + }, + "$geo" => { + "$uuid" => "gc-abc-123", + "$provider" => "geocomply" + }, + "$bot_identification" => { + "$result" => "$human", + "$provider" => "datadome" + }, + # Send this information from a BROWSER client. "$browser" => { "$user_agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36", @@ -836,7 +926,7 @@ def update_order() "$content_language" => "en-GB" } } - + return @@client.track("$update_order", properties) end