Skip to content

API Reference

import 'package:dea_sdk/dea_sdk.dart';

DeaSdk

init

static DeaSdk init(
  DeaOptions options, {
  int? playIntegrityProject,
  String? appKey,
  String? registryAppId,
  Directory? modelDirectory,
  bool modelUpdates = true,
  Duration modelTimeout = const Duration(seconds: 30),
})

Starts the SDK and capture. Returns the running instance if one exists. Never throws. See Options.

registryAppId is the appId written inside the proofs that the Ads calls sign; set it to this platform's appId. See Options.

instance

static DeaSdk? get instance

The running instance, or null before init and after dispose().

error

Object? get error

Why the SDK cannot score, or null.

isScoring

bool get isScoring

Whether the SDK is able to score. When false, getClassification() answers insufficient with a null value, and error says why.

getClassification

Classification getClassification()

The one score read: the score, the evidence behind it and the loaded model's thresholds, classified as human, bot, undetermined or insufficient in one snapshot. Synchronous, no network; includes the latest gesture. The thresholds come from the loaded model only. See Human Scoring.

Throws ThresholdMissing (with modelVersion) when the loaded model has no bot threshold. Never throws when the SDK cannot score.

Consent get consent

The user's current consent answer. See User Consent.

setConsent

Future<void> setConsent(bool granted, {bool remember = true})
Parameter Type Description
granted bool Whether the user agreed
remember bool Store the answer on the device. false keeps it for this run only

Takes effect immediately. Withdrawing discards anything captured but not yet processed.

pause

void pause()

Stops recording. The session is kept. See Sensitive Screens.

resume

void resume()

Starts recording again after pause(). Does not override consent.

setMotion

void setMotion(bool on)

Switches the motion sensors off (false) or back on (true) for this run. While off, no motion data is recorded and getSessionInfo().device.sensorRate reads 0; touch capture and the session continue. The classification then has less evidence to work with.

motion

bool get motion

Whether the motion sensors are on. true unless setMotion(false) was called.

captureEvent

void captureEvent(String name, [Map<String, Object?>? data])
Parameter Type Description
name String Up to 64 characters; longer names are shortened
data Map<String, Object?>? Optional; at most 1024 bytes as JSON, or the event is dropped

See Custom Events.

captureKey

void captureKey(
  KeyClass keyClass, {
  bool pressed = true,
  int mods = 0,
  bool repeat = false,
  String? field,
})

Reports one keystroke your app saw. Does nothing unless EventKind.keyDown (for a press) or EventKind.keyUp (for a release) is in events.

Parameter Type Description
keyClass KeyClass The kind of key — never the character. KeyClass.of(char) classes a character
pressed bool false reports a release
mods int Modifiers held, as KeyMod flags; 0 on a soft keyboard
repeat bool Whether the press is a keyboard autorepeat
field String? A stable name for the field; defaults to the focused widget's semantics identifier

Never call it for a password field. See Report typing.

capturePointer

void capturePointer({
  required EventKind kind,
  required int pointerId,
  required double x,
  required double y,
  required int atEpochMs,
  Tool tool = Tool.touch,
  Force? force,
  Contact? contact,
  Target? target,
})

Reports one pointer event from a surface Flutter does not route, such as a web view. Dropped while paused, before consent, after dispose(), and when kind is not in events.

Parameter Type Description
kind EventKind down, move, up, cancel, scroll or hover
pointerId int Identifies one finger or pointer across its events
x, y double Position in logical pixels, global to the app window
atEpochMs int When the event happened, Unix milliseconds
tool Tool What produced it; touch by default
force Force? Pressure as value within the device's min..max, if known
contact Contact? Contact size, if known
target Target? What the touch landed on; read on down only

See Report touches inside a web view.

reset

void reset()

Ends the current session and starts a new one. See Sessions.

getSessionInfo

SessionInfo getSessionInfo()

The current session id, device and SDK version.

attest

Future<Attestation> attest()

Registers the device key with DEA. A passed result is reused until near expiry. Never throws. See Attest.

The first call also starts automatic renewal: the SDK registers the same key again one minute before the registration expires, and checks again whenever the app returns to the foreground. A renewal that fails is retried after 30 seconds, then 1, 2, 5 and 15 minutes, then every 15 minutes. The kid does not change. Your app does not need its own renewal timer.

attestation

Attestation? get attestation

The last attest() result in this run, including a refusal, or null before the first call.

storedAttestation

Future<Attestation?> storedAttestation()

The registration kept on the device, if still fresh, read without any network request. null when attest() would have to register again.

A registration found here also starts automatic renewal, as attest() does.

forgetAttestation

Future<void> forgetAttestation()

Forgets this install's registration, in memory and on the device, and stops automatic renewal. The next attest() registers again, with the same device key and kid. For example, when a different account signs in.

nextAttestationRefresh

int? get nextAttestationRefresh

When the next automatic renewal is due, in Unix seconds. null before the first attest(), and on a device that cannot keep a key.

onAttestationEvent

void Function(RefreshEvent event)? onAttestationEvent

Called for each renewal decision: RefreshScheduled(after), RefreshFired(verdict) or RefreshIdle(). Set it before the first attest() to see the first schedule.

Model updates

Active only when modelDirectory is passed to init. See Options.

model

ModelInfo get model

The model in use: version (0 for the built-in model) and source (ModelSource.embedded, cache or network).

modelChanges

Stream<ModelInfo> get modelChanges

Emits each time a newer model starts scoring during this run. Empty when updates are off.

checkForModel

Future<ModelCheck> checkForModel({bool force = false})

Checks for a newer model now, if a day has passed since the last check. force: true checks regardless; use it for a button a person presses, never on a schedule. Never throws.

The result's outcome is a ModelCheckOutcome, and its detail says more when there is more to say:

Outcome Meaning
notDue Less than a day since the last check; nothing was asked
unchanged No newer model is published
notPublished No model is published for this platform
notSupported A newer model is published, but it needs a newer SDK release
loaded A newer model was downloaded and is scoring now
refused A model was downloaded, and the scoring engine refused it; the model in use is kept
failed No usable answer: offline, a timeout, or a download that did not check out
cancelled Model updates are not running (no modelDirectory, modelUpdates: false, or the SDK cannot score), or the SDK was disposed

lastModelCheck

({ModelCheck check, DateTime at})? get lastModelCheck

How and when the last check ended, or null before one has run.

Ads

Flutter has no ad session object and does not check that the user touched an ad. These three calls sign a proof for one ad event with the device key; sendProof and record also send it to DEA. See Ads.

Every call first asks DEA for a single-use nonce to sign in, and signs without one when DEA gives none. The scoring engine composes the score claims, so nothing is signed while the classification is insufficient. The calls do not check appKey or the attestation.

Parameter Type Description
sessionId String The ad's session id, signed as session_id. '' for adImpression, so that DEA makes the id; the id DEA answered for adClick and adEnded. Not the capture session id
event ProofEvent The ad event, signed as event_type
attestation Attestation? Decides the tier the proof claims: B when verdict is passed and platformAttested is true, C otherwise. Defaults to attestation, the last attest() result
adUnit String? The ad unit the ad loaded into, signed as ad_unit. Left out when null
appScopedUid String? A pseudonymous id for the user in your app, signed as app_scoped_uid. Left out when null
extra Map<String, Object?> sendProof and record only. Unsigned fields added to the request body beside the proof. They never replace h_proof or sdk_version
update bool sendProof and record only. true sends the proof as PUT /api/sessions/{sessionId} instead of POST /api/sessions. Pass it with adEnded

sendProof

Future<RecordOutcome> sendProof({
  required String sessionId,
  required ProofEvent event,
  Attestation? attestation,
  String? adUnit,
  String? appScopedUid,
  Map<String, Object?> extra = const {},
  bool update = false,
})

Signs one proof and sends it to DEA. The RecordOutcome says whether DEA accepted it, carries the session id DEA answered with, and says why when it was not accepted.

When DEA cannot be reached or answers with a 5xx status, the same proof is sent again after 2, 4, 8 and 16 seconds, plus up to 1 second each, at most five sends in all, and never after the proof expires, 90 seconds after signing. A 4xx answer is final. The future completes after the last send. Nothing is kept on the device.

record

Future<bool> record({
  required String sessionId,
  required ProofEvent event,
  Attestation? attestation,
  String? adUnit,
  String? appScopedUid,
  Map<String, Object?> extra = const {},
  bool update = false,
})

The same as sendProof, answering only whether DEA accepted the proof. It does not return the session id DEA answers an impression with: send the impression with sendProof.

getProof

Future<SignedProof?> getProof({
  required String sessionId,
  required ProofEvent event,
  Attestation? attestation,
  String? adUnit,
  String? appScopedUid,
})

Signs one proof without sending it. null when nothing was signed: no device key, no scoring engine, the classification still insufficient, or the device key did not sign. The proof is valid for 90 seconds after signing.

dispose

void dispose()

Stops capture, drops anything not yet processed, and releases the SDK.

Functions

showDeaConsentDialog

Future<bool> showDeaConsentDialog(
  BuildContext context, {
  DeaSdk? sdk,
  ConsentCopy copy = const ConsentCopy(),
  ConsentDialogStyle style = ConsentDialogStyle.adaptive,
  bool remember = true,
  bool ask = true,
})

Shows the consent dialog if the user has not answered, records the answer, and returns it. Returns false without showing anything when the SDK is not initialized.

Parameter Description
sdk The SDK instance; defaults to DeaSdk.instance
copy The dialog's text
style adaptive (follows the app theme's platform), material or cupertino
remember Store the answer. false clears any stored answer and asks on every call
ask false returns the stored answer without showing anything

Widgets

DeaConsentDialog

const DeaConsentDialog({Key? key, ConsentCopy copy = const ConsentCopy(), ConsentDialogStyle style = ConsentDialogStyle.adaptive})

The dialog itself, for placing inside a flow of your own. It pops its route with true (accept) or false (decline); record the answer with setConsent.

Types

DeaOptions

See Options.

EventKind

down, move, up, cancel, scroll, hover, keyDown, keyUp. The constant pointerKinds lists the first six, which is the default for DeaOptions.events.

KeyClass

letter, digit, space, delete, navigation, modifier, other.

KeyClass.of(String char) returns the class of one character: letter for a letter in any script, digit for 0 to 9, space for a space, and other for anything else.

KeyMod

Flags for captureKey's mods: KeyMod.ctrl, KeyMod.alt, KeyMod.shift, KeyMod.meta. Combine with |.

Tool

unknown, touch, mouse, pen, trackpad, penInverted.

Force

Field Type Description
value double The pressure reading
min double The lowest reading the device reports
max double The highest reading the device reports

Forward the platform's numbers as they are. A device whose min equals max has no pressure sensor.

Contact

Field Type Description
x, y double? Half-extents of the contact along the screen axes
major, minor double? Half-axes of the contact oval
orientation double? Direction of the long axis, radians

Leave a field null when the platform does not measure it; null and 0.0 mean different things.

Target

Field Type Description
bucket TargetBucket unknown, button, link, input, scroller, canvas or background
id int A stable 16-bit id for the element; 0 for unknown

Classification

Field Type Description
result ClassificationResult The answer
value double? The human score, from 0 to 1. null exactly when result is insufficient
actions int How many scored actions value is based on. For "N more actions"
botThreshold double? The model's bot threshold. null when the SDK cannot score
humanThreshold double? The model's human threshold. null when the model sets none, or the SDK cannot score
modelVersion int? The model the thresholds come from; 0 for the one built in. null when the SDK cannot score

ClassificationResult

Checked in this order:

Value When
insufficient The SDK cannot score, or the session has fewer actions than the model asks for (8 with the built-in model). value is null
human value at or above humanThreshold
bot value below botThreshold
human The model sets no humanThreshold, and value is at or above botThreshold
undetermined value lies between the two thresholds

Migrating to this release: Classification.sufficient is gone, and ClassificationResult has a fourth value.

Before This release
c.sufficient == false c.result == ClassificationResult.insufficient
c.value while not sufficient: a number null
ClassificationResult has three values Four: handle insufficient in every switch
No humanThreshold, value at or above botThreshold: undetermined human

ThresholdMissing

Thrown by getClassification() when the loaded model has no bot threshold.

Field Type Description
modelVersion int The version of the model without one
Member Type Description
decision ConsentDecision unknown, granted or denied
isAnswered bool Whether the user has answered
isGranted bool Whether the user agreed
forget() Future<void> Clears the stored answer so the user is asked again
addListener(listener) void Calls listener with the new decision when it changes
removeListener(listener) void Stops calling listener

ConsentCopy

Field Type Description
title String Dialog title
body String Explanation
recorded List<String> What is recorded; empty hides the section
notRecorded List<String> What is never recorded; empty hides the section
recordedLabel String Heading for recorded
notRecordedLabel String Heading for notRecorded
closing String Closing sentence
accept String Accept button
decline String Decline button

SessionInfo

Field Type Description
session String Current session id
device Device Current device information
startedAt int When the current session started, Unix milliseconds
sdk.version String SDK version
sdk.core String Scoring engine build; none when it did not load

Device

Field Type Description
runtime Runtime Runtime.flutter
os Os Operating system
surface Surface Screen size in logical pixels
pixelRatio double Physical pixels per logical pixel
rotation int Screen rotation: 0, 90, 180 or 270
maxTouchPoints int 0: Flutter does not report it
sensorRate int The requested motion rate in Hz once motion data has arrived; 0 before that, and while motion is off

Note: On Flutter, rotation reads 0 on every device: the SDK does not read the screen rotation from the platform.

Attestation

Field Type Description
supported bool Whether a key could be created. false also when no appKey was given
verdict Verdict passed, failed or unsupported
platformAttested bool Whether a Play Integrity (Android) or App Attest (iOS) token went to DEA with the key
expiresAt int? Expiry, epoch seconds
kid String? Key identifier
tier String? Trust tier assigned by DEA
backing String? Where the key is kept
integrity String? DEA's reading of the device's integrity, decided on DEA's service. null when DEA sends none
detail String? Why attestation failed or is unsupported

Note: DEA's service does not send an integrity reading at present, so integrity is null.

Verdict

Value When
passed DEA accepted the device key
failed DEA refused the registration or could not be reached, the platform refused to issue its token, or attestation is paused after refused attempts. detail says which
unsupported No key could be created on this device, the SDK's native plugin is not registered, or no appKey was given

ProofEvent

The ad event a proof records. wire is the event_type claim it is signed as.

Value wire Sent with
adImpression ad.impression sessionId '', as POST /api/sessions. DEA answers with the ad's session id
adClick ad.click DEA's session id, as POST /api/sessions
adEnded ad.ended DEA's session id and update: true, as PUT /api/sessions/{sessionId}

RecordOutcome

What sendProof answers.

Field Type Description
accepted bool Whether DEA accepted the proof (a 2xx status)
sessionId String? The session_id in DEA's answer, or null when it named none. For an impression, the id to send the click and the end with
signed SignedProof? The proof that was signed, or null when nothing was signed
isSigned bool Whether a proof was signed, whether or not DEA accepted it
said String? DEA's answer when it accepted the proof; otherwise why nothing was signed, or why it was not delivered. For a person to read. See Ads

SignedProof

What getProof answers, and RecordOutcome.signed.

Field Type Description
proof String The compact JWS, header.claims.signature: what goes to DEA as h_proof
header Map<String, Object?>? The signed header, decoded: alg, typ, kid
claims Map<String, Object?>? The signed claims, decoded
signature String? The signature segment, base64url
score double The score signed in (h_score), from 0 to 1
evidenceAt int When the evidence behind score was gathered, Unix seconds (h_ts)
windows int How many scored actions score is based on (h_wc)
modelVersion int? The model that scored (h_mv); 0 for the one built in. null when the proof carries none
sessionId String The session_id signed in
event ProofEvent The event signed in