facesign-sdk 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
facesign_sdk/client.py ADDED
@@ -0,0 +1,1504 @@
1
+ import httpx
2
+ import uuid
3
+ import urllib.parse
4
+ from dataclasses import dataclass
5
+ from typing import Literal, Any
6
+ from pydantic import BaseModel, ConfigDict, Field
7
+
8
+ class AgeRangeFaceFeature(BaseModel):
9
+ model_config = ConfigDict(populate_by_name = True)
10
+ low: int = Field(serialization_alias = "low", alias = "low")
11
+ high: int = Field(serialization_alias = "high", alias = "high")
12
+
13
+ class ApiKey(BaseModel):
14
+ model_config = ConfigDict(populate_by_name = True)
15
+ id: str = Field(serialization_alias = "id", alias = "id")
16
+ name: str = Field(serialization_alias = "name", alias = "name")
17
+ obfuscated_value: str = Field(serialization_alias = "obfuscatedValue", alias = "obfuscatedValue")
18
+ last_used_at: str | None = Field(serialization_alias = "lastUsedAt", alias = "lastUsedAt", default = None)
19
+ plain_text_value: str | None = Field(serialization_alias = "plainTextValue", alias = "plainTextValue", default = None)
20
+ scope: str | None = Field(serialization_alias = "scope", alias = "scope", default = None)
21
+
22
+ AssistantSpeechDeliveryExtent = Literal["none" , "partial" , "full" , "unknown"]
23
+ AssistantSpeechEvidenceQuality = Literal["exact" , "estimated" , "provider_reported" , "unknown"]
24
+ AssistantSpeechRealtimeStatus = Literal["active" , "completed" , "interrupted" , "failed" , "timed_out"]
25
+ AssistantSpeechTerminalReasonCode = Literal["playback_completed" , "user_barge_in" , "reconnect_recovery" , "playback_start_timeout" , "playback_completion_timeout" , "interruption_acknowledgement_timeout" , "tts_failure_before_audio" , "tts_failure_after_partial_audio" , "avatar_failure" , "session_terminated" , "pipeline_failure"]
26
+ AssistantSpeechTerminalStatus = Literal["completed" , "interrupted" , "failed" , "timed_out"]
27
+ AudioCodec = Literal["opus" , "aac"]
28
+ class Avatar(BaseModel):
29
+ model_config = ConfigDict(populate_by_name = True)
30
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
31
+ name: str = Field(serialization_alias = "name", alias = "name")
32
+ created_at: str | None = Field(serialization_alias = "createdAt", alias = "createdAt", default = None)
33
+ image_url: str | None = Field(serialization_alias = "imageUrl", alias = "imageUrl", default = None)
34
+ is_custom: bool = Field(serialization_alias = "isCustom", alias = "isCustom")
35
+
36
+ LemonSliceImageState = Literal["awaiting_upload" , "uploaded" , "failed"]
37
+ class ErrorInfo(BaseModel):
38
+ model_config = ConfigDict(populate_by_name = True)
39
+ code: str = Field(serialization_alias = "code", alias = "code")
40
+ message: str = Field(serialization_alias = "message", alias = "message")
41
+ fields: list[str] | None = Field(serialization_alias = "fields", alias = "fields", default = None)
42
+
43
+ class BoundingBox(BaseModel):
44
+ model_config = ConfigDict(populate_by_name = True)
45
+ top: float = Field(serialization_alias = "top", alias = "top")
46
+ left: float = Field(serialization_alias = "left", alias = "left")
47
+ width: float = Field(serialization_alias = "width", alias = "width")
48
+ height: float = Field(serialization_alias = "height", alias = "height")
49
+
50
+ class TrustedParticipantIdentities(BaseModel):
51
+ model_config = ConfigDict(populate_by_name = True)
52
+ orchestrator: str = Field(serialization_alias = "orchestrator", alias = "orchestrator")
53
+ avatar: str = Field(serialization_alias = "avatar", alias = "avatar")
54
+
55
+ class BrowserSessionError(BaseModel):
56
+ model_config = ConfigDict(populate_by_name = True)
57
+ code: str = Field(serialization_alias = "code", alias = "code")
58
+ message: str = Field(serialization_alias = "message", alias = "message")
59
+ retryable: bool = Field(serialization_alias = "retryable", alias = "retryable")
60
+
61
+ class City(BaseModel):
62
+ model_config = ConfigDict(populate_by_name = True)
63
+ name: str | None = Field(serialization_alias = "name", alias = "name", default = None)
64
+ geo_name_id: int | None = Field(serialization_alias = "geoNameId", alias = "geoNameId", default = None)
65
+ confidence: int | None = Field(serialization_alias = "confidence", alias = "confidence", default = None)
66
+
67
+ class ConversationOutcome(BaseModel):
68
+ model_config = ConfigDict(populate_by_name = True)
69
+ # Description of the condition to end the conversation and go to the mapped target
70
+ condition: str | None = Field(serialization_alias = "condition", alias = "condition", default = None)
71
+ # Once this data is collected go to the mapped target
72
+ collect: list[str] | None = Field(serialization_alias = "collect", alias = "collect", default = None)
73
+ # Node key to go to when the outcome matches
74
+ target: str = Field(serialization_alias = "target", alias = "target")
75
+
76
+ ConversationRealtimeMode = Literal["listening" , "thinking" , "speaking" , "terminating" , "terminal"]
77
+ SessionStatus = Literal["created" , "in_progress" , "complete" , "incomplete"]
78
+ SessionTerminalReasonCode = Literal["queue_publish_failed" , "processor_startup_failed" , "worker_crashed" , "flow_failed" , "media_failed" , "disconnect_grace_expired" , "join_timeout" , "session_timeout" , "cancelled_by_user" , "cancelled_by_tenant" , "service_shutdown" , "internal_error" , "legacy_unclassified"]
79
+ class ConversationTranscriptEntry(BaseModel):
80
+ model_config = ConfigDict(populate_by_name = True)
81
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
82
+ speaker: str = Field(serialization_alias = "speaker", alias = "speaker")
83
+ text: str = Field(serialization_alias = "text", alias = "text")
84
+
85
+ class Country(BaseModel):
86
+ model_config = ConfigDict(populate_by_name = True)
87
+ iso_code: str | None = Field(serialization_alias = "isoCode", alias = "isoCode", default = None)
88
+ name: str | None = Field(serialization_alias = "name", alias = "name", default = None)
89
+ names: dict[str, str] | None = Field(serialization_alias = "names", alias = "names", default = None)
90
+ geo_name_id: int | None = Field(serialization_alias = "geoNameId", alias = "geoNameId", default = None)
91
+ confidence: int | None = Field(serialization_alias = "confidence", alias = "confidence", default = None)
92
+
93
+ class CreatedAvatar(BaseModel):
94
+ model_config = ConfigDict(populate_by_name = True)
95
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
96
+ upload_url: str = Field(serialization_alias = "uploadUrl", alias = "uploadUrl")
97
+ blob_key: str = Field(serialization_alias = "blobKey", alias = "blobKey")
98
+
99
+ class CreateSessionPropRequest(BaseModel):
100
+ model_config = ConfigDict(populate_by_name = True)
101
+ name: str = Field(serialization_alias = "name", alias = "name")
102
+ value: str = Field(serialization_alias = "value", alias = "value")
103
+
104
+ class CreateUserApiKeyRequest(BaseModel):
105
+ model_config = ConfigDict(populate_by_name = True)
106
+ name: str = Field(serialization_alias = "name", alias = "name")
107
+ organization_id: str | None = Field(serialization_alias = "organizationId", alias = "organizationId", default = None)
108
+ permissions: list[str] | None = Field(serialization_alias = "permissions", alias = "permissions", default = None)
109
+
110
+ class ExpressionOutcomes(BaseModel):
111
+ model_config = ConfigDict(populate_by_name = True)
112
+ # Which node to go to when the expression evaluated to a truthy value
113
+ true: str = Field(serialization_alias = "true", alias = "true")
114
+ # Which node to go to when the expression evaluated to a falsy value
115
+ false: str = Field(serialization_alias = "false", alias = "false")
116
+
117
+ class ExtractionDefinition(BaseModel):
118
+ model_config = ConfigDict(populate_by_name = True)
119
+ type: str = Field(serialization_alias = "type", alias = "type")
120
+ description: str = Field(serialization_alias = "description", alias = "description")
121
+
122
+ class GenderFaceFeature(BaseModel):
123
+ model_config = ConfigDict(populate_by_name = True)
124
+ confidence: float = Field(serialization_alias = "confidence", alias = "confidence")
125
+ value: str = Field(serialization_alias = "value", alias = "value")
126
+
127
+ class FaceRecognitionOutcomes(BaseModel):
128
+ model_config = ConfigDict(populate_by_name = True)
129
+ # The user matches a known face
130
+ match_1: str | None = Field(serialization_alias = "match", alias = "match", default = None)
131
+ # No matched user is found
132
+ no_match: str | None = Field(serialization_alias = "no_match", alias = "no_match", default = None)
133
+ # No face is detected
134
+ no_face: str | None = Field(serialization_alias = "no_face", alias = "no_face", default = None)
135
+
136
+ class TurnGenerationOptions(BaseModel):
137
+ model_config = ConfigDict(populate_by_name = True)
138
+ # Instruct the assistant's AI, in plain english to generate the speech. Use this when the speech need to be generated on the fly to be relevant to the conversation
139
+ instruction: str | None = Field(serialization_alias = "instruction", alias = "instruction", default = None)
140
+ # Text the assistant should speakm in English. Variable substitution is supported and text will be translated to the user's language on demand
141
+ template: str | None = Field(serialization_alias = "template", alias = "template", default = None)
142
+ # Provide a set of verbatim speech, in different languages, for the assistant to speak. If provided, all requested languages must be provided. No variable substitution of translation is applied
143
+ verbatim: dict[str, str] | None = Field(serialization_alias = "verbatim", alias = "verbatim", default = None)
144
+
145
+ class VerificationCodeOutcomes(BaseModel):
146
+ model_config = ConfigDict(populate_by_name = True)
147
+ # The user provided the correct code back
148
+ verified: str = Field(serialization_alias = "verified", alias = "verified")
149
+ # The code could not be sent to the user
150
+ delivery_failed: str | None = Field(serialization_alias = "delivery_failed", alias = "delivery_failed", default = None)
151
+ # The user failed to provide the correct code after all attempts
152
+ unverified: str = Field(serialization_alias = "unverified", alias = "unverified")
153
+ # The user cancelled the verification
154
+ cancelled: str | None = Field(serialization_alias = "cancelled", alias = "cancelled", default = None)
155
+
156
+ class LivenessOutcomes(BaseModel):
157
+ model_config = ConfigDict(populate_by_name = True)
158
+ # Live person is confirmed
159
+ authentic: str | None = Field(serialization_alias = "authentic", alias = "authentic", default = None)
160
+ # Deepfake or replay attack detected
161
+ synthetic: str | None = Field(serialization_alias = "synthetic", alias = "synthetic", default = None)
162
+ # No face was found in frames
163
+ no_face: str | None = Field(serialization_alias = "no_face", alias = "no_face", default = None)
164
+
165
+ class UsageDetails(BaseModel):
166
+ model_config = ConfigDict(populate_by_name = True)
167
+ input_token_count: int | None = Field(serialization_alias = "inputTokenCount", alias = "inputTokenCount", default = None)
168
+ output_token_count: int | None = Field(serialization_alias = "outputTokenCount", alias = "outputTokenCount", default = None)
169
+ total_token_count: int | None = Field(serialization_alias = "totalTokenCount", alias = "totalTokenCount", default = None)
170
+ cached_input_token_count: int | None = Field(serialization_alias = "cachedInputTokenCount", alias = "cachedInputTokenCount", default = None)
171
+ reasoning_token_count: int | None = Field(serialization_alias = "reasoningTokenCount", alias = "reasoningTokenCount", default = None)
172
+ input_audio_token_count: int | None = Field(serialization_alias = "inputAudioTokenCount", alias = "inputAudioTokenCount", default = None)
173
+ input_text_token_count: int | None = Field(serialization_alias = "inputTextTokenCount", alias = "inputTextTokenCount", default = None)
174
+ output_audio_token_count: int | None = Field(serialization_alias = "outputAudioTokenCount", alias = "outputAudioTokenCount", default = None)
175
+ output_text_token_count: int | None = Field(serialization_alias = "outputTextTokenCount", alias = "outputTextTokenCount", default = None)
176
+ additional_counts: dict[str, int] | None = Field(serialization_alias = "additionalCounts", alias = "additionalCounts", default = None)
177
+
178
+ IdentityContactType = Literal["email" , "phone"]
179
+ class PaginationInfo(BaseModel):
180
+ model_config = ConfigDict(populate_by_name = True)
181
+ page: int | None = Field(serialization_alias = "page", alias = "page", default = None)
182
+ page_size: int | None = Field(serialization_alias = "pageSize", alias = "pageSize", default = None)
183
+ total_count: int | None = Field(serialization_alias = "totalCount", alias = "totalCount", default = None)
184
+ total_pages: int | None = Field(serialization_alias = "totalPages", alias = "totalPages", default = None)
185
+
186
+ class User(BaseModel):
187
+ model_config = ConfigDict(populate_by_name = True)
188
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
189
+ first_name: str = Field(serialization_alias = "firstName", alias = "firstName")
190
+ last_name: str = Field(serialization_alias = "lastName", alias = "lastName")
191
+ email: str = Field(serialization_alias = "email", alias = "email")
192
+ created_at: str = Field(serialization_alias = "createdAt", alias = "createdAt")
193
+ role: str = Field(serialization_alias = "role", alias = "role")
194
+
195
+ LivenessProvider = Literal["face_intel" , "llm"]
196
+ ParticipantRole = int
197
+ class PostAvatarImageRequest(BaseModel):
198
+ model_config = ConfigDict(populate_by_name = True)
199
+ name: str = Field(serialization_alias = "name", alias = "name")
200
+ image_width: int = Field(serialization_alias = "imageWidth", alias = "imageWidth")
201
+ image_height: int = Field(serialization_alias = "imageHeight", alias = "imageHeight")
202
+ image_mime_type: str = Field(serialization_alias = "imageMimeType", alias = "imageMimeType")
203
+ image_size: int = Field(serialization_alias = "imageSize", alias = "imageSize")
204
+
205
+ SessionEventType = Literal["created" , "started" , "complete" , "incomplete" , "user_connected" , "user_disconnected" , "assistant_connected" , "assistant_disconnected" , "flow_node_transition" , "flow_node_wait" , "user_data_input" , "assistant_speak" , "assistant_speech_terminal" , "assistant_idle"]
206
+ class SessionFlowAvatar(BaseModel):
207
+ model_config = ConfigDict(populate_by_name = True)
208
+ id: str | None = Field(serialization_alias = "id", alias = "id", default = None)
209
+
210
+ class SessionFlowVoice(BaseModel):
211
+ model_config = ConfigDict(populate_by_name = True)
212
+ id: str | None = Field(serialization_alias = "id", alias = "id", default = None)
213
+
214
+ class UtteranceWord(BaseModel):
215
+ model_config = ConfigDict(populate_by_name = True)
216
+ confidence: float = Field(serialization_alias = "confidence", alias = "confidence")
217
+ start: float = Field(serialization_alias = "start", alias = "start")
218
+ end: float = Field(serialization_alias = "end", alias = "end")
219
+ punctuated_word: str | None = Field(serialization_alias = "punctuatedWord", alias = "punctuatedWord", default = None)
220
+ heard_word: str = Field(serialization_alias = "heardWord", alias = "heardWord")
221
+
222
+ VideoCodec = Literal["vp8" , "vp9"]
223
+ VideoContainer = Literal["webm"]
224
+ class AssistantSpeechStateVerificationMessage(BaseModel):
225
+ model_config = ConfigDict(populate_by_name = True)
226
+ speech_id: uuid.UUID = Field(serialization_alias = "speech_id", alias = "speech_id")
227
+ turn_generation_id: int = Field(serialization_alias = "turn_generation_id", alias = "turn_generation_id")
228
+ speech_generation_id: int = Field(serialization_alias = "speech_generation_id", alias = "speech_generation_id")
229
+ revision: int = Field(serialization_alias = "revision", alias = "revision")
230
+ status: AssistantSpeechRealtimeStatus = Field(serialization_alias = "status", alias = "status")
231
+ generated_text: str = Field(serialization_alias = "generated_text", alias = "generated_text")
232
+ delivered_text: str | None = Field(serialization_alias = "delivered_text", alias = "delivered_text", default = None)
233
+ delivery_extent: AssistantSpeechDeliveryExtent = Field(serialization_alias = "delivery_extent", alias = "delivery_extent")
234
+ start_offset_ms: int | None = Field(serialization_alias = "start_offset_ms", alias = "start_offset_ms", default = None)
235
+ end_offset_ms: int | None = Field(serialization_alias = "end_offset_ms", alias = "end_offset_ms", default = None)
236
+ estimated_played_duration_ms: int | None = Field(serialization_alias = "estimated_played_duration_ms", alias = "estimated_played_duration_ms", default = None)
237
+
238
+ class AvatarConfigEntityBase(BaseModel):
239
+ model_config = ConfigDict(populate_by_name = True)
240
+ preview_blob_key: str | None = Field(serialization_alias = "preview_blob_key", alias = "preview_blob_key", default = None)
241
+
242
+ class AvatarConfigEntityLiveAvatarConfigEntity(BaseModel):
243
+ model_config = ConfigDict(populate_by_name = True)
244
+ type: str = Field(serialization_alias = "$type", alias = "$type")
245
+ id: str = Field(serialization_alias = "id", alias = "id")
246
+ preview_blob_key: str | None = Field(serialization_alias = "preview_blob_key", alias = "preview_blob_key", default = None)
247
+
248
+ class AvatarConfigEntityLemonSliceAgentConfigEntity(BaseModel):
249
+ model_config = ConfigDict(populate_by_name = True)
250
+ type: str = Field(serialization_alias = "$type", alias = "$type")
251
+ id: str = Field(serialization_alias = "id", alias = "id")
252
+ preview_blob_key: str | None = Field(serialization_alias = "preview_blob_key", alias = "preview_blob_key", default = None)
253
+
254
+ class AvatarConfigEntityLemonSliceImageConfigEntity(BaseModel):
255
+ model_config = ConfigDict(populate_by_name = True)
256
+ type: str = Field(serialization_alias = "$type", alias = "$type")
257
+ blob_key: str = Field(serialization_alias = "blob_key", alias = "blob_key")
258
+ state: LemonSliceImageState | None = Field(serialization_alias = "state", alias = "state", default = None)
259
+ preview_blob_key: str | None = Field(serialization_alias = "preview_blob_key", alias = "preview_blob_key", default = None)
260
+
261
+ AvatarConfigEntity = AvatarConfigEntityLiveAvatarConfigEntity | AvatarConfigEntityLemonSliceAgentConfigEntity | AvatarConfigEntityLemonSliceImageConfigEntity
262
+
263
+ class AvatarResponse(BaseModel):
264
+ model_config = ConfigDict(populate_by_name = True)
265
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
266
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
267
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
268
+ data: Avatar | None = Field(serialization_alias = "data", alias = "data", default = None)
269
+
270
+ class CreateApiKeyResponse(BaseModel):
271
+ model_config = ConfigDict(populate_by_name = True)
272
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
273
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
274
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
275
+ data: ApiKey | None = Field(serialization_alias = "data", alias = "data", default = None)
276
+
277
+ class ErrorResponse(BaseModel):
278
+ model_config = ConfigDict(populate_by_name = True)
279
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
280
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
281
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
282
+ data: list[ErrorInfo] | None = Field(serialization_alias = "data", alias = "data", default = None)
283
+
284
+ class GetDemoReportResponse(BaseModel):
285
+ model_config = ConfigDict(populate_by_name = True)
286
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
287
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
288
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
289
+ data: str | None = Field(serialization_alias = "data", alias = "data", default = None)
290
+
291
+ class BrowserSessionBootstrap(BaseModel):
292
+ model_config = ConfigDict(populate_by_name = True)
293
+ contract_version: int | None = Field(serialization_alias = "contractVersion", alias = "contractVersion", default = None)
294
+ session_id: uuid.UUID = Field(serialization_alias = "sessionId", alias = "sessionId")
295
+ language: str = Field(serialization_alias = "language", alias = "language")
296
+ room_url: str = Field(serialization_alias = "roomUrl", alias = "roomUrl")
297
+ room_token: str = Field(serialization_alias = "roomToken", alias = "roomToken")
298
+ trusted_participants: TrustedParticipantIdentities = Field(serialization_alias = "trustedParticipants", alias = "trustedParticipants")
299
+ allowed_embed_origins: list[str] = Field(serialization_alias = "allowedEmbedOrigins", alias = "allowedEmbedOrigins")
300
+
301
+ class BrowserSessionErrorResponse(BaseModel):
302
+ model_config = ConfigDict(populate_by_name = True)
303
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
304
+ error: BrowserSessionError = Field(serialization_alias = "error", alias = "error")
305
+
306
+ class ConversationSessionTerminalState(BaseModel):
307
+ model_config = ConfigDict(populate_by_name = True)
308
+ status: SessionStatus = Field(serialization_alias = "status", alias = "status")
309
+ reason_code: SessionTerminalReasonCode | None = Field(serialization_alias = "reason_code", alias = "reason_code", default = None)
310
+
311
+ class SessionEventMetadataFlowNodeTransitionEventMetadata(BaseModel):
312
+ model_config = ConfigDict(populate_by_name = True)
313
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
314
+ from_1: str | None = Field(serialization_alias = "from", alias = "from", default = None)
315
+ to: str | None = Field(serialization_alias = "to", alias = "to", default = None)
316
+
317
+ class SessionEventMetadataFlowNodeWaitEventMetadata(BaseModel):
318
+ model_config = ConfigDict(populate_by_name = True)
319
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
320
+ node_id: str = Field(serialization_alias = "nodeId", alias = "nodeId")
321
+
322
+ class SessionEventMetadataAssistantSpeakEventMetadata(BaseModel):
323
+ model_config = ConfigDict(populate_by_name = True)
324
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
325
+ speech_id: uuid.UUID | None = Field(serialization_alias = "speechId", alias = "speechId", default = None)
326
+ turn_generation_id: int | None = Field(serialization_alias = "turnGenerationId", alias = "turnGenerationId", default = None)
327
+ speech_generation_id: int | None = Field(serialization_alias = "speechGenerationId", alias = "speechGenerationId", default = None)
328
+
329
+ class SessionEventMetadataAssistantSpeechTerminalEventMetadata(BaseModel):
330
+ model_config = ConfigDict(populate_by_name = True)
331
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
332
+ speech_id: uuid.UUID = Field(serialization_alias = "speechId", alias = "speechId")
333
+ turn_generation_id: int = Field(serialization_alias = "turnGenerationId", alias = "turnGenerationId")
334
+ speech_generation_id: int = Field(serialization_alias = "speechGenerationId", alias = "speechGenerationId")
335
+ terminal_status: AssistantSpeechTerminalStatus = Field(serialization_alias = "terminalStatus", alias = "terminalStatus")
336
+ delivery_extent: AssistantSpeechDeliveryExtent = Field(serialization_alias = "deliveryExtent", alias = "deliveryExtent")
337
+ generated_text: str = Field(serialization_alias = "generatedText", alias = "generatedText")
338
+ delivered_text: str | None = Field(serialization_alias = "deliveredText", alias = "deliveredText", default = None)
339
+ estimated_played_duration_ms: int | None = Field(serialization_alias = "estimatedPlayedDurationMs", alias = "estimatedPlayedDurationMs", default = None)
340
+ evidence_quality: AssistantSpeechEvidenceQuality = Field(serialization_alias = "evidenceQuality", alias = "evidenceQuality")
341
+ reason_code: AssistantSpeechTerminalReasonCode = Field(serialization_alias = "reasonCode", alias = "reasonCode")
342
+
343
+ class SessionEventMetadataAssistantIdleEventMetadata(BaseModel):
344
+ model_config = ConfigDict(populate_by_name = True)
345
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
346
+
347
+ class SessionEventMetadataUserDataInputEventMetadata(BaseModel):
348
+ model_config = ConfigDict(populate_by_name = True)
349
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
350
+ field_name: str | None = Field(serialization_alias = "fieldName", alias = "fieldName", default = None)
351
+ value: str | None = Field(serialization_alias = "value", alias = "value", default = None)
352
+
353
+ class SessionEventMetadataCreatedEventMetadata(BaseModel):
354
+ model_config = ConfigDict(populate_by_name = True)
355
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
356
+
357
+ class SessionEventMetadataStartedEventMetadata(BaseModel):
358
+ model_config = ConfigDict(populate_by_name = True)
359
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
360
+
361
+ class SessionEventMetadataCompleteEventMetadata(BaseModel):
362
+ model_config = ConfigDict(populate_by_name = True)
363
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
364
+
365
+ class SessionEventMetadataIncompleteEventMetadata(BaseModel):
366
+ model_config = ConfigDict(populate_by_name = True)
367
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
368
+ reason_code: SessionTerminalReasonCode | None = Field(serialization_alias = "reasonCode", alias = "reasonCode", default = None)
369
+
370
+ class SessionEventMetadataConnectedEventMetadata(BaseModel):
371
+ model_config = ConfigDict(populate_by_name = True)
372
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
373
+
374
+ class SessionEventMetadataDisconnectedEventMetadata(BaseModel):
375
+ model_config = ConfigDict(populate_by_name = True)
376
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
377
+
378
+ class SessionEventMetadataEmptyEventMetadata(BaseModel):
379
+ model_config = ConfigDict(populate_by_name = True)
380
+ type: str | None = Field(serialization_alias = "$type", alias = "$type", default = None)
381
+
382
+ SessionEventMetadata = SessionEventMetadataFlowNodeTransitionEventMetadata | SessionEventMetadataFlowNodeWaitEventMetadata | SessionEventMetadataAssistantSpeakEventMetadata | SessionEventMetadataAssistantSpeechTerminalEventMetadata | SessionEventMetadataAssistantIdleEventMetadata | SessionEventMetadataUserDataInputEventMetadata | SessionEventMetadataCreatedEventMetadata | SessionEventMetadataStartedEventMetadata | SessionEventMetadataCompleteEventMetadata | SessionEventMetadataIncompleteEventMetadata | SessionEventMetadataConnectedEventMetadata | SessionEventMetadataDisconnectedEventMetadata | SessionEventMetadataEmptyEventMetadata
383
+
384
+ class IpInfo(BaseModel):
385
+ model_config = ConfigDict(populate_by_name = True)
386
+ ip: str = Field(serialization_alias = "ip", alias = "ip")
387
+ country: Country | None = Field(serialization_alias = "country", alias = "country", default = None)
388
+ region: str | None = Field(serialization_alias = "region", alias = "region", default = None)
389
+ region_name: str | None = Field(serialization_alias = "regionName", alias = "regionName", default = None)
390
+ city: City | None = Field(serialization_alias = "city", alias = "city", default = None)
391
+ postal_code: str | None = Field(serialization_alias = "postalCode", alias = "postalCode", default = None)
392
+ latitude: float | None = Field(serialization_alias = "latitude", alias = "latitude", default = None)
393
+ longitude: float | None = Field(serialization_alias = "longitude", alias = "longitude", default = None)
394
+ timezone: str | None = Field(serialization_alias = "timezone", alias = "timezone", default = None)
395
+ organization: str | None = Field(serialization_alias = "organization", alias = "organization", default = None)
396
+
397
+ class PostAvatarImageResponse(BaseModel):
398
+ model_config = ConfigDict(populate_by_name = True)
399
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
400
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
401
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
402
+ data: CreatedAvatar | None = Field(serialization_alias = "data", alias = "data", default = None)
403
+
404
+ class FaceFeatures(BaseModel):
405
+ model_config = ConfigDict(populate_by_name = True)
406
+ age_range: AgeRangeFaceFeature = Field(serialization_alias = "ageRange", alias = "ageRange")
407
+ gender: GenderFaceFeature = Field(serialization_alias = "gender", alias = "gender")
408
+
409
+ class FlowNodeConversationFlowNode(BaseModel):
410
+ """Communicate with the user using an AI-powered conversational turn. Instruct the assistant to say or ask the user something and route the flow based on the user's response.
411
+
412
+ Use `answers` to categorize the user answer, then use the answer to route the flow through `outcomes`
413
+ Ommiting `answers` and using the `any` key in outcomes skips waiting for a user answer
414
+
415
+ You can also collect data using the `collect` key.
416
+ Example:
417
+ {
418
+ "type": "conversation",
419
+ "generation": {
420
+ "template": "Hi, let's get you started"
421
+ },
422
+ "outcome": "next_node"
423
+ }
424
+
425
+ """
426
+ model_config = ConfigDict(populate_by_name = True)
427
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
428
+ generation: TurnGenerationOptions = Field(serialization_alias = "generation", alias = "generation")
429
+ timeout_generation: TurnGenerationOptions | None = Field(serialization_alias = "timeout_generation", alias = "timeout_generation", default = None)
430
+ # How many seconds the Assistant will wait until it nudges the user
431
+ timeout_seconds: int | None = Field(serialization_alias = "timeout_seconds", alias = "timeout_seconds", default = None)
432
+ # Key-value pairs of answers and their matching next node. Keys must match one of the keys in "answers", or be "any"
433
+ outcomes: dict[str, ConversationOutcome] | None = Field(serialization_alias = "outcomes", alias = "outcomes", default = None)
434
+ # Set this proeprty to end the conversation after the assistant speech, without waiting for a user reply
435
+ outcome: str | None = Field(serialization_alias = "outcome", alias = "outcome", default = None)
436
+ timeout_outcome: str | None = Field(serialization_alias = "timeout_outcome", alias = "timeout_outcome", default = None)
437
+
438
+ class FlowNodeEmail2faFlowNode(BaseModel):
439
+ """Send a verification code by email. The assistant will ask the user to read the code out loud and verify that the it matches.
440
+ Example:
441
+ {
442
+ "type": "two_factor_email",
443
+ "code_length": 6,
444
+ "max_retries": 3,
445
+ "subject": "Your Verification Code",
446
+ "outcomes": {
447
+ "verified": "success",
448
+ "unverified": "fail",
449
+ "delivery_failed": "fail",
450
+ "cancelled": "fail"
451
+ }
452
+ }
453
+
454
+ """
455
+ model_config = ConfigDict(populate_by_name = True)
456
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
457
+ outcomes: VerificationCodeOutcomes = Field(serialization_alias = "outcomes", alias = "outcomes")
458
+ generation: TurnGenerationOptions | None = Field(serialization_alias = "generation", alias = "generation", default = None)
459
+ # How many digits in the code that will be sent. Default to 6
460
+ code_length: int | None = Field(serialization_alias = "code_length", alias = "code_length", default = None)
461
+ # Once the number of tries reaches this number, the outcome of the node will be 'unverified'
462
+ max_retries: int | None = Field(serialization_alias = "max_retries", alias = "max_retries", default = None)
463
+ # Subject line for the sent email
464
+ subject: str | None = Field(serialization_alias = "subject", alias = "subject", default = None)
465
+
466
+ class FlowNodeSms2faFlowNode(BaseModel):
467
+ model_config = ConfigDict(populate_by_name = True)
468
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
469
+
470
+ class FlowNodeOnScreenCodeFlowNode(BaseModel):
471
+ """Example:
472
+ {
473
+ "type": "on_screen_code",
474
+ "code_length": 6,
475
+ "max_retries": 3,
476
+ "outcomes": {
477
+ "verified": "success",
478
+ "unverified": "fail",
479
+ "delivery_failed": "fail",
480
+ "cancelled": "fail"
481
+ }
482
+ }
483
+
484
+
485
+ """
486
+ model_config = ConfigDict(populate_by_name = True)
487
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
488
+ outcomes: VerificationCodeOutcomes = Field(serialization_alias = "outcomes", alias = "outcomes")
489
+ generation: TurnGenerationOptions | None = Field(serialization_alias = "generation", alias = "generation", default = None)
490
+ # How many digits in the code that will be sent. Default to 6
491
+ code_length: int | None = Field(serialization_alias = "code_length", alias = "code_length", default = None)
492
+ # Once the number of tries reaches this number, the outcome of the node will be 'unverified'
493
+ max_retries: int | None = Field(serialization_alias = "max_retries", alias = "max_retries", default = None)
494
+
495
+ class FlowNodeCustomCodeFlowNode(BaseModel):
496
+ """Example:
497
+ {
498
+ "type": "custom_code",
499
+ "code_source": "props.code",
500
+ "max_retries": 3,
501
+ "outcomes": {
502
+ "verified": "success",
503
+ "unverified": "fail",
504
+ "delivery_failed": "fail",
505
+ "cancelled": "fail"
506
+ }
507
+ }
508
+
509
+
510
+ """
511
+ model_config = ConfigDict(populate_by_name = True)
512
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
513
+ outcomes: VerificationCodeOutcomes = Field(serialization_alias = "outcomes", alias = "outcomes")
514
+ sent_generation: TurnGenerationOptions = Field(serialization_alias = "sent_generation", alias = "sent_generation")
515
+ retry_generation: TurnGenerationOptions | None = Field(serialization_alias = "retry_generation", alias = "retry_generation", default = None)
516
+ code_not_ready_generation: TurnGenerationOptions | None = Field(serialization_alias = "code_not_ready_generation", alias = "code_not_ready_generation", default = None)
517
+ # Where you provide the code. Usually 'props', set at session creation or updated after the session starts. e.g. "props.code"
518
+ code_source: str = Field(serialization_alias = "code_source", alias = "code_source")
519
+ # Once the number of tries reaches this number, the outcome of the node will be 'unverified'
520
+ max_retries: int | None = Field(serialization_alias = "max_retries", alias = "max_retries", default = None)
521
+
522
+ class FlowNodeLivenessFlowNode(BaseModel):
523
+ """Example:
524
+ {
525
+ "type": "liveness",
526
+ "outcomes": {
527
+ "authentic": "success",
528
+ "synthetic": "fail",
529
+ "no_face": "fail"
530
+ }
531
+ }
532
+
533
+
534
+ """
535
+ model_config = ConfigDict(populate_by_name = True)
536
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
537
+ outcomes: LivenessOutcomes = Field(serialization_alias = "outcomes", alias = "outcomes")
538
+ # Score threshold for the liveness assessment. Route to the authentic outcome if equal or above the threshold, route to the synthetic outcome if under
539
+ threshold: float | None = Field(serialization_alias = "threshold", alias = "threshold", default = None)
540
+ # Minimum number of frames that need to be analyzed before making a determination. If this node is reached before the minimum number of frames was analyzed, the user will be prompted to wait while the analysis completes. See wait_generation to configure the generated Assistant message.
541
+ min_frames_analyzed: int | None = Field(serialization_alias = "min_frames_analyzed", alias = "min_frames_analyzed", default = None)
542
+ wait_generation: TurnGenerationOptions | None = Field(serialization_alias = "wait_generation", alias = "wait_generation", default = None)
543
+
544
+ class FlowNodeFaceRecognitionFlowNode(BaseModel):
545
+ """Find a known identity using facial recognition.
546
+
547
+ This will find candidates identities in the database based on the faces analyzed during the session so far.
548
+ From there you can do 2 things:
549
+ - Confirm the candidate is correct by asking the user
550
+ - Save the candidate identity id
551
+
552
+ When using the confirmation turn, you can customize the question the assistant ask using the TurnGenerationOptions as `confirmation_generation`. This lets you configure the assistant instruction to generate the conversation turn, or directly provide text.
553
+ If you do not provide text in the language the session expects, the assistant will translate from the languages you did provide.
554
+ You can use variable substitution in the text. The candidate identity information will be made available under `candidate_identity`
555
+
556
+ The assistant will analyze the user response and categorize it into `agreed`, `disagreed` and `other`. Make sure the turn text you provide or generate prompts the user to reply in a way that fits those categories.
557
+ Example:
558
+ {
559
+ "recognition": {
560
+ "type": "face_recognition",
561
+ "outcomes": {
562
+ "match": "foo",
563
+ "no_match": "bar",
564
+ "no_face": "baz"
565
+ }
566
+ }
567
+ }
568
+
569
+ """
570
+ model_config = ConfigDict(populate_by_name = True)
571
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
572
+ outcomes: FaceRecognitionOutcomes = Field(serialization_alias = "outcomes", alias = "outcomes")
573
+ # Minimum similarity score required for an identity to match a face
574
+ threshold: float | None = Field(serialization_alias = "threshold", alias = "threshold", default = None)
575
+ confirmation_generation: TurnGenerationOptions | None = Field(serialization_alias = "confirmation_generation", alias = "confirmation_generation", default = None)
576
+ # Where to save the candidate identity. If provided, the Assistant will not confirm the user identity
577
+ save_as: str | None = Field(serialization_alias = "save_as", alias = "save_as", default = None)
578
+
579
+ class FlowNodeCollectUserDataFlowNode(BaseModel):
580
+ """Example:
581
+ {
582
+ "type": "collect_user_data",
583
+ "label": "Email",
584
+ "input_type": "email",
585
+ "save_as": "identity.email",
586
+ "outcome": "closing"
587
+ }
588
+
589
+ """
590
+ model_config = ConfigDict(populate_by_name = True)
591
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
592
+ # Label displayed in the form UI
593
+ label: str = Field(serialization_alias = "label", alias = "label")
594
+ # Type used for form UI input. Possible values are: email, number, tel, text
595
+ input_type: str = Field(serialization_alias = "input_type", alias = "input_type")
596
+ # Where to save the collected data
597
+ save_as: str = Field(serialization_alias = "save_as", alias = "save_as")
598
+ # Which node to go to after the user provided the requested data
599
+ outcome: str = Field(serialization_alias = "outcome", alias = "outcome")
600
+
601
+ class FlowNodeExpressionFlowNode(BaseModel):
602
+ """Example:
603
+ {
604
+ "type": "expression",
605
+ "expression": "state.collected_amount == props.transfer_amount",
606
+ "outcomes": {
607
+ "true": "success",
608
+ "false": "failure"
609
+ }
610
+ }
611
+
612
+ """
613
+ model_config = ConfigDict(populate_by_name = True)
614
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
615
+ outcomes: ExpressionOutcomes = Field(serialization_alias = "outcomes", alias = "outcomes")
616
+ # JavaScript expression. Native JavaScript functions like `parseInt` and toLowerCase are available.
617
+ expression: str = Field(serialization_alias = "expression", alias = "expression")
618
+
619
+ class FlowNodeStartFlowNode(BaseModel):
620
+ """Entry point of the Verification flow. Exactly one instance of this node must be present and it must provide an `outcome` that points to the key of a node in the flow
621
+ Example:
622
+ {
623
+ "start": {
624
+ "type": "start",
625
+ "outcome": "my_first_node"
626
+ }
627
+ }
628
+
629
+ """
630
+ model_config = ConfigDict(populate_by_name = True)
631
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
632
+ # First node of the flow
633
+ outcome: str = Field(serialization_alias = "outcome", alias = "outcome")
634
+
635
+ class FlowNodeEndFlowNode(BaseModel):
636
+ """Exit node of the flow. Exactly one instance of this node must be present. Use the key of the node route other nodes to the end of the flow"""
637
+ model_config = ConfigDict(populate_by_name = True)
638
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
639
+
640
+ FlowNode = FlowNodeConversationFlowNode | FlowNodeEmail2faFlowNode | FlowNodeSms2faFlowNode | FlowNodeOnScreenCodeFlowNode | FlowNodeCustomCodeFlowNode | FlowNodeLivenessFlowNode | FlowNodeFaceRecognitionFlowNode | FlowNodeCollectUserDataFlowNode | FlowNodeExpressionFlowNode | FlowNodeStartFlowNode | FlowNodeEndFlowNode
641
+
642
+ class FrameAnalysisBase(BaseModel):
643
+ model_config = ConfigDict(populate_by_name = True)
644
+ score: float = Field(serialization_alias = "score", alias = "score")
645
+ confidence: float = Field(serialization_alias = "confidence", alias = "confidence")
646
+ created_at: str = Field(serialization_alias = "created_at", alias = "created_at")
647
+ version: str = Field(serialization_alias = "version", alias = "version")
648
+ duration_ms: int = Field(serialization_alias = "duration_ms", alias = "duration_ms")
649
+
650
+ class FrameAnalysisFaceIntelFrameAnalysis(BaseModel):
651
+ model_config = ConfigDict(populate_by_name = True)
652
+ type: str = Field(serialization_alias = "$type", alias = "$type")
653
+ ela_score: float = Field(serialization_alias = "ela_score", alias = "ela_score")
654
+ source_score: float = Field(serialization_alias = "source_score", alias = "source_score")
655
+ score: float = Field(serialization_alias = "score", alias = "score")
656
+ confidence: float = Field(serialization_alias = "confidence", alias = "confidence")
657
+ created_at: str = Field(serialization_alias = "created_at", alias = "created_at")
658
+ version: str = Field(serialization_alias = "version", alias = "version")
659
+ duration_ms: int = Field(serialization_alias = "duration_ms", alias = "duration_ms")
660
+
661
+ class FrameAnalysisLlmFrameAnalysis(BaseModel):
662
+ model_config = ConfigDict(populate_by_name = True)
663
+ type: str = Field(serialization_alias = "$type", alias = "$type")
664
+ short_description: str = Field(serialization_alias = "short_description", alias = "short_description")
665
+ long_description: str = Field(serialization_alias = "long_description", alias = "long_description")
666
+ model_key: str = Field(serialization_alias = "model_key", alias = "model_key")
667
+ usage: UsageDetails = Field(serialization_alias = "usage", alias = "usage")
668
+ score: float = Field(serialization_alias = "score", alias = "score")
669
+ confidence: float = Field(serialization_alias = "confidence", alias = "confidence")
670
+ created_at: str = Field(serialization_alias = "created_at", alias = "created_at")
671
+ version: str = Field(serialization_alias = "version", alias = "version")
672
+ duration_ms: int = Field(serialization_alias = "duration_ms", alias = "duration_ms")
673
+
674
+ FrameAnalysis = FrameAnalysisFaceIntelFrameAnalysis | FrameAnalysisLlmFrameAnalysis
675
+
676
+ class IdentityContact(BaseModel):
677
+ model_config = ConfigDict(populate_by_name = True)
678
+ type: IdentityContactType = Field(serialization_alias = "type", alias = "type")
679
+ value: str = Field(serialization_alias = "value", alias = "value")
680
+
681
+ class ListApiKeyResponse(BaseModel):
682
+ model_config = ConfigDict(populate_by_name = True)
683
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
684
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
685
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
686
+ data: list[ApiKey] | None = Field(serialization_alias = "data", alias = "data", default = None)
687
+ pagination: PaginationInfo | None = Field(serialization_alias = "pagination", alias = "pagination", default = None)
688
+
689
+ class ListAvatarsResponse(BaseModel):
690
+ model_config = ConfigDict(populate_by_name = True)
691
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
692
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
693
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
694
+ data: list[Avatar] | None = Field(serialization_alias = "data", alias = "data", default = None)
695
+ pagination: PaginationInfo | None = Field(serialization_alias = "pagination", alias = "pagination", default = None)
696
+
697
+ class ListUsersResponse(BaseModel):
698
+ model_config = ConfigDict(populate_by_name = True)
699
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
700
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
701
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
702
+ data: list[User] | None = Field(serialization_alias = "data", alias = "data", default = None)
703
+ pagination: PaginationInfo | None = Field(serialization_alias = "pagination", alias = "pagination", default = None)
704
+
705
+ class LivenessAnalysisSummary(BaseModel):
706
+ model_config = ConfigDict(populate_by_name = True)
707
+ frame_count: int = Field(serialization_alias = "frame_count", alias = "frame_count")
708
+ score: float = Field(serialization_alias = "score", alias = "score")
709
+ score_without_outliers: float = Field(serialization_alias = "score_without_outliers", alias = "score_without_outliers")
710
+ providers: list[LivenessProvider] = Field(serialization_alias = "providers", alias = "providers")
711
+
712
+ class SessionFlow(BaseModel):
713
+ model_config = ConfigDict(populate_by_name = True)
714
+ avatar: SessionFlowAvatar | None = Field(serialization_alias = "avatar", alias = "avatar", default = None)
715
+ voice: SessionFlowVoice | None = Field(serialization_alias = "voice", alias = "voice", default = None)
716
+ # List of filler words for the assistant to say to acknowledge the user's sentences. Grouped by language. For each time the user says something, the assistant will pick a random word from the list for the language of the user and speak it When left empty, the assistant doesn't use filler words. Empty by default
717
+ filler_words: dict[str, list[str]] | None = Field(serialization_alias = "filler_words", alias = "filler_words", default = None)
718
+ nodes: dict[str, FlowNode] | None = Field(serialization_alias = "nodes", alias = "nodes", default = None)
719
+ # Use this to expose any data that the verification flow may need during the session. This will be exposed to any node supporting variable substitution under `props` Nested objects are supported.
720
+ props: dict[str, object | None] | None = Field(serialization_alias = "props", alias = "props", default = None)
721
+ extract: dict[str, ExtractionDefinition] | None = Field(serialization_alias = "extract", alias = "extract", default = None)
722
+
723
+ class Utterance(BaseModel):
724
+ model_config = ConfigDict(populate_by_name = True)
725
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
726
+ session_id: uuid.UUID = Field(serialization_alias = "sessionId", alias = "sessionId")
727
+ role: ParticipantRole = Field(serialization_alias = "role", alias = "role")
728
+ start_offset_ms: int = Field(serialization_alias = "startOffsetMs", alias = "startOffsetMs")
729
+ end_offset_ms: int = Field(serialization_alias = "endOffsetMs", alias = "endOffsetMs")
730
+ transcript: str = Field(serialization_alias = "transcript", alias = "transcript")
731
+ created_at: str | None = Field(serialization_alias = "createdAt", alias = "createdAt", default = None)
732
+ words: list[UtteranceWord] | None = Field(serialization_alias = "words", alias = "words", default = None)
733
+
734
+ class VideoMetadata(BaseModel):
735
+ model_config = ConfigDict(populate_by_name = True)
736
+ frame_count: int | None = Field(serialization_alias = "frameCount", alias = "frameCount", default = None)
737
+ duration_us: int | None = Field(serialization_alias = "durationUs", alias = "durationUs", default = None)
738
+ frame_rate: int | None = Field(serialization_alias = "frameRate", alias = "frameRate", default = None)
739
+ container: VideoContainer | None = Field(serialization_alias = "container", alias = "container", default = None)
740
+ video_codec: VideoCodec | None = Field(serialization_alias = "videoCodec", alias = "videoCodec", default = None)
741
+ audio_codec: AudioCodec | None = Field(serialization_alias = "audioCodec", alias = "audioCodec", default = None)
742
+
743
+ class UpdateAvatarRequest(BaseModel):
744
+ model_config = ConfigDict(populate_by_name = True)
745
+ name: str | None = Field(serialization_alias = "name", alias = "name", default = None)
746
+ config: AvatarConfigEntity | None = Field(serialization_alias = "config", alias = "config", default = None)
747
+
748
+ class StartSessionResponse(BaseModel):
749
+ model_config = ConfigDict(populate_by_name = True)
750
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
751
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
752
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
753
+ data: BrowserSessionBootstrap | None = Field(serialization_alias = "data", alias = "data", default = None)
754
+
755
+ class IVerificationMessageShowUiVerificationMessage(BaseModel):
756
+ model_config = ConfigDict(populate_by_name = True)
757
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
758
+ transaction_id: uuid.UUID = Field(serialization_alias = "transaction_id", alias = "transaction_id")
759
+ input_type: str = Field(serialization_alias = "input_type", alias = "input_type")
760
+ label: str = Field(serialization_alias = "label", alias = "label")
761
+
762
+ class IVerificationMessageUserCollectedDataVerificationMessage(BaseModel):
763
+ model_config = ConfigDict(populate_by_name = True)
764
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
765
+ transaction_id: uuid.UUID = Field(serialization_alias = "transaction_id", alias = "transaction_id")
766
+ value: str = Field(serialization_alias = "value", alias = "value")
767
+
768
+ class IVerificationMessageUserSimulatedUtteranceVerificationMessage(BaseModel):
769
+ model_config = ConfigDict(populate_by_name = True)
770
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
771
+ transcript: str = Field(serialization_alias = "transcript", alias = "transcript")
772
+
773
+ class IVerificationMessageAvatarPlaybackReadyVerificationMessage(BaseModel):
774
+ model_config = ConfigDict(populate_by_name = True)
775
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
776
+
777
+ class IVerificationMessageUserCancelledVerificationMessage(BaseModel):
778
+ model_config = ConfigDict(populate_by_name = True)
779
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
780
+
781
+ class IVerificationMessageShowCodeVerificationMessage(BaseModel):
782
+ model_config = ConfigDict(populate_by_name = True)
783
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
784
+ transaction_id: uuid.UUID = Field(serialization_alias = "transaction_id", alias = "transaction_id")
785
+ code: str = Field(serialization_alias = "code", alias = "code")
786
+
787
+ class IVerificationMessageHideCodeVerificationMessage(BaseModel):
788
+ model_config = ConfigDict(populate_by_name = True)
789
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
790
+ transaction_id: uuid.UUID = Field(serialization_alias = "transaction_id", alias = "transaction_id")
791
+
792
+ class IVerificationMessageSessionEndedVerificationMessage(BaseModel):
793
+ model_config = ConfigDict(populate_by_name = True)
794
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
795
+ redirect_to: str | None = Field(serialization_alias = "redirect_to", alias = "redirect_to", default = None)
796
+
797
+ class IVerificationMessageUserUtteranceInterimVerificationMessage(BaseModel):
798
+ model_config = ConfigDict(populate_by_name = True)
799
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
800
+ transcript: str = Field(serialization_alias = "transcript", alias = "transcript")
801
+
802
+ class IVerificationMessageUserUtteranceVerificationMessage(BaseModel):
803
+ model_config = ConfigDict(populate_by_name = True)
804
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
805
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
806
+ transcript: str = Field(serialization_alias = "transcript", alias = "transcript")
807
+
808
+ class IVerificationMessageConversationTranscriptVerificationMessage(BaseModel):
809
+ model_config = ConfigDict(populate_by_name = True)
810
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
811
+ entries: list[ConversationTranscriptEntry] = Field(serialization_alias = "entries", alias = "entries")
812
+
813
+ class IVerificationMessageAssistantSpeechStateVerificationMessage(BaseModel):
814
+ model_config = ConfigDict(populate_by_name = True)
815
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
816
+ speech_id: uuid.UUID = Field(serialization_alias = "speech_id", alias = "speech_id")
817
+ turn_generation_id: int = Field(serialization_alias = "turn_generation_id", alias = "turn_generation_id")
818
+ speech_generation_id: int = Field(serialization_alias = "speech_generation_id", alias = "speech_generation_id")
819
+ revision: int = Field(serialization_alias = "revision", alias = "revision")
820
+ status: AssistantSpeechRealtimeStatus = Field(serialization_alias = "status", alias = "status")
821
+ generated_text: str = Field(serialization_alias = "generated_text", alias = "generated_text")
822
+ delivered_text: str | None = Field(serialization_alias = "delivered_text", alias = "delivered_text", default = None)
823
+ delivery_extent: AssistantSpeechDeliveryExtent = Field(serialization_alias = "delivery_extent", alias = "delivery_extent")
824
+ start_offset_ms: int | None = Field(serialization_alias = "start_offset_ms", alias = "start_offset_ms", default = None)
825
+ end_offset_ms: int | None = Field(serialization_alias = "end_offset_ms", alias = "end_offset_ms", default = None)
826
+ estimated_played_duration_ms: int | None = Field(serialization_alias = "estimated_played_duration_ms", alias = "estimated_played_duration_ms", default = None)
827
+
828
+ class IVerificationMessageConversationSnapshotAvailableVerificationMessage(BaseModel):
829
+ model_config = ConfigDict(populate_by_name = True)
830
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
831
+ version: int = Field(serialization_alias = "version", alias = "version")
832
+
833
+ class IVerificationMessageConversationSnapshotRequestVerificationMessage(BaseModel):
834
+ model_config = ConfigDict(populate_by_name = True)
835
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
836
+ version: int = Field(serialization_alias = "version", alias = "version")
837
+ client_instance_id: uuid.UUID = Field(serialization_alias = "client_instance_id", alias = "client_instance_id")
838
+ request_id: int = Field(serialization_alias = "request_id", alias = "request_id")
839
+
840
+ class IVerificationMessageConversationSnapshotVerificationMessage(BaseModel):
841
+ model_config = ConfigDict(populate_by_name = True)
842
+ type: str | None = Field(serialization_alias = "type", alias = "type", default = None)
843
+ version: int = Field(serialization_alias = "version", alias = "version")
844
+ client_instance_id: uuid.UUID = Field(serialization_alias = "client_instance_id", alias = "client_instance_id")
845
+ request_id: int = Field(serialization_alias = "request_id", alias = "request_id")
846
+ mode: ConversationRealtimeMode = Field(serialization_alias = "mode", alias = "mode")
847
+ active_turn_generation_id: int | None = Field(serialization_alias = "active_turn_generation_id", alias = "active_turn_generation_id", default = None)
848
+ active_speech_id: uuid.UUID | None = Field(serialization_alias = "active_speech_id", alias = "active_speech_id", default = None)
849
+ active_speech_generation_id: int | None = Field(serialization_alias = "active_speech_generation_id", alias = "active_speech_generation_id", default = None)
850
+ transcript: list[ConversationTranscriptEntry] = Field(serialization_alias = "transcript", alias = "transcript")
851
+ assistant_speech: AssistantSpeechStateVerificationMessage | None = Field(serialization_alias = "assistant_speech", alias = "assistant_speech", default = None)
852
+ session_terminal: ConversationSessionTerminalState | None = Field(serialization_alias = "session_terminal", alias = "session_terminal", default = None)
853
+
854
+ IVerificationMessage = IVerificationMessageShowUiVerificationMessage | IVerificationMessageUserCollectedDataVerificationMessage | IVerificationMessageUserSimulatedUtteranceVerificationMessage | IVerificationMessageAvatarPlaybackReadyVerificationMessage | IVerificationMessageUserCancelledVerificationMessage | IVerificationMessageShowCodeVerificationMessage | IVerificationMessageHideCodeVerificationMessage | IVerificationMessageSessionEndedVerificationMessage | IVerificationMessageUserUtteranceInterimVerificationMessage | IVerificationMessageUserUtteranceVerificationMessage | IVerificationMessageConversationTranscriptVerificationMessage | IVerificationMessageAssistantSpeechStateVerificationMessage | IVerificationMessageConversationSnapshotAvailableVerificationMessage | IVerificationMessageConversationSnapshotRequestVerificationMessage | IVerificationMessageConversationSnapshotVerificationMessage
855
+
856
+ class SessionEvent(BaseModel):
857
+ model_config = ConfigDict(populate_by_name = True)
858
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
859
+ event_type: SessionEventType = Field(serialization_alias = "eventType", alias = "eventType")
860
+ created_at: str = Field(serialization_alias = "createdAt", alias = "createdAt")
861
+ metadata: SessionEventMetadata = Field(serialization_alias = "metadata", alias = "metadata")
862
+
863
+ class Face(BaseModel):
864
+ model_config = ConfigDict(populate_by_name = True)
865
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
866
+ bounding_box: BoundingBox = Field(serialization_alias = "boundingBox", alias = "boundingBox")
867
+ confidence: float = Field(serialization_alias = "confidence", alias = "confidence")
868
+ identity_id: uuid.UUID | None = Field(serialization_alias = "identityId", alias = "identityId", default = None)
869
+ features: FaceFeatures | None = Field(serialization_alias = "features", alias = "features", default = None)
870
+
871
+ class Identity(BaseModel):
872
+ model_config = ConfigDict(populate_by_name = True)
873
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
874
+ preferred_name: str | None = Field(serialization_alias = "preferredName", alias = "preferredName", default = None)
875
+ first_name: str | None = Field(serialization_alias = "firstName", alias = "firstName", default = None)
876
+ last_name: str | None = Field(serialization_alias = "lastName", alias = "lastName", default = None)
877
+ contacts: list[IdentityContact] = Field(serialization_alias = "contacts", alias = "contacts")
878
+
879
+ class AnalysisSummary(BaseModel):
880
+ model_config = ConfigDict(populate_by_name = True)
881
+ liveness: LivenessAnalysisSummary | None = Field(serialization_alias = "liveness", alias = "liveness", default = None)
882
+
883
+ class CreateSessionRequest(BaseModel):
884
+ model_config = ConfigDict(populate_by_name = True)
885
+ # example: en-US
886
+ lang: str | None = Field(serialization_alias = "lang", alias = "lang", default = None)
887
+ flow: SessionFlow = Field(serialization_alias = "flow", alias = "flow")
888
+ saml_session_id: uuid.UUID | None = Field(serialization_alias = "samlSessionId", alias = "samlSessionId", default = None)
889
+
890
+ class ListSessionUtterancesResponse(BaseModel):
891
+ model_config = ConfigDict(populate_by_name = True)
892
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
893
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
894
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
895
+ data: list[Utterance] | None = Field(serialization_alias = "data", alias = "data", default = None)
896
+ pagination: PaginationInfo | None = Field(serialization_alias = "pagination", alias = "pagination", default = None)
897
+
898
+ class Video(BaseModel):
899
+ model_config = ConfigDict(populate_by_name = True)
900
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
901
+ created_at: str = Field(serialization_alias = "createdAt", alias = "createdAt")
902
+ started_at: str | None = Field(serialization_alias = "startedAt", alias = "startedAt", default = None)
903
+ metadata: VideoMetadata | None = Field(serialization_alias = "metadata", alias = "metadata", default = None)
904
+ url: str | None = Field(serialization_alias = "url", alias = "url", default = None)
905
+
906
+ class FrameWithFaces(BaseModel):
907
+ model_config = ConfigDict(populate_by_name = True)
908
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
909
+ analysis: list[FrameAnalysis] | None = Field(serialization_alias = "analysis", alias = "analysis", default = None)
910
+ timestamp: str = Field(serialization_alias = "timestamp", alias = "timestamp")
911
+ created_at: str = Field(serialization_alias = "createdAt", alias = "createdAt")
912
+ index: int = Field(serialization_alias = "index", alias = "index")
913
+ url: str | None = Field(serialization_alias = "url", alias = "url", default = None)
914
+ faces: list[Face] = Field(serialization_alias = "faces", alias = "faces")
915
+
916
+ class Session(BaseModel):
917
+ model_config = ConfigDict(populate_by_name = True)
918
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
919
+ created_at: str = Field(serialization_alias = "createdAt", alias = "createdAt")
920
+ started_at: str | None = Field(serialization_alias = "startedAt", alias = "startedAt", default = None)
921
+ finished_at: str | None = Field(serialization_alias = "finishedAt", alias = "finishedAt", default = None)
922
+ status: SessionStatus = Field(serialization_alias = "status", alias = "status")
923
+ room_name: str = Field(serialization_alias = "roomName", alias = "roomName")
924
+ user_identity: str = Field(serialization_alias = "userIdentity", alias = "userIdentity")
925
+ ws_url: str = Field(serialization_alias = "wsUrl", alias = "wsUrl")
926
+ session_duration_seconds: int | None = Field(serialization_alias = "sessionDurationSeconds", alias = "sessionDurationSeconds", default = None)
927
+ identity: Identity | None = Field(serialization_alias = "identity", alias = "identity", default = None)
928
+ ip: str | None = Field(serialization_alias = "ip", alias = "ip", default = None)
929
+ ip_info: IpInfo | None = Field(serialization_alias = "ipInfo", alias = "ipInfo", default = None)
930
+ analysis_summary: AnalysisSummary | None = Field(serialization_alias = "analysisSummary", alias = "analysisSummary", default = None)
931
+
932
+ class SessionDetail(BaseModel):
933
+ model_config = ConfigDict(populate_by_name = True)
934
+ id: uuid.UUID = Field(serialization_alias = "id", alias = "id")
935
+ created_at: str = Field(serialization_alias = "createdAt", alias = "createdAt")
936
+ started_at: str | None = Field(serialization_alias = "startedAt", alias = "startedAt", default = None)
937
+ finished_at: str | None = Field(serialization_alias = "finishedAt", alias = "finishedAt", default = None)
938
+ status: SessionStatus = Field(serialization_alias = "status", alias = "status")
939
+ lang: str = Field(serialization_alias = "lang", alias = "lang")
940
+ session_duration_seconds: int = Field(serialization_alias = "sessionDurationSeconds", alias = "sessionDurationSeconds")
941
+ user_duration_seconds: int = Field(serialization_alias = "userDurationSeconds", alias = "userDurationSeconds")
942
+ assistant_duration_seconds: int = Field(serialization_alias = "assistantDurationSeconds", alias = "assistantDurationSeconds")
943
+ flow: SessionFlow = Field(serialization_alias = "flow", alias = "flow")
944
+ events: list[SessionEvent] = Field(serialization_alias = "events", alias = "events")
945
+ frames: list[FrameWithFaces] = Field(serialization_alias = "frames", alias = "frames")
946
+ user_video: Video = Field(serialization_alias = "userVideo", alias = "userVideo")
947
+ avatar_video: Video = Field(serialization_alias = "avatarVideo", alias = "avatarVideo")
948
+ identity: Identity | None = Field(serialization_alias = "identity", alias = "identity", default = None)
949
+ ip: str | None = Field(serialization_alias = "ip", alias = "ip", default = None)
950
+ ip_info: IpInfo | None = Field(serialization_alias = "ipInfo", alias = "ipInfo", default = None)
951
+ flow_output: dict[str, dict[str, object]] | None = Field(serialization_alias = "flowOutput", alias = "flowOutput", default = None)
952
+ analysis_summary: AnalysisSummary | None = Field(serialization_alias = "analysisSummary", alias = "analysisSummary", default = None)
953
+
954
+ class CreatedSession(BaseModel):
955
+ model_config = ConfigDict(populate_by_name = True)
956
+ start_session_url: str = Field(serialization_alias = "startSessionUrl", alias = "startSessionUrl")
957
+ session: Session = Field(serialization_alias = "session", alias = "session")
958
+
959
+ class GetSessionResponse(BaseModel):
960
+ model_config = ConfigDict(populate_by_name = True)
961
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
962
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
963
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
964
+ data: Session | None = Field(serialization_alias = "data", alias = "data", default = None)
965
+
966
+ class GetSessionDetailResponse(BaseModel):
967
+ model_config = ConfigDict(populate_by_name = True)
968
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
969
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
970
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
971
+ data: SessionDetail | None = Field(serialization_alias = "data", alias = "data", default = None)
972
+
973
+ class CreateSessionResponse(BaseModel):
974
+ model_config = ConfigDict(populate_by_name = True)
975
+ is_success: bool | None = Field(serialization_alias = "isSuccess", alias = "isSuccess", default = None)
976
+ message: str | None = Field(serialization_alias = "message", alias = "message", default = None)
977
+ errors: list[ErrorInfo] | None = Field(serialization_alias = "errors", alias = "errors", default = None)
978
+ data: CreatedSession | None = Field(serialization_alias = "data", alias = "data", default = None)
979
+
980
+ class ClientCredentials(BaseModel):
981
+ api_key: str | None = None
982
+ single_use_token: str | None = None
983
+
984
+
985
+ class ClientOptions(BaseModel):
986
+ client: Any | None = None
987
+ headers: dict[str, str] | None = None
988
+ base_url: str | None = None
989
+ creds: ClientCredentials | None = None
990
+
991
+ @dataclass
992
+ class ClientResponse[TRes, TErr]:
993
+ status_code: int
994
+ response_body: str | None = None
995
+ error: TErr | None = None
996
+ data: TRes | None = None
997
+
998
+ class Client:
999
+ def __init__(self, options: ClientOptions):
1000
+ self.client = options.client or httpx.AsyncClient()
1001
+ self.options = options
1002
+ self.base_url = (options.base_url or "https://api-dev.facesign.ai/").rstrip('/')
1003
+
1004
+ async def get_user_api_keys(self, user_id: str) -> ClientResponse[ListApiKeyResponse, ErrorResponse]:
1005
+ creds = self.options.creds
1006
+ if creds is None or not creds.api_key:
1007
+ raise Exception("Missing security api_key")
1008
+
1009
+ response = await self.client.get(f"{self.base_url}/users/{urllib.parse.quote(str(user_id), safe="")}/api-keys", headers={
1010
+ "X-API-KEY": creds.api_key,
1011
+
1012
+ } | (self.options.headers or {}))
1013
+ if response.status_code == 200:
1014
+ try:
1015
+ data = ListApiKeyResponse.model_validate_json(response.text)
1016
+ return ClientResponse(data=data, status_code=200)
1017
+
1018
+ except Exception:
1019
+ return ClientResponse(response_body=response.text, status_code=200)
1020
+
1021
+
1022
+ if response.status_code == 500:
1023
+ try:
1024
+ data = ErrorResponse.model_validate_json(response.text)
1025
+ return ClientResponse(error=data, status_code=500)
1026
+
1027
+ except Exception:
1028
+ return ClientResponse(response_body=response.text, status_code=500)
1029
+
1030
+
1031
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1032
+
1033
+ async def create_user_api_key(self, user_id: str, body: CreateUserApiKeyRequest) -> ClientResponse[CreateApiKeyResponse, ErrorResponse]:
1034
+ creds = self.options.creds
1035
+ if creds is None or not creds.api_key:
1036
+ raise Exception("Missing security api_key")
1037
+
1038
+ response = await self.client.post(f"{self.base_url}/users/{urllib.parse.quote(str(user_id), safe="")}/api-keys", json=body.model_dump(), headers={
1039
+ "X-API-KEY": creds.api_key,
1040
+
1041
+ } | (self.options.headers or {}))
1042
+ if response.status_code == 201:
1043
+ try:
1044
+ data = CreateApiKeyResponse.model_validate_json(response.text)
1045
+ return ClientResponse(data=data, status_code=201)
1046
+
1047
+ except Exception:
1048
+ return ClientResponse(response_body=response.text, status_code=201)
1049
+
1050
+
1051
+ if response.status_code == 500:
1052
+ try:
1053
+ data = ErrorResponse.model_validate_json(response.text)
1054
+ return ClientResponse(error=data, status_code=500)
1055
+
1056
+ except Exception:
1057
+ return ClientResponse(response_body=response.text, status_code=500)
1058
+
1059
+
1060
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1061
+
1062
+ async def revoke_user_api_key(self, id: str, user_id: str) -> ClientResponse[None, ErrorResponse]:
1063
+ creds = self.options.creds
1064
+ if creds is None or not creds.api_key:
1065
+ raise Exception("Missing security api_key")
1066
+
1067
+ response = await self.client.delete(f"{self.base_url}/users/{urllib.parse.quote(str(user_id), safe="")}/api-keys/{urllib.parse.quote(str(id), safe="")}", headers={
1068
+ "X-API-KEY": creds.api_key,
1069
+
1070
+ } | (self.options.headers or {}))
1071
+ if response.status_code == 204:
1072
+ return ClientResponse(status_code=response.status_code)
1073
+
1074
+ if response.status_code == 404:
1075
+ try:
1076
+ data = ErrorResponse.model_validate_json(response.text)
1077
+ return ClientResponse(error=data, status_code=404)
1078
+
1079
+ except Exception:
1080
+ return ClientResponse(response_body=response.text, status_code=404)
1081
+
1082
+
1083
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1084
+
1085
+ async def list_avatars(self) -> ClientResponse[ListAvatarsResponse, ErrorResponse]:
1086
+ creds = self.options.creds
1087
+ if creds is None or not creds.api_key:
1088
+ raise Exception("Missing security api_key")
1089
+
1090
+ response = await self.client.get(f"{self.base_url}/avatars", headers={
1091
+ "X-API-KEY": creds.api_key,
1092
+
1093
+ } | (self.options.headers or {}))
1094
+ if response.status_code == 200:
1095
+ try:
1096
+ data = ListAvatarsResponse.model_validate_json(response.text)
1097
+ return ClientResponse(data=data, status_code=200)
1098
+
1099
+ except Exception:
1100
+ return ClientResponse(response_body=response.text, status_code=200)
1101
+
1102
+
1103
+ if response.status_code == 500:
1104
+ try:
1105
+ data = ErrorResponse.model_validate_json(response.text)
1106
+ return ClientResponse(error=data, status_code=500)
1107
+
1108
+ except Exception:
1109
+ return ClientResponse(response_body=response.text, status_code=500)
1110
+
1111
+
1112
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1113
+
1114
+ async def create_avatar(self, body: PostAvatarImageRequest) -> ClientResponse[PostAvatarImageResponse, ErrorResponse]:
1115
+ creds = self.options.creds
1116
+ if creds is None or not creds.api_key:
1117
+ raise Exception("Missing security api_key")
1118
+
1119
+ response = await self.client.post(f"{self.base_url}/avatars", json=body.model_dump(), headers={
1120
+ "X-API-KEY": creds.api_key,
1121
+
1122
+ } | (self.options.headers or {}))
1123
+ if response.status_code == 201:
1124
+ try:
1125
+ data = PostAvatarImageResponse.model_validate_json(response.text)
1126
+ return ClientResponse(data=data, status_code=201)
1127
+
1128
+ except Exception:
1129
+ return ClientResponse(response_body=response.text, status_code=201)
1130
+
1131
+
1132
+ if response.status_code == 400:
1133
+ try:
1134
+ data = ErrorResponse.model_validate_json(response.text)
1135
+ return ClientResponse(error=data, status_code=400)
1136
+
1137
+ except Exception:
1138
+ return ClientResponse(response_body=response.text, status_code=400)
1139
+
1140
+
1141
+ if response.status_code == 500:
1142
+ try:
1143
+ data = ErrorResponse.model_validate_json(response.text)
1144
+ return ClientResponse(error=data, status_code=500)
1145
+
1146
+ except Exception:
1147
+ return ClientResponse(response_body=response.text, status_code=500)
1148
+
1149
+
1150
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1151
+
1152
+ async def get_avatar(self, id: uuid.UUID) -> ClientResponse[AvatarResponse, ErrorResponse]:
1153
+ creds = self.options.creds
1154
+ if creds is None or not creds.api_key:
1155
+ raise Exception("Missing security api_key")
1156
+
1157
+ response = await self.client.get(f"{self.base_url}/avatars/{urllib.parse.quote(str(id), safe="")}", headers={
1158
+ "X-API-KEY": creds.api_key,
1159
+
1160
+ } | (self.options.headers or {}))
1161
+ if response.status_code == 200:
1162
+ try:
1163
+ data = AvatarResponse.model_validate_json(response.text)
1164
+ return ClientResponse(data=data, status_code=200)
1165
+
1166
+ except Exception:
1167
+ return ClientResponse(response_body=response.text, status_code=200)
1168
+
1169
+
1170
+ if response.status_code == 404:
1171
+ try:
1172
+ data = ErrorResponse.model_validate_json(response.text)
1173
+ return ClientResponse(error=data, status_code=404)
1174
+
1175
+ except Exception:
1176
+ return ClientResponse(response_body=response.text, status_code=404)
1177
+
1178
+
1179
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1180
+
1181
+ async def update_avatar(self, id: uuid.UUID, body: UpdateAvatarRequest) -> ClientResponse[AvatarResponse, ErrorResponse]:
1182
+ creds = self.options.creds
1183
+ if creds is None or not creds.api_key:
1184
+ raise Exception("Missing security api_key")
1185
+
1186
+ response = await self.client.patch(f"{self.base_url}/avatars/{urllib.parse.quote(str(id), safe="")}", json=body.model_dump(), headers={
1187
+ "X-API-KEY": creds.api_key,
1188
+
1189
+ } | (self.options.headers or {}))
1190
+ if response.status_code == 200:
1191
+ try:
1192
+ data = AvatarResponse.model_validate_json(response.text)
1193
+ return ClientResponse(data=data, status_code=200)
1194
+
1195
+ except Exception:
1196
+ return ClientResponse(response_body=response.text, status_code=200)
1197
+
1198
+
1199
+ if response.status_code == 404:
1200
+ try:
1201
+ data = ErrorResponse.model_validate_json(response.text)
1202
+ return ClientResponse(error=data, status_code=404)
1203
+
1204
+ except Exception:
1205
+ return ClientResponse(response_body=response.text, status_code=404)
1206
+
1207
+
1208
+ if response.status_code == 500:
1209
+ try:
1210
+ data = ErrorResponse.model_validate_json(response.text)
1211
+ return ClientResponse(error=data, status_code=500)
1212
+
1213
+ except Exception:
1214
+ return ClientResponse(response_body=response.text, status_code=500)
1215
+
1216
+
1217
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1218
+
1219
+ async def delete_avatar(self, id: uuid.UUID) -> ClientResponse[None, ErrorResponse]:
1220
+ creds = self.options.creds
1221
+ if creds is None or not creds.api_key:
1222
+ raise Exception("Missing security api_key")
1223
+
1224
+ response = await self.client.delete(f"{self.base_url}/avatars/{urllib.parse.quote(str(id), safe="")}", headers={
1225
+ "X-API-KEY": creds.api_key,
1226
+
1227
+ } | (self.options.headers or {}))
1228
+ if response.status_code == 204:
1229
+ return ClientResponse(status_code=response.status_code)
1230
+
1231
+ if response.status_code == 404:
1232
+ try:
1233
+ data = ErrorResponse.model_validate_json(response.text)
1234
+ return ClientResponse(error=data, status_code=404)
1235
+
1236
+ except Exception:
1237
+ return ClientResponse(response_body=response.text, status_code=404)
1238
+
1239
+
1240
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1241
+
1242
+ async def get_demo_report(self, session_id: uuid.UUID) -> ClientResponse[GetDemoReportResponse, ErrorResponse]:
1243
+ creds = self.options.creds
1244
+ if creds is None or not creds.api_key:
1245
+ raise Exception("Missing security api_key")
1246
+
1247
+ response = await self.client.get(f"{self.base_url}/sessions/{urllib.parse.quote(str(session_id), safe="")}/demo_report", headers={
1248
+ "X-API-KEY": creds.api_key,
1249
+
1250
+ } | (self.options.headers or {}))
1251
+ if response.status_code == 200:
1252
+ try:
1253
+ data = GetDemoReportResponse.model_validate_json(response.text)
1254
+ return ClientResponse(data=data, status_code=200)
1255
+
1256
+ except Exception:
1257
+ return ClientResponse(response_body=response.text, status_code=200)
1258
+
1259
+
1260
+ if response.status_code == 500:
1261
+ try:
1262
+ data = ErrorResponse.model_validate_json(response.text)
1263
+ return ClientResponse(error=data, status_code=500)
1264
+
1265
+ except Exception:
1266
+ return ClientResponse(response_body=response.text, status_code=500)
1267
+
1268
+
1269
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1270
+
1271
+ async def create_session(self, body: CreateSessionRequest) -> ClientResponse[CreateSessionResponse, ErrorResponse]:
1272
+ creds = self.options.creds
1273
+ if creds is None or not creds.api_key:
1274
+ raise Exception("Missing security api_key")
1275
+
1276
+ response = await self.client.post(f"{self.base_url}/sessions", json=body.model_dump(), headers={
1277
+ "X-API-KEY": creds.api_key,
1278
+
1279
+ } | (self.options.headers or {}))
1280
+ if response.status_code == 200:
1281
+ try:
1282
+ data = CreateSessionResponse.model_validate_json(response.text)
1283
+ return ClientResponse(data=data, status_code=200)
1284
+
1285
+ except Exception:
1286
+ return ClientResponse(response_body=response.text, status_code=200)
1287
+
1288
+
1289
+ if response.status_code == 500:
1290
+ try:
1291
+ data = ErrorResponse.model_validate_json(response.text)
1292
+ return ClientResponse(error=data, status_code=500)
1293
+
1294
+ except Exception:
1295
+ return ClientResponse(response_body=response.text, status_code=500)
1296
+
1297
+
1298
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1299
+
1300
+ async def start_session(self) -> ClientResponse[StartSessionResponse, BrowserSessionErrorResponse]:
1301
+ creds = self.options.creds
1302
+ if creds is None or not creds.single_use_token:
1303
+ raise Exception("Missing security single_use_token")
1304
+
1305
+ response = await self.client.post(f"{self.base_url}/sessions/attempts", headers={
1306
+ "Authorization": f"Bearer {creds.single_use_token}",
1307
+
1308
+ } | (self.options.headers or {}))
1309
+ if response.status_code == 200:
1310
+ try:
1311
+ data = StartSessionResponse.model_validate_json(response.text)
1312
+ return ClientResponse(data=data, status_code=200)
1313
+
1314
+ except Exception:
1315
+ return ClientResponse(response_body=response.text, status_code=200)
1316
+
1317
+
1318
+ if response.status_code == 404:
1319
+ try:
1320
+ data = BrowserSessionErrorResponse.model_validate_json(response.text)
1321
+ return ClientResponse(error=data, status_code=404)
1322
+
1323
+ except Exception:
1324
+ return ClientResponse(response_body=response.text, status_code=404)
1325
+
1326
+
1327
+ if response.status_code == 500:
1328
+ try:
1329
+ data = BrowserSessionErrorResponse.model_validate_json(response.text)
1330
+ return ClientResponse(error=data, status_code=500)
1331
+
1332
+ except Exception:
1333
+ return ClientResponse(response_body=response.text, status_code=500)
1334
+
1335
+
1336
+ if response.status_code == 503:
1337
+ try:
1338
+ data = BrowserSessionErrorResponse.model_validate_json(response.text)
1339
+ return ClientResponse(error=data, status_code=503)
1340
+
1341
+ except Exception:
1342
+ return ClientResponse(response_body=response.text, status_code=503)
1343
+
1344
+
1345
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1346
+
1347
+ async def create_session_prop(self, id: uuid.UUID, body: CreateSessionPropRequest) -> ClientResponse[None, ErrorResponse]:
1348
+ creds = self.options.creds
1349
+ if creds is None or not creds.api_key:
1350
+ raise Exception("Missing security api_key")
1351
+
1352
+ response = await self.client.post(f"{self.base_url}/sessions/{urllib.parse.quote(str(id), safe="")}/props", json=body.model_dump(), headers={
1353
+ "X-API-KEY": creds.api_key,
1354
+
1355
+ } | (self.options.headers or {}))
1356
+ if response.status_code == 201:
1357
+ return ClientResponse(status_code=response.status_code)
1358
+
1359
+ if response.status_code == 500:
1360
+ try:
1361
+ data = ErrorResponse.model_validate_json(response.text)
1362
+ return ClientResponse(error=data, status_code=500)
1363
+
1364
+ except Exception:
1365
+ return ClientResponse(response_body=response.text, status_code=500)
1366
+
1367
+
1368
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1369
+
1370
+ async def get_session(self, id: uuid.UUID) -> ClientResponse[GetSessionResponse, ErrorResponse]:
1371
+ creds = self.options.creds
1372
+ if creds is None or not creds.api_key:
1373
+ raise Exception("Missing security api_key")
1374
+
1375
+ response = await self.client.get(f"{self.base_url}/sessions/{urllib.parse.quote(str(id), safe="")}", headers={
1376
+ "X-API-KEY": creds.api_key,
1377
+
1378
+ } | (self.options.headers or {}))
1379
+ if response.status_code == 200:
1380
+ try:
1381
+ data = GetSessionResponse.model_validate_json(response.text)
1382
+ return ClientResponse(data=data, status_code=200)
1383
+
1384
+ except Exception:
1385
+ return ClientResponse(response_body=response.text, status_code=200)
1386
+
1387
+
1388
+ if response.status_code == 404:
1389
+ try:
1390
+ data = ErrorResponse.model_validate_json(response.text)
1391
+ return ClientResponse(error=data, status_code=404)
1392
+
1393
+ except Exception:
1394
+ return ClientResponse(response_body=response.text, status_code=404)
1395
+
1396
+
1397
+ if response.status_code == 500:
1398
+ try:
1399
+ data = ErrorResponse.model_validate_json(response.text)
1400
+ return ClientResponse(error=data, status_code=500)
1401
+
1402
+ except Exception:
1403
+ return ClientResponse(response_body=response.text, status_code=500)
1404
+
1405
+
1406
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1407
+
1408
+ async def get_session_detail(self, session_id: uuid.UUID) -> ClientResponse[GetSessionDetailResponse, ErrorResponse]:
1409
+ creds = self.options.creds
1410
+ if creds is None or not creds.api_key:
1411
+ raise Exception("Missing security api_key")
1412
+
1413
+ response = await self.client.get(f"{self.base_url}/sessions/{urllib.parse.quote(str(session_id), safe="")}/details", headers={
1414
+ "X-API-KEY": creds.api_key,
1415
+
1416
+ } | (self.options.headers or {}))
1417
+ if response.status_code == 200:
1418
+ try:
1419
+ data = GetSessionDetailResponse.model_validate_json(response.text)
1420
+ return ClientResponse(data=data, status_code=200)
1421
+
1422
+ except Exception:
1423
+ return ClientResponse(response_body=response.text, status_code=200)
1424
+
1425
+
1426
+ if response.status_code == 404:
1427
+ try:
1428
+ data = ErrorResponse.model_validate_json(response.text)
1429
+ return ClientResponse(error=data, status_code=404)
1430
+
1431
+ except Exception:
1432
+ return ClientResponse(response_body=response.text, status_code=404)
1433
+
1434
+
1435
+ if response.status_code == 500:
1436
+ try:
1437
+ data = ErrorResponse.model_validate_json(response.text)
1438
+ return ClientResponse(error=data, status_code=500)
1439
+
1440
+ except Exception:
1441
+ return ClientResponse(response_body=response.text, status_code=500)
1442
+
1443
+
1444
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1445
+
1446
+ async def list_session_utterances(self, session_id: uuid.UUID) -> ClientResponse[ListSessionUtterancesResponse, ErrorResponse]:
1447
+ creds = self.options.creds
1448
+ if creds is None or not creds.api_key:
1449
+ raise Exception("Missing security api_key")
1450
+
1451
+ response = await self.client.get(f"{self.base_url}/sessions/{urllib.parse.quote(str(session_id), safe="")}/utterances", headers={
1452
+ "X-API-KEY": creds.api_key,
1453
+
1454
+ } | (self.options.headers or {}))
1455
+ if response.status_code == 200:
1456
+ try:
1457
+ data = ListSessionUtterancesResponse.model_validate_json(response.text)
1458
+ return ClientResponse(data=data, status_code=200)
1459
+
1460
+ except Exception:
1461
+ return ClientResponse(response_body=response.text, status_code=200)
1462
+
1463
+
1464
+ if response.status_code == 500:
1465
+ try:
1466
+ data = ErrorResponse.model_validate_json(response.text)
1467
+ return ClientResponse(error=data, status_code=500)
1468
+
1469
+ except Exception:
1470
+ return ClientResponse(response_body=response.text, status_code=500)
1471
+
1472
+
1473
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1474
+
1475
+ async def list_users(self) -> ClientResponse[ListUsersResponse, ErrorResponse]:
1476
+ creds = self.options.creds
1477
+ if creds is None or not creds.api_key:
1478
+ raise Exception("Missing security api_key")
1479
+
1480
+ response = await self.client.get(f"{self.base_url}/users", headers={
1481
+ "X-API-KEY": creds.api_key,
1482
+
1483
+ } | (self.options.headers or {}))
1484
+ if response.status_code == 200:
1485
+ try:
1486
+ data = ListUsersResponse.model_validate_json(response.text)
1487
+ return ClientResponse(data=data, status_code=200)
1488
+
1489
+ except Exception:
1490
+ return ClientResponse(response_body=response.text, status_code=200)
1491
+
1492
+
1493
+ if response.status_code == 500:
1494
+ try:
1495
+ data = ErrorResponse.model_validate_json(response.text)
1496
+ return ClientResponse(error=data, status_code=500)
1497
+
1498
+ except Exception:
1499
+ return ClientResponse(response_body=response.text, status_code=500)
1500
+
1501
+
1502
+ return ClientResponse(status_code=response.status_code, response_body=response.text)
1503
+
1504
+