turnix_dart wraps POST /credentials/ice and GET /regions for Dart. It returns typed objects, including the expiry time.
Package: turnix_dart on pub.dev · Source: github.com/turnixio/turnix_dart
Building a Flutter app? The Flutter integration guide has a ready-made prompt for Claude Code, Cursor or Copilot that adds the backend endpoint and the app side in one go.
The SDK needs your API token. If you ship the token inside a Flutter app, anyone can extract it. Run the SDK in a Dart backend (for example with shelf or dart_frog), and let the app fetch only iceServers from that backend.
Install#
dart pub add turnix_dart
import 'package:turnix_dart/turnix_dart.dart';
Request credentials#
import 'dart:io';
import 'package:turnix_dart/turnix_dart.dart';
final creds = await TurnixIO.getIceCredentials(
apiToken: Platform.environment['TURNIX_API_TOKEN']!,
ttl: 3600,
room: 'room-42',
initiatorClient: 'user-1842',
clientIp: '203.0.113.42', // the end user's public IP, for geo-routing
);
print(creds.expiresAt); // DateTime (UTC)
Return the servers to your app as JSON, for example:
final body = {
'iceServers': creds.iceServers
.map((s) => {
'urls': s.urls,
if (s.username != null) 'username': s.username,
if (s.credential != null) 'credential': s.credential,
})
.toList(),
'expiresAt': creds.expiresAt.toIso8601String(),
};
In the Flutter app, with flutter_webrtc:
final pc = await createPeerConnection({'iceServers': json['iceServers']});
For the complete app side (fetching, refreshing before ICE restarts, verifying the relay), see the Flutter integration guide.
API#
TurnixIO.getIceCredentials(...)#
Returns Future<IceCredentials>. Only apiToken is required.
| Parameter | Type | Sent as |
|---|---|---|
apiToken |
String |
Authorization: Bearer … header |
ttl |
int? |
ttl |
room |
String? |
room |
initiatorClient |
String? |
initiator_client |
receiverClient |
String? |
receiver_client |
preferredRegion |
String? |
preferred_region |
fixedRegion |
String? |
fixed_region |
clientIp |
String? |
X-TURN-CLIENT-IP header |
IceCredentials has iceServers (List<IceServer>, each with urls, username?, credential?) and expiresAt (DateTime).
Throws http.ClientException with the status code (for example Failed to fetch ICE credentials (429)) for any non-200 response.
TurnixIO.getAvailableRegions(apiToken: ...)#
Returns Future<List<Region>> with slug, nat2 (country code), city, name, lat, lon, isOnline and isOperational.
final regions = await TurnixIO.getAvailableRegions(apiToken: token);
final usable = regions.where((r) => r.isOnline && r.isOperational);
Refreshing before expiry#
if (creds.expiresAt.difference(DateTime.now().toUtc()) < const Duration(seconds: 60)) {
creds = await TurnixIO.getIceCredentials(apiToken: token, ttl: 3600);
}
See Credentials & TTL for when to refresh.