Managed UI Preview Available

Flutter SDK

Use the Flutter SDK for Android, iOS, web, and desktop apps built with Flutter. It supports Managed UI for fast installs and Headless SDK objects for custom screens, with chat, AI stream events, reports, subscription fallback, ringtone preferences, and Android/iOS call adapter controls behind the same object model.

Use this page for app implementation

Flutter setup, Managed UI widgets, Headless object methods, permission flow, ringtone, push token registration, and video renderer examples belong in this guide.

Use Scalar for REST details

Open Scalar when you need exact endpoint fields, response schemas, auth schemes, status codes, or generated client details.

Open Scalar API Reference

1. Create a runtime token

Your app calls your own backend. Your backend calls Ringnity Server API with a secret Server API key and returns a short-lived token to the Flutter app.

mobile app -> customer backend -> Ringnity Server API
customer backend -> short-lived runtime token -> mobile app

Token rule

Public tenant slug can identify the app experience, but trusted customer identity, agent identity, admin reads, and reports must use backend-issued tokens. Never ship a Server API key inside a Flutter app.

2. Managed UI: fastest setup

import 'package:ringnity_flutter_sdk/ringnity_flutter_sdk.dart';

final callAdapter = RingnityPlatformCallAdapter();

final config = RingnityConfig(
  apiBaseUrl: 'https://api.ringnity.com',
  tokenProvider: () async {
    final response = await yourBackend.post('/ringnity/runtime-token');
    return RingnityRuntimeToken(
      token: response.data['token'] as String,
      expiresIn: response.data['expiresIn'] as int,
    );
  },
  callMode: RingnityCallMode.basic,
  mediaAdapter: callAdapter,
  notificationAdapter: callAdapter,
);

return RingnityWidget(
  config: config,
  mode: RingnityWidgetMode.full,
  conversationSubject: 'Need help with my order',
);

3. Smaller managed surfaces

RingnityWidget(config: config, mode: RingnityWidgetMode.chat);
RingnityWidget(config: config, mode: RingnityWidgetMode.aiChat);
RingnityWidget(config: config, mode: RingnityWidgetMode.call);

final ringnity = await Ringnity.create(config);

Column(
  children: [
    Expanded(child: RingnityChatWidget(ringnity: ringnity)),
    SizedBox(height: 320, child: RingnityCallWidget(ringnity: ringnity)),
  ],
);

4. Custom video renderer

RingnityWidget(
  config: config,
  mode: RingnityWidgetMode.call,
  remoteVideo: YourRemoteVideoView(),
  localPreview: YourLocalPreviewView(),
);

RingnityVideoView(
  session: callSession,
  remoteVideo: YourRemoteVideoView(),
  localPreview: YourLocalPreviewView(),
);

5. Headless SDK initialization

import 'package:ringnity_flutter_sdk/ringnity_flutter_sdk.dart';

final callAdapter = RingnityPlatformCallAdapter();
final permissions = await callAdapter.permissions(video: true);

if (!permissions.canStartVideo) {
  // Request microphone/camera permission with your app permission flow.
}

final ringnity = await Ringnity.create(
  RingnityConfig(
    apiBaseUrl: 'https://api.ringnity.com',
    tokenProvider: () async {
      final response = await yourBackend.post('/ringnity/runtime-token');
      return RingnityRuntimeToken(
        token: response.data['token'] as String,
        expiresIn: response.data['expiresIn'] as int,
      );
    },
    callMode: RingnityCallMode.basic,
    mediaAdapter: callAdapter,
    notificationAdapter: callAdapter,
    notifications: RingnityNotificationPreferences(
      incomingCall: RingnityRingtoneOptions(
        soundName: 'ringnity_default',
        vibrate: true,
      ),
    ),
  ),
);

final readiness = await ringnity.account.readiness();
final services = await ringnity.account.services();

await ringnity.devices.registerPushToken(
  platform: RingnityPushPlatform.flutter,
  provider: RingnityPushProvider.fcm,
  token: firebaseMessagingToken,
  audience: RingnityPushAudience.customer,
  externalId: 'customer-123',
  appId: 'com.example.customer',
);

6. Ringtone behavior

// Add Android asset: android/app/src/main/res/raw/ringnity_default.*
// Add iOS asset: ringnity_default.caf in the app bundle.

await ringnity.notifications.previewRingtone();

await ringnity.notifications.playIncomingRingtone();

// Stop when the customer answers, declines, or the call expires.
await ringnity.notifications.stopRingtone();

Chat

Create or open a conversation, send messages, and subscribe to conversation updates with the SDK object model.

AI chat

Send AI prompts and consume streaming-style SDK events while the transport adapter stays internal.

Calls

Create audio/video call sessions and let the SDK hide the platform-specific media adapter.

7. Common headless app flow

final conversation = await ringnity.chat.createConversation(
  subject: 'Need help with my order',
);
final conversationId = conversation['conversationId'] as String;

// Register once after login or whenever Firebase/APNs rotates the token.
await ringnity.devices.registerPushToken(
  platform: RingnityPushPlatform.flutter,
  provider: RingnityPushProvider.fcm,
  token: firebaseMessagingToken,
  audience: RingnityPushAudience.customer,
  externalId: 'customer-123',
);

await ringnity.chat.sendMessage(
  conversationId: conversationId,
  body: 'Hi, I need help.',
);

final subscription = await ringnity.chat.subscribe(conversationId);

await for (final event in ringnity.ai.streamChat(
  conversationId: conversationId,
  message: 'Summarize the customer issue.',
)) {
  if (event['type'] == 'ai.message.delta') {
    final data = event['data'] as Map<String, Object?>;
    appendToChat(data['delta'] as String);
  }
}

final call = await ringnity.calls.startVideo(
  conversationId: conversationId,
);
await call.mute();
await call.setVideoEnabled(false);
await call.end();

subscription.unsubscribe();

Related docs

Turn Your Website Into a Real-Time Call Center

Let customers call your team directly from your website, no phone numbers and no apps required. Just add one <script>.