Docs

Dart: Push, attestation and crashes

Register devices for push, prove requests come from your real app, and report crashes with the Dart and Flutter SDK.

Updated Oct 24, 2026

Register devices for push, prove requests come from your real app, and report crashes. Every call runs as the client's signed-in user, so your project's policies and row-level security apply. Types and members are listed in source order; each one links to its HTTP endpoint where it maps to one.

#Types and members

SovariaPush

Push notifications for the signed-in app user. Get the token from your push plugin and register it after sign-in: Sending happens on your server or in a function with the service role key (api.push.send), never from the app.

class SovariaPush

SovariaPush.SovariaPush

Create an instance.

SovariaPush(this._client)

SovariaPush.register

Register (or move to this user) a push token.

Future<PushDevice> register({required String token, required String platform, String? provider, String? appId,
    List<String>? topics, String? locale})

provider is fcm or apns (default: apns for a raw hex iOS token, else fcm). The token is tied to the client's Sovaria.device.

SovariaPush.unregister

Drop a token (sign-out, notifications turned off).

Future<void> unregister(String token)

Safe to call twice.

SovariaPush.devices

Future<List<PushDevice>> devices()

SovariaPush.subscribe

Future<PushDevice> subscribe(String deviceRowId, List<String> topics)

SovariaPush.unsubscribe

Future<PushDevice> unsubscribe(String deviceRowId, List<String> topics)

PushDevice

class PushDevice

PushDevice.PushDevice

Create an instance.

PushDevice(this.id, this.platform, this.provider, this.topics, this.raw)

PushDevice.id

A property.

final String id

PushDevice.platform

A property.

final String platform

PushDevice.provider

A property.

final String provider

PushDevice.topics

A property.

final List<String> topics

PushDevice.raw

A property.

final Map<String, Object?> raw

PushDevice.PushDevice.fromJson

Create an instance.

factory PushDevice.fromJson(Object? json)

AttestationProvider

Produces platform evidence for a challenge. Implement it with your platform code (a MethodChannel to Play Integrity / App Attest), or use DebugAttestationProvider on simulators. Return the fields of POST /api/v1/attest/exchange: * Play Integrity: {'provider': 'play_integrity', 'app_id': packageName, 'token': integrityToken} (request the token with nonce/requestHash = the challenge); * App Attest, first time: {'provider': 'app_attest', 'app_id': bundleId, 'key_id': keyId, 'attestation': base64(attestationObject)} with clientDataHash = SHA-256(challenge); afterwards {'provider': 'app_attest', 'app_id': bundleId, 'key_id': keyId, 'assertion': base64(assertion)}; * DeviceCheck: {'provider': 'device_check', 'app_id': bundleId, 'token': base64(deviceToken)}.

abstract class AttestationProvider

AttestationProvider.evidence

Future<Map<String, Object?>> evidence(String challenge)

DebugAttestationProvider

Stands in for a device on simulators and CI. Create the token in the console (Mobile › App attestation › Debug tokens); never ship it in a release build.

class DebugAttestationProvider implements AttestationProvider

DebugAttestationProvider.DebugAttestationProvider

Create an instance.

DebugAttestationProvider(this.debugToken)

DebugAttestationProvider.debugToken

A property.

final String debugToken

DebugAttestationProvider.evidence

Future<Map<String, Object?>> evidence(String challenge)

AttestationManager

Keeps a valid attestation token and refreshes it before it expires. The client sends it as X-Sovaria-Attestation and fetches a new one after a 401 APP_ATTESTATION_REQUIRED.

class AttestationManager

AttestationManager.AttestationManager

Create an instance.

AttestationManager(this._client, this.provider, {this.margin = const Duration(seconds: 60)})

AttestationManager.provider

A property.

final AttestationProvider provider

AttestationManager.margin

A property.

final Duration margin

AttestationManager.token

The current token (fetching one first when there is none or it is about to expire).

Future<String?> token()

Returns null when attestation fails, so requests still go out (the project may only monitor).

AttestationManager.refresh

Fetch a new token now (one request at a time).

Future<String?> refresh()

AttestationManager.clear

void clear()

SovariaCrashes

App crash reporting (Monitor › Crashes in the console), the same reports as the Swift and Kotlin clients: error type, message, stack, release, platform, device, the last 50 breadcrumbs and the signed-in user (the server takes the user from the request token). In a Flutter app, route the framework's and the engine's errors here once at start-up: or wrap runApp in runZonedGuarded(..., sovaria.crashes.recordFatal). A fatal report is written to the OfflineStore first and sent on the next launch, because a dying isolate may not finish a request.

class SovariaCrashes

SovariaCrashes.SovariaCrashes

Create an instance.

SovariaCrashes(this._client)

SovariaCrashes.installed

A property.

bool get installed

SovariaCrashes.install

Start capturing.

void install({String? release, String? environment, OfflineStore? store})

Pass a durable store (or enable offline first) so a fatal crash survives to the next launch.

SovariaCrashes.uninstall

void uninstall()

SovariaCrashes.addBreadcrumb

Add a breadcrumb (a step that led up to a crash).

void addBreadcrumb(String category, String message)

SovariaCrashes.capture

Report a handled error.

bool capture(Object error, {StackTrace? stack, bool handled = true, Map<String, String> tags = const {},
    Map<String, Object?> extra = const {}, String? fingerprint})

Returns false if crash reporting isn't installed.

SovariaCrashes.recordFatal

An error that ends the app: persisted first (sent on the next launch), then sent now on a best-effort basis.

Future<void> recordFatal(Object error, StackTrace? stack)

SovariaCrashes.flush

Send queued reports now (joins a flush already running).

Future<void> flush()

What didn't go through is kept (bounded).