{"id":"56a84f05-2acb-467f-8fdc-669ae68299a9","shortId":"9Lt93D","kind":"skill","title":"telnyx-webrtc-client-flutter","tagline":">-","description":"# Telnyx WebRTC - Flutter SDK\n\nBuild real-time voice communication into Flutter applications (Android, iOS, Web).\n\n> **Prerequisites**: Create WebRTC credentials and generate a login token using the Telnyx server-side SDK. See the `telnyx-webrtc-*` skill in your server language plugin (e.g., `telnyx-python`, `telnyx-javascript`).\n\n## Quick Start Option\n\nFor faster implementation, consider [Telnyx Common](https://pub.dev/packages/telnyx_common) - a higher-level abstraction that simplifies WebRTC integration with minimal setup.\n\n## Installation\n\nAdd to `pubspec.yaml`:\n\n```yaml\ndependencies:\n  telnyx_webrtc: ^latest_version\n```\n\nThen run:\n\n```bash\nflutter pub get\n```\n\n## Platform Configuration\n\n### Android\n\nAdd to `AndroidManifest.xml`:\n\n```xml\n<uses-permission android:name=\"android.permission.INTERNET\"/>\n<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />\n<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\" />\n```\n\n### iOS\n\nAdd to `Info.plist`:\n\n```xml\n<key>NSMicrophoneUsageDescription</key>\n<string>$(PRODUCT_NAME) needs microphone access for calls</string>\n```\n\n---\n\n## Authentication\n\n### Option 1: Credential-Based Login\n\n```dart\nfinal telnyxClient = TelnyxClient();\n\nfinal credentialConfig = CredentialConfig(\n  sipUser: 'your_sip_username',\n  sipPassword: 'your_sip_password',\n  sipCallerIDName: 'Display Name',\n  sipCallerIDNumber: '+15551234567',\n  notificationToken: fcmOrApnsToken,  // Optional: for push\n  autoReconnect: true,\n  debug: true,\n  logLevel: LogLevel.debug,\n);\n\ntelnyxClient.connectWithCredential(credentialConfig);\n```\n\n### Option 2: Token-Based Login (JWT)\n\n```dart\nfinal tokenConfig = TokenConfig(\n  sipToken: 'your_jwt_token',\n  sipCallerIDName: 'Display Name',\n  sipCallerIDNumber: '+15551234567',\n  notificationToken: fcmOrApnsToken,\n  autoReconnect: true,\n  debug: true,\n);\n\ntelnyxClient.connectWithToken(tokenConfig);\n```\n\n### Configuration Options\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `sipUser` / `sipToken` | String | Credentials from Telnyx Portal |\n| `sipCallerIDName` | String | Caller ID name displayed to recipients |\n| `sipCallerIDNumber` | String | Caller ID number |\n| `notificationToken` | String? | FCM (Android) or APNS (iOS) token |\n| `autoReconnect` | bool | Auto-retry login on failure |\n| `debug` | bool | Enable call quality metrics |\n| `logLevel` | LogLevel | none, error, warning, debug, info, all |\n| `ringTonePath` | String? | Custom ringtone asset path |\n| `ringbackPath` | String? | Custom ringback tone asset path |\n\n---\n\n## Making Outbound Calls\n\n```dart\ntelnyxClient.call.newInvite(\n  'John Doe',           // callerName\n  '+15551234567',       // callerNumber\n  '+15559876543',       // destinationNumber\n  'my-custom-state',    // clientState\n);\n```\n\n---\n\n## Receiving Inbound Calls\n\nListen for socket events:\n\n```dart\nInviteParams? _incomingInvite;\nCall? _currentCall;\n\ntelnyxClient.onSocketMessageReceived = (TelnyxMessage message) {\n  switch (message.socketMethod) {\n    case SocketMethod.CLIENT_READY:\n      // Ready to make/receive calls\n      break;\n      \n    case SocketMethod.LOGIN:\n      // Successfully logged in\n      break;\n      \n    case SocketMethod.INVITE:\n      // Incoming call!\n      _incomingInvite = message.message.inviteParams;\n      // Show incoming call UI...\n      break;\n      \n    case SocketMethod.ANSWER:\n      // Call was answered\n      break;\n      \n    case SocketMethod.BYE:\n      // Call ended\n      break;\n  }\n};\n\n// Accept the incoming call\nvoid acceptCall() {\n  if (_incomingInvite != null) {\n    _currentCall = telnyxClient.acceptCall(\n      _incomingInvite!,\n      'My Name',\n      '+15551234567',\n      'state',\n    );\n  }\n}\n```\n\n---\n\n## Call Controls\n\n```dart\n// End call\ntelnyxClient.call.endCall(telnyxClient.call.callId);\n\n// Decline incoming call\ntelnyxClient.createCall().endCall(_incomingInvite?.callID);\n\n// Mute/Unmute\ntelnyxClient.call.onMuteUnmutePressed();\n\n// Hold/Unhold\ntelnyxClient.call.onHoldUnholdPressed();\n\n// Toggle speaker\ntelnyxClient.call.enableSpeakerPhone(true);\n\n// Send DTMF tone\ntelnyxClient.call.dtmf(telnyxClient.call.callId, '1');\n```\n\n---\n\n## Push Notifications - Android (FCM)\n\n### 1. Setup Firebase\n\n```dart\n// main.dart\n@pragma('vm:entry-point')\nFuture<void> main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  \n  if (defaultTargetPlatform == TargetPlatform.android) {\n    await Firebase.initializeApp();\n    FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler);\n  }\n  \n  runApp(const MyApp());\n}\n```\n\n### 2. Background Handler\n\n```dart\nFuture<void> _firebaseBackgroundHandler(RemoteMessage message) async {\n  // Show notification (e.g., using flutter_callkit_incoming)\n  showIncomingCallNotification(message);\n  \n  // Listen for user action\n  FlutterCallkitIncoming.onEvent.listen((CallEvent? event) {\n    switch (event!.event) {\n      case Event.actionCallAccept:\n        TelnyxClient.setPushMetaData(\n          message.data,\n          isAnswer: true,\n          isDecline: false,\n        );\n        break;\n      case Event.actionCallDecline:\n        TelnyxClient.setPushMetaData(\n          message.data,\n          isAnswer: false,\n          isDecline: true,  // SDK handles decline automatically\n        );\n        break;\n    }\n  });\n}\n```\n\n### 3. Handle Push When App Opens\n\n```dart\nFuture<void> _handlePushNotification() async {\n  final data = await TelnyxClient.getPushMetaData();\n  if (data != null) {\n    PushMetaData pushMetaData = PushMetaData.fromJson(data);\n    telnyxClient.handlePushNotification(\n      pushMetaData,\n      credentialConfig,\n      tokenConfig,\n    );\n  }\n}\n```\n\n### Early Accept/Decline Handling\n\n```dart\nbool _waitingForInvite = false;\n\nvoid acceptCall() {\n  if (_incomingInvite != null) {\n    _currentCall = telnyxClient.acceptCall(...);\n  } else {\n    // Set flag if invite hasn't arrived yet\n    _waitingForInvite = true;\n  }\n}\n\n// In socket message handler:\ncase SocketMethod.INVITE:\n  _incomingInvite = message.message.inviteParams;\n  if (_waitingForInvite) {\n    acceptCall();  // Accept now that invite arrived\n    _waitingForInvite = false;\n  }\n  break;\n```\n\n---\n\n## Push Notifications - iOS (APNS + PushKit)\n\n### 1. AppDelegate Setup\n\n```swift\n// AppDelegate.swift\nfunc pushRegistry(_ registry: PKPushRegistry, \n                  didUpdate credentials: PKPushCredentials, \n                  for type: PKPushType) {\n    let deviceToken = credentials.token.map { \n        String(format: \"%02x\", $0) \n    }.joined()\n    SwiftFlutterCallkitIncomingPlugin.sharedInstance?\n        .setDevicePushTokenVoIP(deviceToken)\n}\n\nfunc pushRegistry(_ registry: PKPushRegistry,\n                  didReceiveIncomingPushWith payload: PKPushPayload,\n                  for type: PKPushType,\n                  completion: @escaping () -> Void) {\n    guard type == .voIP else { return }\n    \n    if let metadata = payload.dictionaryPayload[\"metadata\"] as? [String: Any] {\n        let callerName = (metadata[\"caller_name\"] as? String) ?? \"\"\n        let callerNumber = (metadata[\"caller_number\"] as? String) ?? \"\"\n        let callId = (metadata[\"call_id\"] as? String) ?? UUID().uuidString\n        \n        let data = flutter_callkit_incoming.Data(\n            id: callId,\n            nameCaller: callerName,\n            handle: callerNumber,\n            type: 0\n        )\n        data.extra = payload.dictionaryPayload as NSDictionary\n        \n        SwiftFlutterCallkitIncomingPlugin.sharedInstance?\n            .showCallkitIncoming(data, fromPushKit: true)\n    }\n}\n```\n\n### 2. Handle in Flutter\n\n```dart\nFlutterCallkitIncoming.onEvent.listen((CallEvent? event) {\n  switch (event!.event) {\n    case Event.actionCallIncoming:\n      PushMetaData? pushMetaData = PushMetaData.fromJson(\n        event.body['extra']['metadata']\n      );\n      telnyxClient.handlePushNotification(\n        pushMetaData,\n        credentialConfig,\n        tokenConfig,\n      );\n      break;\n    case Event.actionCallAccept:\n      // Handle accept\n      break;\n  }\n});\n```\n\n---\n\n## Handling Late Notifications\n\n```dart\nconst CALL_MISSED_TIMEOUT = 60;  // seconds\n\nvoid handlePushMessage(RemoteMessage message) {\n  DateTime now = DateTime.now();\n  Duration? diff = now.difference(message.sentTime!);\n  \n  if (diff.inSeconds > CALL_MISSED_TIMEOUT) {\n    showMissedCallNotification(message);\n    return;\n  }\n  \n  // Handle normal incoming call...\n}\n```\n\n---\n\n## Call Quality Metrics\n\nEnable with `debug: true` in config:\n\n```dart\n// When making a call\ncall.newInvite(\n  callerName: 'John',\n  callerNumber: '+15551234567',\n  destinationNumber: '+15559876543',\n  clientState: 'state',\n  debug: true,\n);\n\n// Listen for quality updates\ncall.onCallQualityChange = (CallQualityMetrics metrics) {\n  print('MOS: ${metrics.mos}');\n  print('Jitter: ${metrics.jitter * 1000} ms');\n  print('RTT: ${metrics.rtt * 1000} ms');\n  print('Quality: ${metrics.quality}');  // excellent, good, fair, poor, bad\n};\n```\n\n| Quality Level | MOS Range |\n|---------------|-----------|\n| excellent | > 4.2 |\n| good | 4.1 - 4.2 |\n| fair | 3.7 - 4.0 |\n| poor | 3.1 - 3.6 |\n| bad | ≤ 3.0 |\n\n---\n\n## AI Agent Integration\n\nConnect to a Telnyx Voice AI Agent:\n\n### 1. Anonymous Login\n\n```dart\ntry {\n  await telnyxClient.anonymousLogin(\n    targetId: 'your_ai_assistant_id',\n    targetType: 'ai_assistant',  // Default\n    targetVersionId: 'optional_version_id',  // Optional\n  );\n} catch (e) {\n  print('Login failed: $e');\n}\n```\n\n### 2. Start Conversation\n\n```dart\ntelnyxClient.newInvite(\n  'User Name',\n  '+15551234567',\n  '',  // Destination ignored for AI Agent\n  'state',\n  customHeaders: {\n    'X-Account-Number': '123',  // Maps to {{account_number}}\n    'X-User-Tier': 'premium',   // Maps to {{user_tier}}\n  },\n);\n```\n\n### 3. Receive Transcripts\n\n```dart\ntelnyxClient.onTranscriptUpdate = (List<TranscriptItem> transcript) {\n  for (var item in transcript) {\n    print('${item.role}: ${item.content}');\n    // role: 'user' or 'assistant'\n    // content: transcribed text\n    // timestamp: when received\n  }\n};\n\n// Get current transcript anytime\nList<TranscriptItem> current = telnyxClient.transcript;\n\n// Clear transcript\ntelnyxClient.clearTranscript();\n```\n\n### 4. Send Text to AI Agent\n\n```dart\nCall? activeCall = telnyxClient.calls.values.firstOrNull;\n\nif (activeCall != null) {\n  activeCall.sendConversationMessage(\n    'Hello, I need help with my account'\n  );\n}\n```\n\n---\n\n## Custom Logging\n\n```dart\nclass MyCustomLogger extends CustomLogger {\n  @override\n  log(LogLevel level, String message) {\n    print('[$level] $message');\n    // Send to analytics, file, server, etc.\n  }\n}\n\nfinal config = CredentialConfig(\n  // ... other config\n  logLevel: LogLevel.debug,\n  customLogger: MyCustomLogger(),\n);\n```\n\n---\n\n## Troubleshooting\n\n| Issue | Solution |\n|-------|----------|\n| No audio on Android | Check RECORD_AUDIO permission |\n| No audio on iOS | Check NSMicrophoneUsageDescription in Info.plist |\n| Push not working (debug) | Push only works in release mode |\n| Login fails | Verify SIP credentials in Telnyx Portal |\n| 10-second timeout | INVITE didn't arrive - check network/push setup |\n| sender_id_mismatch | FCM project mismatch between app and server |\n\n<!-- BEGIN AUTO-GENERATED API REFERENCE -- do not edit below this line -->\n\n**[references/webrtc-server-api.md](references/webrtc-server-api.md) has the server-side WebRTC API — credential creation, token generation, and push notification setup. You MUST read it when setting up authentication or push notifications.**\n\n## API Reference\n\n\n### TxClient\n\n### Telnyx Client\n\nTelnyxClient() is the core class of the SDK, and can be used to connect to our backend socket connection, create calls, check state and disconnect, etc.\n\n```dart\n    TelnyxClient _telnyxClient = TelnyxClient();\n```\n### Logging into Telnyx Client\n\nTo log into the Telnyx WebRTC client, you'll need to authenticate using a Telnyx SIP Connection. Follow our [quickstart guide](https://developers.telnyx.com/docs/v2/webrtc/quickstart) to create **JWTs** (JSON Web Tokens) to authenticate. To log in with a token we use the connectWithToken() method. You can also authenticate directly with the SIP Connection `username` and `password` with the connectWithCredential() method:\n\n```dart\n    _telnyxClient.connectWithToken(tokenConfig)\n                     //OR\n    _telnyxClient.connectWithCredential(credentialConfig)             \n ```\n### Listening for events and reacting - Accepting a Call\n\nIn order to be able to accept a call, we first need to listen for invitations. We do this by getting the Telnyx Socket Response callbacks from our TelnyxClient:\n\n\n### Call\n\n### Call\n\nThe Call class is used to manage the call state and call actions. It is used to accept, decline, end, mute, hold, and send DTMF tones during a call.\n### Accept Call\n\nIn order to accept a call, we simply retrieve the instance of the call and use the .acceptCall(callID) method:\n\n```dart\n    _telnyxClient.call.acceptCall(_incomingInvite?.callID);\n```\n### Decline / End Call\n\nIn order to end a call, we can get a stored instance of Call and call the .endCall(callID) method. To decline an incoming call we first create the call with the .createCall() method and then call the .endCall(callID) method:\n\n```dart\n    if (_ongoingCall) {\n      _telnyxClient.call.endCall(_telnyxClient.call.callId);\n    } else {\n      _telnyxClient.createCall().endCall(_incomingInvite?.callID);\n    }\n```\n### DTMF (Dual Tone Multi Frequency)\n\nIn order to send a DTMF message while on a call you can call the .dtmf(callID, tone), method where tone is a String value of the character you would like pressed:\n\n```dart\n    _telnyxClient.call.dtmf(_telnyxClient.call.callId, tone);\n```\n### Mute a call\n\nTo mute a call, you can simply call the .onMuteUnmutePressed() method:\n\n```dart\n    _telnyxClient.call.onMuteUnmutePressed();\n```\n### Toggle loud speaker\n\nTo toggle loud speaker, you can simply call .enableSpeakerPhone(bool):\n\n```dart\n    _telnyxClient.call.enableSpeakerPhone(true);\n```\n### Put a call on hold\n\nTo put a call on hold, you can simply call the .onHoldUnholdPressed() method:\n\n```dart\n    _telnyxClient.call.onHoldUnholdPressed();\n```\n\n<!-- END AUTO-GENERATED API REFERENCE -->","tags":["telnyx","webrtc","client","flutter","team-telnyx","agent-skills","ai-coding-agent","claude-code","cpaas","cursor","iot","llm"],"capabilities":["skill","source-team-telnyx","skill-telnyx-webrtc-client-flutter","topic-agent-skills","topic-ai-coding-agent","topic-claude-code","topic-cpaas","topic-cursor","topic-iot","topic-llm","topic-sdk","topic-sip","topic-sms","topic-speech-to-text","topic-telephony"],"categories":["ai"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/team-telnyx/ai/telnyx-webrtc-client-flutter","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add team-telnyx/ai","source_repo":"https://github.com/team-telnyx/ai","install_from":"skills.sh"}},"qualityScore":"0.533","qualityRationale":"deterministic score 0.53 from registry signals: · indexed on github topic:agent-skills · 167 github stars · SKILL.md body (14,182 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:54:55.079Z","embedding":null,"createdAt":"2026-04-18T22:08:43.185Z","updatedAt":"2026-04-22T00:54:55.079Z","lastSeenAt":"2026-04-22T00:54:55.079Z","tsv":"'+15551234567':142,175,260,336,693,789 '+15559876543':262,695 '/docs/v2/webrtc/quickstart)':1049 '/or':1088 '/packages/telnyx_common)':67 '0':539,603 '02x':538 '1':118,365,370,518,755 '10':939 '1000':713,718 '123':801 '2':157,394,613,782 '3':444,815 '3.0':744 '3.1':741 '3.6':742 '3.7':738 '4':850 '4.0':739 '4.1':735 '4.2':733,736 '60':650 'abl':1103 'abstract':72 'accept':322,505,640,1096,1105,1147,1159,1164 'accept/decline':470 'acceptcal':327,477,504,1178 'access':113 'account':799,804,870 'action':415,1142 'activecal':858,861 'activecall.sendconversationmessage':863 'add':81,99,104 'agent':746,754,794,855 'ai':745,753,764,768,793,854 'also':1071 'analyt':889 'android':19,98,212,368,908 'androidmanifest.xml':101 'anonym':756 'answer':315 'anytim':843 'api':967,987 'apn':214,516 'app':448,956 'appdeleg':519 'appdelegate.swift':522 'applic':18 'arriv':490,509,945 'asset':243,250 'assist':765,769,833 'async':382,402,453 'audio':906,911,914 'authent':116,983,1037,1057,1072 'auto':220 'auto-retri':219 'automat':442 'autoreconnect':148,178,217 'await':387,456,760 'backend':1008 'background':395 'bad':727,743 'base':121,160 'bash':92 'bool':218,226,473,1308 'break':293,299,310,316,321,430,443,512,636,641 'build':10 'call':115,228,254,271,279,292,303,308,313,319,325,338,342,347,587,647,665,674,675,688,857,1012,1098,1107,1128,1129,1131,1138,1141,1158,1160,1166,1174,1187,1193,1201,1203,1212,1217,1224,1254,1257,1282,1286,1290,1306,1314,1320,1326 'call.newinvite':689 'call.oncallqualitychange':704 'callback':1124 'caller':198,206,573,580 'callernam':259,571,599,690 'callernumb':261,578,601,692 'callev':417,619 'callid':351,585,597,1179,1184,1206,1227,1238,1260 'callkit':408 'callqualitymetr':705 'case':286,294,300,311,317,422,431,498,624,637 'catch':776 'charact':1271 'check':909,917,946,1013 'class':874,996,1132 'clear':847 'client':4,991,1025,1032 'clientstat':268,696 'common':64 'communic':15 'complet':554 'config':683,894,897 'configur':97,184 'connect':748,1005,1010,1042,1077 'connectwithcredenti':1083 'connectwithtoken':1067 'consid':62 'const':392,646 'content':834 'control':339 'convers':784 'core':995 'creat':23,1011,1051,1215 'createcal':1220 'creation':969 'credenti':25,120,192,528,935,968 'credential-bas':119 'credentialconfig':128,129,155,467,634,895,1090 'credentials.token.map':535 'current':841,845 'currentcal':280,331,481 'custom':241,247,266,871 'customhead':796 'customlogg':877,900 'dart':123,163,255,276,340,373,397,450,472,617,645,684,758,785,818,856,873,1018,1085,1181,1229,1276,1294,1309,1330 'data':455,459,464,594,610 'data.extra':604 'datetim':656 'datetime.now':658 'debug':150,180,225,236,680,698,924 'declin':345,441,1148,1185,1209 'default':770 'defaulttargetplatform':385 'depend':85 'descript':188 'destin':790 'destinationnumb':263,694 'developers.telnyx.com':1048 'developers.telnyx.com/docs/v2/webrtc/quickstart)':1047 'devicetoken':534,543 'didn':943 'didreceiveincomingpushwith':548 'didupd':527 'diff':660 'diff.inseconds':664 'direct':1073 'disconnect':1016 'display':139,172,201 'doe':258 'dtmf':361,1154,1239,1249,1259 'dual':1240 'durat':659 'e':777,781 'e.g':49,405 'earli':469 'els':483,560,1234 'enabl':227,678 'enablespeakerphon':1307 'end':320,341,1149,1186,1191 'endcal':349,1205,1226,1236 'entri':378 'entry-point':377 'error':234 'escap':555 'etc':892,1017 'event':275,418,420,421,620,622,623,1093 'event.actioncallaccept':423,638 'event.actioncalldecline':432 'event.actioncallincoming':625 'event.body':629 'excel':723,732 'extend':876 'extra':630 'fail':780,932 'failur':224 'fair':725,737 'fals':429,436,475,511 'faster':60 'fcm':211,369,952 'fcmorapnstoken':144,177 'file':890 'final':124,127,164,454,893 'firebas':372 'firebase.initializeapp':388 'firebasebackgroundhandl':390,399 'firebasemessaging.onbackgroundmessage':389 'first':1109,1214 'flag':485 'flutter':5,8,17,93,407,616 'flutter_callkit_incoming.data':595 'fluttercallkitincoming.onevent.listen':416,618 'follow':1043 'format':537 'frequenc':1243 'frompushkit':611 'func':523,544 'futur':380,398,451 'generat':27,971 'get':95,840,1119,1196 'good':724,734 'guard':557 'guid':1046 'handl':440,445,471,600,614,639,642,671 'handlepushmessag':653 'handlepushnotif':452 'handler':396,497 'hasn':488 'hello':864 'help':867 'higher':70 'higher-level':69 'hold':1151,1316,1322 'hold/unhold':354 'id':199,207,588,596,766,774,950 'ignor':791 'implement':61 'inbound':270 'incom':302,307,324,346,409,673,1211 'incominginvit':278,304,329,333,350,479,500,1183,1237 'info':237 'info.plist':106,920 'instal':80 'instanc':1171,1199 'integr':76,747 'invit':487,508,942,1114 'inviteparam':277 'io':20,103,215,515,916 'isansw':426,435 'isdeclin':428,437 'issu':903 'item':824 'item.content':829 'item.role':828 'javascript':55 'jitter':711 'john':257,691 'join':540 'json':1053 'jwt':162,169 'jwts':1052 'languag':47 'late':643 'latest':88 'let':533,563,570,577,584,593 'level':71,729,881,885 'like':1274 'list':820,844 'listen':272,412,700,1091,1112 'll':1034 'log':297,872,879,1022,1027,1059 'login':29,122,161,222,757,779,931 'loglevel':152,231,232,880,898 'loglevel.debug':153,899 'loud':1297,1301 'main':381 'main.dart':374 'make':252,686 'make/receive':291 'manag':1136 'map':802,811 'messag':283,401,411,496,655,669,883,886,1250 'message.data':425,434 'message.message.inviteparams':305,501 'message.senttime':662 'message.socketmethod':285 'metadata':564,566,572,579,586,631 'method':1068,1084,1180,1207,1221,1228,1262,1293,1329 'metric':230,677,706 'metrics.jitter':712 'metrics.mos':709 'metrics.quality':722 'metrics.rtt':717 'microphon':112 'minim':78 'mismatch':951,954 'miss':648,666 'mode':930 'mos':708,730 'ms':714,719 'multi':1242 'must':977 'mute':1150,1280,1284 'mute/unmute':352 'my-custom-st':264 'myapp':393 'mycustomlogg':875,901 'name':110,140,173,200,335,574,788 'namecal':598 'need':111,866,1035,1110 'network/push':947 'none':233 'normal':672 'notif':367,404,514,644,974,986 'notificationtoken':143,176,209 'now.difference':661 'nsdictionari':607 'nsmicrophoneusagedescript':108,918 'null':330,460,480,862 'number':208,581,800,805 'ongoingcal':1231 'onholdunholdpress':1328 'onmuteunmutepress':1292 'open':449 'option':58,117,145,156,185,772,775 'order':1100,1162,1189,1245 'outbound':253 'overrid':878 'paramet':186 'password':137,1080 'path':244,251 'payload':549 'payload.dictionarypayload':565,605 'permiss':912 'pkpushcredenti':529 'pkpushpayload':550 'pkpushregistri':526,547 'pkpushtyp':532,553 'platform':96 'plugin':48 'point':379 'poor':726,740 'portal':195,938 'pragma':375 'premium':810 'prerequisit':22 'press':1275 'print':707,710,715,720,778,827,884 'product':109 'project':953 'pub':94 'pub.dev':66 'pub.dev/packages/telnyx_common)':65 'pubspec.yaml':83 'push':147,366,446,513,921,925,973,985 'pushkit':517 'pushmetadata':461,462,466,626,627,633 'pushmetadata.fromjson':463,628 'pushregistri':524,545 'put':1312,1318 'python':52 'qualiti':229,676,702,721,728 'quick':56 'quickstart':1045 'rang':731 'react':1095 'read':978 'readi':288,289 'real':12 'real-tim':11 'receiv':269,816,839 'recipi':203 'record':910 'refer':988 'references/webrtc-server-api.md':959,960 'registri':525,546 'releas':929 'remotemessag':400,654 'respons':1123 'retri':221 'retriev':1169 'return':561,670 'ringback':248 'ringbackpath':245 'rington':242 'ringtonepath':239 'role':830 'rtt':716 'run':91 'runapp':391 'sdk':9,37,439,999 'second':651,940 'see':38 'send':360,851,887,1153,1247 'sender':949 'server':35,46,891,958,964 'server-sid':34,963 'set':484,981 'setdevicepushtokenvoip':542 'setup':79,371,520,948,975 'show':306,403 'showcallkitincom':609 'showincomingcallnotif':410 'showmissedcallnotif':668 'side':36,965 'simpli':1168,1289,1305,1325 'simplifi':74 'sip':132,136,934,1041,1076 'sipcalleridnam':138,171,196 'sipcalleridnumb':141,174,204 'sippassword':134 'siptoken':167,190 'sipus':130,189 'skill':43 'skill-telnyx-webrtc-client-flutter' 'socket':274,495,1009,1122 'socketmethod.answer':312 'socketmethod.bye':318 'socketmethod.client':287 'socketmethod.invite':301,499 'socketmethod.login':295 'solut':904 'source-team-telnyx' 'speaker':357,1298,1302 'start':57,783 'state':267,337,697,795,1014,1139 'store':1198 'string':191,197,205,210,240,246,536,568,576,583,590,882,1267 'success':296 'swift':521 'swiftfluttercallkitincomingplugin.sharedinstance':541,608 'switch':284,419,621 'targetid':762 'targetplatform.android':386 'targettyp':767 'targetversionid':771 'telnyx':2,6,33,41,51,54,63,86,194,751,937,990,1024,1030,1040,1121 'telnyx-javascript':53 'telnyx-python':50 'telnyx-webrtc':40 'telnyx-webrtc-client-flutt':1 'telnyxcli':125,126,992,1019,1020,1021,1127 'telnyxclient.acceptcall':332,482 'telnyxclient.anonymouslogin':761 'telnyxclient.call.acceptcall':1182 'telnyxclient.call.callid':344,364,1233,1278 'telnyxclient.call.dtmf':363,1277 'telnyxclient.call.enablespeakerphone':358,1310 'telnyxclient.call.endcall':343,1232 'telnyxclient.call.newinvite':256 'telnyxclient.call.onholdunholdpressed':355,1331 'telnyxclient.call.onmuteunmutepressed':353,1295 'telnyxclient.calls.values.firstornull':859 'telnyxclient.cleartranscript':849 'telnyxclient.connectwithcredential':154,1089 'telnyxclient.connectwithtoken':182,1086 'telnyxclient.createcall':348,1235 'telnyxclient.getpushmetadata':457 'telnyxclient.handlepushnotification':465,632 'telnyxclient.newinvite':786 'telnyxclient.onsocketmessagereceived':281 'telnyxclient.ontranscriptupdate':819 'telnyxclient.setpushmetadata':424,433 'telnyxclient.transcript':846 'telnyxmessag':282 'text':836,852 'tier':809,814 'time':13 'timeout':649,667,941 'timestamp':837 'toggl':356,1296,1300 'token':30,159,170,216,970,1055,1063 'token-bas':158 'tokenconfig':165,166,183,468,635,1087 'tone':249,362,1155,1241,1261,1264,1279 'topic-agent-skills' 'topic-ai-coding-agent' 'topic-claude-code' 'topic-cpaas' 'topic-cursor' 'topic-iot' 'topic-llm' 'topic-sdk' 'topic-sip' 'topic-sms' 'topic-speech-to-text' 'topic-telephony' 'transcrib':835 'transcript':817,821,826,842,848 'tri':759 'troubleshoot':902 'true':149,151,179,181,359,427,438,493,612,681,699,1311 'txclient':989 'type':187,531,552,558,602 'ui':309 'updat':703 'use':31,406,1003,1038,1065,1134,1145,1176 'user':414,787,808,813,831 'usernam':133,1078 'uuid':591 'uuidstr':592 'valu':1268 'var':823 'verifi':933 'version':89,773 'vm':376 'voic':14,752 'void':326,476,556,652 'voip':559 'waitingforinvit':474,492,503,510 'warn':235 'web':21,1054 'webrtc':3,7,24,42,75,87,966,1031 'widgetsflutterbinding.ensureinitialized':383 'work':923,927 'would':1273 'x':798,807 'x-account-numb':797 'x-user-ti':806 'xml':102,107 'yaml':84 'yet':491","prices":[{"id":"0fade6ed-9b9f-45b9-99f8-4ba5566861d3","listingId":"56a84f05-2acb-467f-8fdc-669ae68299a9","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"team-telnyx","category":"ai","install_from":"skills.sh"},"createdAt":"2026-04-18T22:08:43.185Z"}],"sources":[{"listingId":"56a84f05-2acb-467f-8fdc-669ae68299a9","source":"github","sourceId":"team-telnyx/ai/telnyx-webrtc-client-flutter","sourceUrl":"https://github.com/team-telnyx/ai/tree/main/skills/telnyx-webrtc-client-flutter","isPrimary":false,"firstSeenAt":"2026-04-18T22:08:43.185Z","lastSeenAt":"2026-04-22T00:54:55.079Z"}],"details":{"listingId":"56a84f05-2acb-467f-8fdc-669ae68299a9","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"team-telnyx","slug":"telnyx-webrtc-client-flutter","github":{"repo":"team-telnyx/ai","stars":167,"topics":["agent-skills","ai","ai-coding-agent","claude-code","cpaas","cursor","iot","llm","sdk","sip","sms","speech-to-text","telephony","telnyx","tts","twilio-migration","voice-agents","voice-ai","webrtc","windsurf"],"license":"mit","html_url":"https://github.com/team-telnyx/ai","pushed_at":"2026-04-21T22:09:49Z","description":"Official one-stop shop for AI Agents and developers building with Telnyx.","skill_md_sha":"75034a4c5a1039af37a8b7af601e4862d73f07fa","skill_md_path":"skills/telnyx-webrtc-client-flutter/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/team-telnyx/ai/tree/main/skills/telnyx-webrtc-client-flutter"},"layout":"multi","source":"github","category":"ai","frontmatter":{"name":"telnyx-webrtc-client-flutter","description":">-"},"skills_sh_url":"https://skills.sh/team-telnyx/ai/telnyx-webrtc-client-flutter"},"updatedAt":"2026-04-22T00:54:55.079Z"}}