clariodesk library

ClarioDesk Flutter SDK — headless surface.

Quick start:

// 1. Once at app start. Awaiting is optional — subsequent calls
//    transparently wait on the in-flight bootstrap if you don't.
await ClarioDesk.init(apiKey: 'pk_live_…');

// 2. After the host's own auth flow knows the user. Metadata only —
//    the device's hardware-bound key is the actual identity.
await ClarioDesk.identify(
  externalId: hostUser.id,
  email: hostUser.email,
  traits: {'plan': 'pro'},
);

// 3. Writes are imperative.
final t = await ClarioDesk.createTicket(
  subject: 'Upload broken',
  body: 'Tapping upload does nothing.',
);

// 4. Reads are reactive streams — auto-prime + live updates.
StreamBuilder<List<Ticket>>(
  stream: ClarioDesk.ticketsStream(),
  builder: (_, snap) => …,
);

Auth model: Device-Is-Identity. On first launch the SDK generates an ECDSA P-256 keypair inside iOS Secure Enclave / Android Keystore, registers it via challenge-response, and signs every subsequent request with that key. The publishable pk_* key you pass to init only opens the door to register a new device; it cannot read tickets or impersonate users.

Classes

Attachment
One file/photo/video on a Message. Mirrors the API's attachment payload. image/file carry a short-lived presigned R2 GET (url + urlExpiresAt, refreshable); video carries the Cloudflare Stream fields (playbackUrl/posterUrl/processingStatus).
ChangelogEntry
A published "What's New" changelog entry.
ClarioDesk
Static facade. Backed by a singleton state holder so hot reload (which preserves Dart globals across rebuilds) keeps registration state intact.
ClarioDeskDiagnostic
A non-fatal event the SDK would otherwise swallow silently — a best-effort failure, an exhausted retry, a dropped queued write, a fatal transition. Delivered to the host's ClarioDiagnosticHandler (wired at init) so it can pipe SDK internals into Sentry/Crashlytics: "swallow with a receipt". code is a stable machine key; message is for logs; context carries structured extras (ticketId, clientId, error code).
ClarioDeskDiagnostics
A point-in-time snapshot of SDK health, from ClarioDesk.diagnostics(). Designed to be pasted straight into a support ticket — toJson renders the same field names on every ClarioDesk SDK.
ClarioDeskFeedback
Headless feedback-board API, reached via ClarioDesk.feedback (docs/FEEDBACK_BOARD_IN_APP_SURFACE). Every call funnels through the same signed client as tickets, so it inherits the SDK's auth, retries, and resilience. Reads throw ClarioDeskException (404 feedback_not_enabled) when the app owner hasn't provisioned a board.
ClarioPushPayload
A parsed ClarioDesk push payload (the FCM message.data map). Produced by ClarioDesk.parsePushPayload; null for any message that isn't ours.
DeviceKey
A device-resident ECDSA P-256 keypair backed by iOS Secure Enclave or Android Keystore. The private key is non-extractable by design — every operation that needs it (signing, attestation) goes through this interface.
FeedbackBoard
The board's config + taxonomy — everything the SDK needs to render the shell.
FeedbackCategory
An optional tag a post can carry.
FeedbackComment
A public comment on a post.
FeedbackPost
A feedback post (feature request / idea).
FeedbackPostCreated
Result of creating a post: its id + whether it's held for moderation.
FeedbackPostDetail
A post plus its comment thread.
FeedbackStatus
A status column on the board (Open / Planned / Shipped …).
IdentityTokenProvider
Supplies a fresh verified-identity token for the current host session.
Message
NotificationPreferences
The end user's notification preferences. Quiet-hours bounds are HH:MM 24h strings in timezone; all three are null when no window is set.
OutgoingAttachment
A file the host has picked and handed to ClarioDesk.sendMessage / createTicket to attach. The SDK reads its bytes, uploads them (sign → direct PUT/Stream), and binds the resulting id when the message is sent.
PushTokenProvider
Source of the device's push token, owned by the host app, not the SDK.
SdkFeatureFlags
SdkNotice
SdkRuntimeConfig
SecureStorage
Persists tiny pieces of identity state across app launches — today only the deviceId minted by /v1/sdk/devices registration. The device's private key itself never travels through here; it lives in Secure Enclave / Keystore via DeviceKey.
Ticket

Enums

AttachmentKind
Server-derived discriminator both the bubble and viewer switch on. The wire also carries legacy screenshot/log values which collapse to file.
ClarioDeskConnectionState
ClarioDeskErrorCode
ClarioDiagnosticLevel
Severity of a ClarioDeskDiagnostic. Advisory — branch on code, not this.
ConversationSyncState
Per-conversation sync lifecycle (REALTIME_ARCHITECTURE §9). Distinct from ClarioDeskConnectionState: a connected socket doesn't mean a given thread is caught up. Drives the mid-session "Updating…" / "Offline" hints the pre-built UI renders on top of the message list.
DevicePlatform
String form on the wire — matches device_platform_enum in the backend schema. Sent on registration so the server can both rate-limit per-platform and surface the device in the dashboard.
IdentityMode
KeyAttestation
Where the private key actually lives. The native layer reports the strongest backing it landed in; the server records the same enum on devices.key_attestation so the dashboard can surface a per-device badge.
MessageAuthor
MessageReadState
Delivery state of an end-user's own outgoing message, for status-tick rendering. A failed send is signalled separately by Message.failed; this enum covers the success path only.
SdkFeature
TicketStatus
TicketType

Functions

readStateOf(Message m, Ticket t) → MessageReadState
Derives the MessageReadState of m within t. Meaningful only for the end-user's own messages; callers gate on author/failed first. Headless hosts use this to render delivery ticks without reimplementing the read-pointer comparison; the pre-built UI uses it too.

Typedefs

ClarioDiagnosticHandler = void Function(ClarioDeskDiagnostic diagnostic)
Optional host hook passed to ClarioDesk.init(onDiagnostic: …). The SDK guarantees it never throws into the host: it is invoked inside a guard, so a sink that itself throws can't crash the SDK (the never-crash contract).

Exceptions / Errors

ClarioDeskException