SDKs

Ruby

Read identification events with a secret key and verify signed webhooks from Ruby 3.1 and newer, with a Rails example.

The fingerly gem reads stored events by request ID and verifies webhook signatures. It has no runtime dependencies beyond the standard library.

Requirements

Install

bundle add fingerly

Read an event

Create one client with your secret key and reuse it. The key decides the regional API and the environment the client reads.

Ruby
require "fingerly"

fingerly = Fingerly::Client.new(secret_key: ENV.fetch("FINGERLY_SECRET_KEY"))
event = fingerly.events.get("01a0a84b-e6a2-7c09-9f51-0b3d7a26c8e4")

An event has the fields listed in Get an event. suspect_score is null when the request was not scored.

Verify a checkout

Read the event your client identified, check it belongs to this action and is recent, then decide on its level. See server-side verification.

Ruby
def decide(order_id, request_id)
  event = fingerly.events.get(request_id)

  return "refuse" unless event.tag == "checkout:#{order_id}"
  return "refuse" if event.occurred_at < Time.now - 120

  case event.suspect_level
  when "high" then "review"
  when "medium" then "challenge"
  else "allow"
  end
rescue Fingerly::APIError => e
  raise unless e.status == 404
  "refuse"
end

Verify a webhook

Check the signature over the raw request body before parsing it. The helper rejects timestamps more than five minutes from now.

Ruby
class FingerlyWebhooksController < ActionController::API
  def create
    payload = request.raw_post
    valid = Fingerly::Webhook.verify(
      secret: ENV.fetch("FINGERLY_WEBHOOK_SECRET"),
      payload: payload,
      timestamp: request.headers["x-fingerly-timestamp"],
      signature: request.headers["x-fingerly-signature"],
    )
    return head :bad_request unless valid

    event = JSON.parse(payload)
    FingerlyEventJob.perform_later(event)   # deduplicate on event["id"]
    head :no_content
  end
end

Rails

config/initializers/fingerly.rb
FINGERLY = Fingerly::Client.new(secret_key: Rails.application.credentials.dig(:fingerly, :secret_key))

API

MemberReturnsNotes
Fingerly::Client.new(secret_key:, endpoint: nil, timeout: 10)clientThread-safe; create one per process.
events.get(request_id)Fingerly::EventRaises Fingerly::APIError with #status for a non-2xx response.
events.list(from: nil, to: nil, page: 1, limit: 10, visitor: nil, level: nil)Fingerly::EventPageHas rows, page and page_size.
Fingerly::Webhook.verify(secret:, payload:, timestamp:, signature:)true or falseFive minutes of tolerance.