fireflies-api 0.5.0

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/action-items-CC9yUxHY.d.cts +380 -0
  4. package/dist/action-items-CC9yUxHY.d.ts +380 -0
  5. package/dist/cli/index.cjs +3909 -0
  6. package/dist/cli/index.cjs.map +1 -0
  7. package/dist/cli/index.d.cts +2 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/index.js +3906 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/index.cjs +3389 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.cts +966 -0
  14. package/dist/index.d.ts +966 -0
  15. package/dist/index.js +3344 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/middleware/express.cjs +2491 -0
  18. package/dist/middleware/express.cjs.map +1 -0
  19. package/dist/middleware/express.d.cts +36 -0
  20. package/dist/middleware/express.d.ts +36 -0
  21. package/dist/middleware/express.js +2489 -0
  22. package/dist/middleware/express.js.map +1 -0
  23. package/dist/middleware/fastify.cjs +2501 -0
  24. package/dist/middleware/fastify.cjs.map +1 -0
  25. package/dist/middleware/fastify.d.cts +66 -0
  26. package/dist/middleware/fastify.d.ts +66 -0
  27. package/dist/middleware/fastify.js +2498 -0
  28. package/dist/middleware/fastify.js.map +1 -0
  29. package/dist/middleware/hono.cjs +2493 -0
  30. package/dist/middleware/hono.cjs.map +1 -0
  31. package/dist/middleware/hono.d.cts +37 -0
  32. package/dist/middleware/hono.d.ts +37 -0
  33. package/dist/middleware/hono.js +2490 -0
  34. package/dist/middleware/hono.js.map +1 -0
  35. package/dist/schemas/index.cjs +307 -0
  36. package/dist/schemas/index.cjs.map +1 -0
  37. package/dist/schemas/index.d.cts +926 -0
  38. package/dist/schemas/index.d.ts +926 -0
  39. package/dist/schemas/index.js +268 -0
  40. package/dist/schemas/index.js.map +1 -0
  41. package/dist/speaker-analytics-Dr46LKyP.d.ts +275 -0
  42. package/dist/speaker-analytics-l45LXqO1.d.cts +275 -0
  43. package/dist/types-BX-3JcRI.d.cts +41 -0
  44. package/dist/types-C_XxdRd1.d.cts +1546 -0
  45. package/dist/types-CaHcwnKw.d.ts +41 -0
  46. package/dist/types-DIPZmUl3.d.ts +1546 -0
  47. package/package.json +126 -0
@@ -0,0 +1,966 @@
1
+ import { T as TranscriptionChunk, A as ActionItemsFilterOptions, a as AggregatedActionItemsResult, b as ActionItemsMarkdownOptions, M as MeetingInsightsOptions, c as MeetingInsights, d as TranscriptsListParams, S as SearchTranscriptOptions, e as SearchMatch, F as FirefliesClient, W as WebhookPayload, P as ParseOptions, V as VerifyOptions } from './types-DIPZmUl3.js';
2
+ export { f as AIApp, g as AIAppsAPI, h as AIAppsListParams, i as ActionItemGrouping, j as ActionItemPreset, k as ActionItemStyle, l as ActiveMeeting, m as ActiveMeetingsParams, n as AddBotParams, o as AggregatedActionItem, p as AudioAPI, B as Bite, q as BiteCaption, r as BiteCreatedFrom, s as BiteSource, t as BiteUser, u as BitesAPI, v as BitesListParams, C as CreateBiteParams, D as DayOfWeekStats, w as DayStats, E as ExportActionItemsParams, x as FirefliesConfig, y as MeetingPrivacy, z as MeetingState, G as MeetingsAPI, H as ParticipantStats, R as RateLimitConfig, I as RateLimitState, J as RealtimeAPI, K as RealtimeConfig, L as RealtimeEvents, N as RealtimeStream, O as RetryConfig, Q as SearchParams, U as SearchResults, X as SpeakerInsightStats, Y as ThrottleConfig, Z as TimeGroupStats, _ as TranscriptGetParams, $ as TranscriptsAPI, a0 as TranscriptsInsightsParams, a1 as TranscriptsMutationsAPI, a2 as TranscriptsQueryScope, a3 as UploadAudioAttendee, a4 as UploadAudioParams, a5 as UserGroup, a6 as UserGroupMember, a7 as UserProfile, a8 as UserRole, a9 as UsersAPI, aa as UsersMutationsAPI, ab as WebhookEventType } from './types-DIPZmUl3.js';
3
+ import { T as Transcript, a as ActionItemOptions, b as ActionItem, A as ActionItemsResult } from './action-items-CC9yUxHY.js';
4
+ export { c as AIAppOutput, d as AIFilter, e as AppsPreview, C as Channel, f as ChannelMember, M as MeetingAnalytics, g as MeetingAttendance, h as MeetingAttendee, i as MeetingInfo, j as Sentence, k as Sentiments, S as Speaker, l as Summary, m as SummarySection, n as SummaryStatus, U as User, o as extractActionItems } from './action-items-CC9yUxHY.js';
5
+ import { a as NormalizationOptions, N as NormalizedMeeting } from './speaker-analytics-Dr46LKyP.js';
6
+ export { b as NormalizedAnalytics, c as NormalizedAttendee, d as NormalizedChannel, e as NormalizedParticipant, f as NormalizedSentence, g as NormalizedSpeaker, h as NormalizedSummary, S as SpeakerAnalytics, i as SpeakerAnalyticsOptions, j as SpeakerStats, k as analyzeSpeakers } from './speaker-analytics-Dr46LKyP.js';
7
+
8
+ /**
9
+ * Base error class for all Fireflies API errors.
10
+ * All errors include a code for programmatic handling.
11
+ */
12
+ declare class FirefliesError extends Error {
13
+ readonly code: string;
14
+ readonly status?: number;
15
+ constructor(message: string, options?: {
16
+ status?: number;
17
+ cause?: unknown;
18
+ });
19
+ }
20
+ /**
21
+ * Thrown when the API key is invalid or missing.
22
+ */
23
+ declare class AuthenticationError extends FirefliesError {
24
+ readonly code = "AUTHENTICATION_ERROR";
25
+ constructor(message?: string);
26
+ }
27
+ /**
28
+ * Thrown when rate limits are exceeded.
29
+ * Check retryAfter for suggested wait time in milliseconds.
30
+ */
31
+ declare class RateLimitError extends FirefliesError {
32
+ readonly code = "RATE_LIMIT_ERROR";
33
+ /** Suggested wait time in milliseconds before retrying. */
34
+ readonly retryAfter?: number;
35
+ constructor(message?: string, retryAfter?: number);
36
+ }
37
+ /**
38
+ * Thrown when a requested resource is not found.
39
+ */
40
+ declare class NotFoundError extends FirefliesError {
41
+ readonly code = "NOT_FOUND";
42
+ constructor(message?: string);
43
+ }
44
+ /**
45
+ * Thrown when request validation fails.
46
+ */
47
+ declare class ValidationError extends FirefliesError {
48
+ readonly code = "VALIDATION_ERROR";
49
+ constructor(message: string);
50
+ }
51
+ /**
52
+ * Thrown when the GraphQL API returns errors.
53
+ */
54
+ declare class GraphQLError extends FirefliesError {
55
+ readonly code = "GRAPHQL_ERROR";
56
+ readonly errors: GraphQLErrorDetail[];
57
+ constructor(message: string, errors: GraphQLErrorDetail[]);
58
+ }
59
+ /**
60
+ * Detail from a GraphQL error response.
61
+ */
62
+ interface GraphQLErrorDetail {
63
+ message: string;
64
+ path?: string[];
65
+ extensions?: Record<string, unknown>;
66
+ }
67
+ /**
68
+ * Thrown when a request times out.
69
+ */
70
+ declare class TimeoutError extends FirefliesError {
71
+ readonly code = "TIMEOUT_ERROR";
72
+ constructor(message?: string);
73
+ }
74
+ /**
75
+ * Thrown when a network error occurs.
76
+ */
77
+ declare class NetworkError extends FirefliesError {
78
+ readonly code = "NETWORK_ERROR";
79
+ constructor(message: string, cause?: unknown);
80
+ }
81
+ /**
82
+ * Base error for realtime operations.
83
+ */
84
+ declare class RealtimeError extends FirefliesError {
85
+ readonly code: string;
86
+ constructor(message: string, options?: {
87
+ cause?: unknown;
88
+ });
89
+ }
90
+ /**
91
+ * Thrown when realtime connection fails.
92
+ */
93
+ declare class ConnectionError extends RealtimeError {
94
+ readonly code = "CONNECTION_ERROR";
95
+ constructor(message?: string, options?: {
96
+ cause?: unknown;
97
+ });
98
+ }
99
+ /**
100
+ * Thrown when stream is accessed after close.
101
+ */
102
+ declare class StreamClosedError extends RealtimeError {
103
+ readonly code = "STREAM_CLOSED";
104
+ constructor(message?: string);
105
+ }
106
+ /**
107
+ * Thrown when webhook signature verification fails.
108
+ */
109
+ declare class WebhookVerificationError extends FirefliesError {
110
+ readonly code = "WEBHOOK_VERIFICATION_FAILED";
111
+ constructor(message: string);
112
+ }
113
+ /**
114
+ * Thrown when webhook payload parsing fails.
115
+ */
116
+ declare class WebhookParseError extends FirefliesError {
117
+ readonly code = "WEBHOOK_PARSE_FAILED";
118
+ constructor(message: string);
119
+ }
120
+ /**
121
+ * Thrown when no chunks received for configured timeout.
122
+ * Consumer should check if meeting is still active and decide whether to reconnect.
123
+ */
124
+ declare class ChunkTimeoutError extends RealtimeError {
125
+ readonly code = "CHUNK_TIMEOUT";
126
+ readonly timeoutMs: number;
127
+ constructor(timeoutMs: number);
128
+ }
129
+
130
+ /**
131
+ * A speaker turn containing one or more consecutive chunks from the same speaker.
132
+ */
133
+ interface SpeakerTurn {
134
+ /** Name of the speaker */
135
+ speaker: string;
136
+ /** Combined text from all chunks in this turn */
137
+ text: string;
138
+ /** Start time of the first chunk in seconds */
139
+ startTime: number;
140
+ /** End time of the last chunk in seconds */
141
+ endTime: number;
142
+ /** Original chunks that make up this turn */
143
+ chunks: TranscriptionChunk[];
144
+ }
145
+ /**
146
+ * The accumulated transcript state.
147
+ */
148
+ interface AccumulatedTranscript {
149
+ /** Speaker turns in chronological order */
150
+ turns: SpeakerTurn[];
151
+ /** Unique speaker names in order of first appearance */
152
+ speakers: string[];
153
+ /** Total word count across all turns */
154
+ wordCount: number;
155
+ /** Duration in seconds from first chunk start to last chunk end */
156
+ duration: number;
157
+ /** Total number of final chunks accumulated */
158
+ chunkCount: number;
159
+ }
160
+ /**
161
+ * Accumulates streaming transcription chunks into a coherent transcript.
162
+ *
163
+ * Chunks from the same speaker are merged into turns. Statistics like word count
164
+ * and duration are computed on demand.
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const accumulator = new TranscriptAccumulator();
169
+ *
170
+ * for await (const chunk of client.realtime.stream(meetingId)) {
171
+ * accumulator.add(chunk);
172
+ * const transcript = accumulator.getTranscript();
173
+ * console.log(`${transcript.speakers.length} speakers, ${transcript.wordCount} words`);
174
+ * }
175
+ *
176
+ * const final = accumulator.getTranscript();
177
+ * ```
178
+ */
179
+ declare class TranscriptAccumulator {
180
+ private turns;
181
+ private currentTurn;
182
+ private seenChunkIds;
183
+ /**
184
+ * Add a chunk to the accumulator.
185
+ *
186
+ * Only final chunks are accumulated; non-final chunks are ignored.
187
+ * Duplicate chunk IDs are also ignored.
188
+ *
189
+ * @param chunk - The transcription chunk to add
190
+ */
191
+ add(chunk: TranscriptionChunk): void;
192
+ /**
193
+ * Get the current accumulated transcript state.
194
+ *
195
+ * Statistics are computed on demand to ensure accuracy.
196
+ *
197
+ * @returns The accumulated transcript with turns, speakers, and statistics
198
+ */
199
+ getTranscript(): AccumulatedTranscript;
200
+ /**
201
+ * Clear all accumulated data.
202
+ *
203
+ * Useful for resetting the accumulator between sessions.
204
+ */
205
+ clear(): void;
206
+ private getUniqueSpeakers;
207
+ private computeWordCount;
208
+ private computeDuration;
209
+ }
210
+
211
+ /**
212
+ * Filter action items by criteria.
213
+ *
214
+ * Filters can be combined with AND logic - items must match all specified criteria.
215
+ *
216
+ * @param items - Action items to filter
217
+ * @param options - Filter criteria
218
+ * @returns Filtered items preserving original type and order
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Filter to Alice's items with due dates
223
+ * const filtered = filterActionItems(items, {
224
+ * assignees: ['Alice'],
225
+ * datedOnly: true,
226
+ * });
227
+ * ```
228
+ */
229
+ declare function filterActionItems<T extends ActionItem>(items: T[], options: ActionItemsFilterOptions): T[];
230
+ /**
231
+ * Aggregate action items from multiple transcripts.
232
+ *
233
+ * Extracts action items from each transcript and attaches source metadata
234
+ * (transcript ID, title, date) to each item.
235
+ *
236
+ * @param transcripts - Transcripts to extract action items from
237
+ * @param extractionOptions - Options for action item extraction
238
+ * @param filterOptions - Options to filter extracted items
239
+ * @returns Aggregated result with items and statistics
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const result = aggregateActionItems(transcripts);
244
+ * console.log(`${result.totalItems} items from ${result.transcriptsProcessed} meetings`);
245
+ * ```
246
+ */
247
+ declare function aggregateActionItems(transcripts: Transcript[], extractionOptions?: ActionItemOptions, filterOptions?: ActionItemsFilterOptions): AggregatedActionItemsResult;
248
+ /**
249
+ * Format action items as Markdown.
250
+ *
251
+ * Supports multiple styles (checkbox, bullet, numbered), grouping options,
252
+ * inline metadata, and presets for popular tools.
253
+ *
254
+ * @param result - Action items result (single or aggregated)
255
+ * @param options - Formatting options
256
+ * @returns Formatted markdown string
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * const markdown = formatActionItemsMarkdown(result, {
261
+ * style: 'checkbox',
262
+ * groupBy: 'assignee',
263
+ * includeSummary: true,
264
+ * preset: 'notion',
265
+ * });
266
+ * ```
267
+ */
268
+ declare function formatActionItemsMarkdown(result: ActionItemsResult | AggregatedActionItemsResult, options?: ActionItemsMarkdownOptions): string;
269
+
270
+ /**
271
+ * Options for batch processing.
272
+ */
273
+ interface BatchOptions {
274
+ /**
275
+ * Number of concurrent operations.
276
+ * Currently only sequential (1) is supported.
277
+ * @default 1
278
+ */
279
+ concurrency?: number;
280
+ /**
281
+ * Delay in milliseconds between operations.
282
+ * @default 100
283
+ */
284
+ delayMs?: number;
285
+ /**
286
+ * Whether to automatically handle rate limit errors.
287
+ * When true, waits for retryAfter and retries.
288
+ * @default true
289
+ */
290
+ handleRateLimit?: boolean;
291
+ /**
292
+ * Maximum number of rate limit retries per item.
293
+ * @default 3
294
+ */
295
+ maxRateLimitRetries?: number;
296
+ }
297
+ /**
298
+ * Result of a batch operation on a single item.
299
+ */
300
+ type BatchResult<T, R> = {
301
+ item: T;
302
+ result: R;
303
+ error?: never;
304
+ } | {
305
+ item: T;
306
+ result?: never;
307
+ error: Error;
308
+ };
309
+ /**
310
+ * Process items in batch with rate limiting and error handling.
311
+ *
312
+ * Yields results as they complete, allowing streaming processing.
313
+ * On rate limit errors, automatically waits and retries if handleRateLimit is true.
314
+ *
315
+ * @param items - Items to process (sync or async iterable)
316
+ * @param processor - Function to process each item
317
+ * @param options - Batch processing options
318
+ * @returns AsyncIterable yielding results (success or error) for each item
319
+ *
320
+ * @example
321
+ * ```typescript
322
+ * import { batch, FirefliesClient } from 'fireflies-api';
323
+ *
324
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
325
+ * const ids = ['id1', 'id2', 'id3'];
326
+ *
327
+ * for await (const result of batch(ids, id => client.transcripts.get(id))) {
328
+ * if (result.error) {
329
+ * console.error(`Failed to fetch ${result.item}: ${result.error.message}`);
330
+ * } else {
331
+ * console.log(`Got ${result.result.title}`);
332
+ * }
333
+ * }
334
+ * ```
335
+ */
336
+ declare function batch<T, R>(items: Iterable<T> | AsyncIterable<T>, processor: (item: T) => Promise<R>, options?: BatchOptions): AsyncIterable<BatchResult<T, R>>;
337
+ /**
338
+ * Process all items in batch and collect results.
339
+ *
340
+ * Unlike the streaming `batch()`, this waits for all items to complete
341
+ * and returns results as an array.
342
+ *
343
+ * @param items - Array of items to process
344
+ * @param processor - Function to process each item
345
+ * @param options - Batch processing options plus continueOnError
346
+ * @returns Array of successful results. When continueOnError is false, results
347
+ * match input order. When true, failed items are omitted (array may be shorter).
348
+ * @throws First error encountered if continueOnError is false (default)
349
+ *
350
+ * @example
351
+ * ```typescript
352
+ * import { batchAll, FirefliesClient } from 'fireflies-api';
353
+ *
354
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
355
+ * const ids = ['id1', 'id2', 'id3'];
356
+ *
357
+ * // Throws on first error
358
+ * const transcripts = await batchAll(ids, id => client.transcripts.get(id));
359
+ *
360
+ * // Continues on error, collects successful results
361
+ * const results = await batchAll(
362
+ * ids,
363
+ * id => client.transcripts.get(id),
364
+ * { continueOnError: true }
365
+ * );
366
+ * ```
367
+ */
368
+ declare function batchAll<T, R>(items: T[], processor: (item: T) => Promise<R>, options?: BatchOptions & {
369
+ continueOnError?: boolean;
370
+ }): Promise<R[]>;
371
+
372
+ /**
373
+ * Extract domain from email address.
374
+ *
375
+ * @param email - Email address
376
+ * @returns Lowercase domain, or empty string if invalid
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * extractDomain('user@company.com'); // 'company.com'
381
+ * extractDomain('User@EXAMPLE.ORG'); // 'example.org'
382
+ * extractDomain('invalid'); // ''
383
+ * ```
384
+ */
385
+ declare function extractDomain(email: string): string;
386
+ /**
387
+ * Check if any participant has an email outside the given domain.
388
+ *
389
+ * @param participants - List of participant email addresses
390
+ * @param internalDomain - The internal/company domain to check against
391
+ * @returns True if at least one participant has a different domain
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * hasExternalParticipants(['a@company.com', 'b@external.com'], 'company.com'); // true
396
+ * hasExternalParticipants(['a@company.com', 'b@company.com'], 'company.com'); // false
397
+ * ```
398
+ */
399
+ declare function hasExternalParticipants(participants: string[], internalDomain: string): boolean;
400
+
401
+ /**
402
+ * A question asked by an external participant.
403
+ */
404
+ interface ExternalQuestion {
405
+ /** The question text */
406
+ text: string;
407
+ /** Name of the speaker who asked the question */
408
+ speakerName: string;
409
+ /** Email of the speaker (if available from attendees) */
410
+ speakerEmail?: string;
411
+ /** Index of the sentence in the transcript */
412
+ sentenceIndex: number;
413
+ /** Start time as decimal seconds string */
414
+ startTime: string;
415
+ /** End time as decimal seconds string */
416
+ endTime: string;
417
+ }
418
+ /**
419
+ * Result of finding external participant questions.
420
+ */
421
+ interface ExternalQuestionsResult {
422
+ /** List of external participants identified */
423
+ externalParticipants: Array<{
424
+ name: string;
425
+ email?: string;
426
+ }>;
427
+ /** Questions asked by external participants */
428
+ questions: ExternalQuestion[];
429
+ /** Total count of questions */
430
+ totalQuestions: number;
431
+ }
432
+ /**
433
+ * Find questions asked by external participants in a transcript.
434
+ *
435
+ * This function analyzes a transcript to identify questions from participants
436
+ * whose email domains don't match the specified internal domains.
437
+ *
438
+ * @param transcript - The transcript to analyze
439
+ * @param internalDomains - Internal domain(s) to identify internal participants.
440
+ * Can be a single domain string (e.g., '@mycompany.com' or 'mycompany.com')
441
+ * or an array of domains.
442
+ * @returns Object containing external participants, their questions, and count
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * const transcript = await client.transcripts.get('id');
447
+ * const result = findExternalParticipantQuestions(transcript, '@mycompany.com');
448
+ *
449
+ * console.log(`Found ${result.totalQuestions} questions from external participants`);
450
+ * for (const q of result.questions) {
451
+ * console.log(`${q.speakerName}: ${q.text}`);
452
+ * }
453
+ * ```
454
+ */
455
+ declare function findExternalParticipantQuestions(transcript: Transcript, internalDomains: string | string[]): ExternalQuestionsResult;
456
+
457
+ /**
458
+ * Options for transcriptToMarkdown().
459
+ */
460
+ interface MarkdownExportOptions {
461
+ /** Include meeting metadata header (title, date, participants, duration). Default: true */
462
+ includeMetadata?: boolean;
463
+ /** Include AI-generated summary sections. Default: true */
464
+ includeSummary?: boolean;
465
+ /** Include action items section. Default: true */
466
+ includeActionItems?: boolean;
467
+ /** Format for action items: checkbox or plain list. Default: 'checkbox' */
468
+ actionItemFormat?: 'checkbox' | 'list';
469
+ /** Include timestamps for each sentence. Default: false */
470
+ includeTimestamps?: boolean;
471
+ /** How to format speaker names. Default: 'bold' */
472
+ speakerFormat?: 'bold' | 'plain';
473
+ /** Group consecutive sentences by same speaker. Default: true */
474
+ groupBySpeaker?: boolean;
475
+ /** Write output to file path (Node.js only). If set, also returns the string. */
476
+ outputPath?: string;
477
+ }
478
+ /**
479
+ * Options for chunksToMarkdown().
480
+ */
481
+ interface ChunksExportOptions {
482
+ /** Meeting title (chunks don't include metadata). Default: 'Live Transcript' */
483
+ title?: string;
484
+ /** Include timestamps for each chunk. Default: false */
485
+ includeTimestamps?: boolean;
486
+ /** How to format speaker names. Default: 'bold' */
487
+ speakerFormat?: 'bold' | 'plain';
488
+ /** Group consecutive chunks by same speaker. Default: true */
489
+ groupBySpeaker?: boolean;
490
+ /** Write output to file path (Node.js only). If set, also returns the string. */
491
+ outputPath?: string;
492
+ }
493
+ /**
494
+ * Convert a completed Fireflies transcript to well-formatted Markdown.
495
+ *
496
+ * @param transcript - The transcript to convert
497
+ * @param options - Formatting options
498
+ * @returns Markdown string representation of the transcript
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * import { FirefliesClient, transcriptToMarkdown } from 'fireflies-api';
503
+ *
504
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
505
+ * const transcript = await client.transcripts.get('transcript-id');
506
+ *
507
+ * // Basic usage
508
+ * const markdown = await transcriptToMarkdown(transcript);
509
+ *
510
+ * // With options
511
+ * const markdown = await transcriptToMarkdown(transcript, {
512
+ * includeTimestamps: true,
513
+ * actionItemFormat: 'list',
514
+ * });
515
+ *
516
+ * // Write to file
517
+ * const markdown = await transcriptToMarkdown(transcript, {
518
+ * outputPath: './meeting-notes.md',
519
+ * });
520
+ * ```
521
+ */
522
+ declare function transcriptToMarkdown(transcript: Transcript, options?: MarkdownExportOptions): Promise<string>;
523
+ /**
524
+ * Convert realtime transcription chunks to well-formatted Markdown.
525
+ *
526
+ * @param chunks - Array of transcription chunks from realtime stream
527
+ * @param options - Formatting options
528
+ * @returns Markdown string representation of the chunks
529
+ *
530
+ * @example
531
+ * ```typescript
532
+ * import { FirefliesClient, chunksToMarkdown } from 'fireflies-api';
533
+ *
534
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
535
+ *
536
+ * // Accumulate chunks from realtime stream
537
+ * const chunks: TranscriptionChunk[] = [];
538
+ * for await (const chunk of client.realtime.stream(meetingId)) {
539
+ * chunks.push(chunk);
540
+ * }
541
+ *
542
+ * // Convert to markdown
543
+ * const markdown = await chunksToMarkdown(chunks);
544
+ *
545
+ * // With options
546
+ * const markdown = await chunksToMarkdown(chunks, {
547
+ * title: 'Team Standup',
548
+ * includeTimestamps: true,
549
+ * });
550
+ * ```
551
+ */
552
+ declare function chunksToMarkdown(chunks: TranscriptionChunk[], options?: ChunksExportOptions): Promise<string>;
553
+
554
+ /**
555
+ * Analyze multiple transcripts to compute aggregate meeting statistics.
556
+ *
557
+ * Pure function - no API calls, fully testable. Computes duration totals,
558
+ * day of week distribution, participant counts, speaker talk times, and
559
+ * time-based groupings.
560
+ *
561
+ * @param transcripts - Array of transcripts to analyze
562
+ * @param options - Analysis options for filtering and grouping
563
+ * @returns Aggregate meeting insights
564
+ *
565
+ * @example
566
+ * ```typescript
567
+ * import { FirefliesClient, analyzeMeetings } from 'fireflies-api';
568
+ *
569
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
570
+ *
571
+ * // Fetch transcripts
572
+ * const transcripts: Transcript[] = [];
573
+ * for await (const t of client.transcripts.listAll({ mine: true })) {
574
+ * transcripts.push(t);
575
+ * }
576
+ *
577
+ * // Analyze
578
+ * const insights = analyzeMeetings(transcripts, {
579
+ * groupBy: 'week',
580
+ * topSpeakersCount: 5,
581
+ * });
582
+ *
583
+ * console.log(`${insights.totalMeetings} meetings, ${insights.totalDurationMinutes} minutes total`);
584
+ * console.log(`Average: ${insights.averageDurationMinutes} minutes`);
585
+ * ```
586
+ */
587
+ declare function analyzeMeetings(transcripts: Transcript[], options?: MeetingInsightsOptions): MeetingInsights;
588
+
589
+ /**
590
+ * Options for fetching transcripts from multiple users.
591
+ */
592
+ interface MultiUserOptions {
593
+ /**
594
+ * Whether to deduplicate transcripts by ID across accounts.
595
+ * Useful when multiple users have access to the same transcripts.
596
+ * @default true
597
+ */
598
+ deduplicate?: boolean;
599
+ /**
600
+ * Filter parameters to apply to each account's transcript listing.
601
+ * Pagination (skip/limit) is handled automatically.
602
+ */
603
+ filter?: Omit<TranscriptsListParams, 'skip' | 'limit'>;
604
+ /**
605
+ * Delay in milliseconds between yielded transcripts.
606
+ * Helps throttle processing and reduce memory pressure.
607
+ * Note: API rate limiting is handled by the underlying client.
608
+ * @default 100
609
+ */
610
+ delayMs?: number;
611
+ }
612
+ /**
613
+ * A transcript with source tracking information.
614
+ */
615
+ interface MultiUserTranscript {
616
+ /** The transcript object */
617
+ transcript: Transcript;
618
+ /** API key used to fetch this transcript (for attribution) */
619
+ sourceApiKey: string;
620
+ /** Index of the API key in the input array */
621
+ sourceIndex: number;
622
+ }
623
+ /**
624
+ * Fetch transcripts from multiple Fireflies accounts with deduplication.
625
+ *
626
+ * This function creates a client for each API key and iterates through
627
+ * all transcripts, optionally deduplicating across accounts.
628
+ *
629
+ * @param apiKeys - Array of Fireflies API keys
630
+ * @param options - Configuration options
631
+ * @returns AsyncIterable yielding transcripts with source tracking
632
+ *
633
+ * @example
634
+ * ```typescript
635
+ * import { getMeetingsForMultipleUsers } from 'fireflies-api';
636
+ *
637
+ * const apiKeys = [
638
+ * process.env.FIREFLIES_API_KEY_USER1!,
639
+ * process.env.FIREFLIES_API_KEY_USER2!,
640
+ * ];
641
+ *
642
+ * for await (const { transcript, sourceIndex } of getMeetingsForMultipleUsers(apiKeys)) {
643
+ * console.log(`[User ${sourceIndex}] ${transcript.title}`);
644
+ * }
645
+ *
646
+ * // With filtering
647
+ * for await (const item of getMeetingsForMultipleUsers(apiKeys, {
648
+ * filter: { fromDate: '2024-01-01' },
649
+ * deduplicate: true,
650
+ * })) {
651
+ * console.log(item.transcript.title);
652
+ * }
653
+ * ```
654
+ */
655
+ declare function getMeetingsForMultipleUsers(apiKeys: string[], options?: MultiUserOptions): AsyncIterable<MultiUserTranscript>;
656
+
657
+ /**
658
+ * Options for batch normalization, extending NormalizationOptions.
659
+ */
660
+ interface BatchNormalizationOptions extends NormalizationOptions {
661
+ /**
662
+ * Delay between items in ms.
663
+ * Since normalization is a pure function, this is typically 0.
664
+ * @default 0
665
+ */
666
+ delayMs?: number;
667
+ }
668
+ /**
669
+ * Normalize a Fireflies transcript to a provider-agnostic format.
670
+ *
671
+ * This function converts Fireflies-specific transcript data to a normalized schema
672
+ * that can be used across multiple meeting intelligence providers.
673
+ *
674
+ * @param transcript - The Fireflies transcript to normalize
675
+ * @param options - Normalization options
676
+ * @returns A normalized meeting object
677
+ *
678
+ * @example
679
+ * ```typescript
680
+ * import { FirefliesClient, normalizeTranscript } from 'fireflies-api';
681
+ *
682
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
683
+ * const transcript = await client.transcripts.get({ id: 'transcript-id' });
684
+ *
685
+ * const normalized = normalizeTranscript(transcript, {
686
+ * timeUnit: 'milliseconds',
687
+ * includeRawData: true,
688
+ * });
689
+ *
690
+ * console.log(normalized.id); // "fireflies:transcript-id"
691
+ * console.log(normalized.duration); // in seconds
692
+ * ```
693
+ */
694
+ declare function normalizeTranscript(transcript: Transcript, options?: NormalizationOptions): NormalizedMeeting;
695
+ /**
696
+ * Create a pre-configured normalizer function.
697
+ *
698
+ * Useful when normalizing multiple transcripts with the same options.
699
+ *
700
+ * @param options - Normalization options to apply to all transcripts
701
+ * @returns A function that normalizes transcripts with the configured options
702
+ *
703
+ * @example
704
+ * ```typescript
705
+ * import { createNormalizer } from 'fireflies-api';
706
+ *
707
+ * const normalizer = createNormalizer({
708
+ * timeUnit: 'milliseconds',
709
+ * includeRawData: false,
710
+ * });
711
+ *
712
+ * // Reuse with same config
713
+ * const norm1 = normalizer(transcript1);
714
+ * const norm2 = normalizer(transcript2);
715
+ * ```
716
+ */
717
+ declare function createNormalizer(options?: NormalizationOptions): (transcript: Transcript) => NormalizedMeeting;
718
+ /**
719
+ * Normalize multiple transcripts with streaming and error handling.
720
+ *
721
+ * Yields a BatchResult for each transcript, capturing any errors
722
+ * without stopping iteration.
723
+ *
724
+ * @param transcripts - Array or async iterable of transcripts to normalize
725
+ * @param options - Batch normalization options
726
+ * @returns AsyncIterable yielding BatchResult for each transcript
727
+ *
728
+ * @example
729
+ * ```typescript
730
+ * import { normalizeTranscripts } from 'fireflies-api';
731
+ *
732
+ * for await (const result of normalizeTranscripts(transcripts)) {
733
+ * if (result.error) {
734
+ * console.error(`Failed: ${result.item.id}`, result.error);
735
+ * } else {
736
+ * console.log(result.result.id); // "fireflies:..."
737
+ * }
738
+ * }
739
+ * ```
740
+ */
741
+ declare function normalizeTranscripts(transcripts: Transcript[] | AsyncIterable<Transcript>, options?: BatchNormalizationOptions): AsyncIterable<BatchResult<Transcript, NormalizedMeeting>>;
742
+ /**
743
+ * Normalize multiple transcripts and collect all results.
744
+ *
745
+ * Unlike the streaming `normalizeTranscripts()`, this waits for all items
746
+ * to complete and returns results as an array.
747
+ *
748
+ * @param transcripts - Array or async iterable of transcripts to normalize
749
+ * @param options - Batch normalization options
750
+ * @returns Array of BatchResult for each transcript
751
+ *
752
+ * @example
753
+ * ```typescript
754
+ * import { normalizeTranscriptsAll } from 'fireflies-api';
755
+ *
756
+ * const results = await normalizeTranscriptsAll(transcripts, {
757
+ * timeUnit: 'milliseconds',
758
+ * includeRawData: false,
759
+ * });
760
+ *
761
+ * const successful = results.filter(r => !r.error).map(r => r.result);
762
+ * const failed = results.filter(r => r.error);
763
+ * ```
764
+ */
765
+ declare function normalizeTranscriptsAll(transcripts: Transcript[] | AsyncIterable<Transcript>, options?: BatchNormalizationOptions): Promise<BatchResult<Transcript, NormalizedMeeting>[]>;
766
+
767
+ /**
768
+ * Create an async iterable that automatically paginates through results.
769
+ *
770
+ * @param fetcher - Function that fetches a page of results
771
+ * @param pageSize - Number of items per page
772
+ * @returns Async iterable yielding items one at a time
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * const items = paginate(
777
+ * (skip, limit) => client.transcripts.list({ skip, limit }),
778
+ * 50
779
+ * );
780
+ *
781
+ * for await (const item of items) {
782
+ * console.log(item.title);
783
+ * }
784
+ * ```
785
+ */
786
+ declare function paginate<T>(fetcher: (skip: number, limit: number) => Promise<T[]>, pageSize?: number): AsyncIterable<T>;
787
+ /**
788
+ * Collect all items from an async iterable into an array.
789
+ *
790
+ * @param iterable - Async iterable to collect
791
+ * @returns Array of all items
792
+ */
793
+ declare function collectAll<T>(iterable: AsyncIterable<T>): Promise<T[]>;
794
+
795
+ /**
796
+ * Search helper functions for searching transcript content.
797
+ */
798
+
799
+ /**
800
+ * Search a single transcript for matching sentences.
801
+ *
802
+ * This is a pure function with no API calls, making it fully testable.
803
+ * It searches the transcript's sentences for text matching the query,
804
+ * optionally filtering by speaker, questions, or tasks.
805
+ *
806
+ * @param transcript - The transcript to search
807
+ * @param options - Search options including query, filters, and context settings
808
+ * @returns Array of matches with context
809
+ *
810
+ * @example
811
+ * ```typescript
812
+ * import { searchTranscript } from 'fireflies-api';
813
+ *
814
+ * const matches = searchTranscript(transcript, {
815
+ * query: 'budget',
816
+ * speakers: ['Alice'],
817
+ * filterQuestions: true,
818
+ * contextLines: 2,
819
+ * });
820
+ *
821
+ * for (const match of matches) {
822
+ * console.log(`${match.sentence.speakerName}: ${match.sentence.text}`);
823
+ * }
824
+ * ```
825
+ */
826
+ declare function searchTranscript(transcript: Transcript, options: SearchTranscriptOptions): SearchMatch[];
827
+
828
+ /**
829
+ * A transcript with a guaranteed video URL.
830
+ */
831
+ interface TranscriptWithVideo {
832
+ /** The full transcript object */
833
+ transcript: Transcript;
834
+ /** URL to download video (expires after 24h) */
835
+ videoUrl: string;
836
+ }
837
+ /**
838
+ * Iterate through transcripts that have video recordings.
839
+ *
840
+ * This function filters transcripts to only yield those with video_url set.
841
+ * Video recordings require Business plan or higher.
842
+ *
843
+ * @param client - FirefliesClient instance
844
+ * @param options - Optional filter parameters (pagination is handled automatically)
845
+ * @returns AsyncIterable yielding transcripts with their video URLs
846
+ *
847
+ * @example
848
+ * ```typescript
849
+ * import { FirefliesClient, getMeetingVideos } from 'fireflies-api';
850
+ *
851
+ * const client = new FirefliesClient({ apiKey: 'your-api-key' });
852
+ *
853
+ * for await (const { transcript, videoUrl } of getMeetingVideos(client)) {
854
+ * console.log(`${transcript.title}: ${videoUrl}`);
855
+ * }
856
+ *
857
+ * // With filters
858
+ * for await (const item of getMeetingVideos(client, {
859
+ * fromDate: '2024-01-01',
860
+ * mine: true,
861
+ * })) {
862
+ * console.log(item.videoUrl);
863
+ * }
864
+ * ```
865
+ */
866
+ declare function getMeetingVideos(client: FirefliesClient, options?: Omit<TranscriptsListParams, 'skip' | 'limit'>): AsyncIterable<TranscriptWithVideo>;
867
+ /**
868
+ * Check if a transcript has a video recording.
869
+ *
870
+ * @param transcript - Transcript to check
871
+ * @returns true if the transcript has a video URL
872
+ */
873
+ declare function hasVideo(transcript: Transcript): transcript is Transcript & {
874
+ video_url: string;
875
+ };
876
+
877
+ /**
878
+ * Deduplicates items by a key.
879
+ * Uses a sliding window to avoid unbounded memory growth.
880
+ */
881
+ declare class Deduplicator {
882
+ private seen;
883
+ private queue;
884
+ private maxSize;
885
+ constructor(maxSize?: number);
886
+ /**
887
+ * Check if item is a duplicate and mark as seen.
888
+ * @param key - Unique key to check
889
+ * @returns true if duplicate, false if new
890
+ */
891
+ isDuplicate(key: string): boolean;
892
+ /**
893
+ * Clear all tracked keys.
894
+ */
895
+ clear(): void;
896
+ /**
897
+ * Get current number of tracked keys.
898
+ */
899
+ get size(): number;
900
+ }
901
+
902
+ /**
903
+ * Type guard to check if a payload is a valid WebhookPayload.
904
+ *
905
+ * @param payload - The payload to validate
906
+ * @returns true if the payload matches the WebhookPayload structure
907
+ *
908
+ * @example
909
+ * ```typescript
910
+ * if (isValidWebhookPayload(req.body)) {
911
+ * // req.body is now typed as WebhookPayload
912
+ * console.log(req.body.meetingId);
913
+ * }
914
+ * ```
915
+ */
916
+ declare function isValidWebhookPayload(payload: unknown): payload is WebhookPayload;
917
+ /**
918
+ * Parse and validate a Fireflies webhook payload.
919
+ *
920
+ * Optionally verifies the webhook signature if signature and secret are provided.
921
+ *
922
+ * @param payload - The webhook payload to parse
923
+ * @param options - Optional verification options
924
+ * @returns The validated WebhookPayload
925
+ * @throws {WebhookVerificationError} If signature verification fails
926
+ * @throws {WebhookParseError} If payload structure is invalid
927
+ *
928
+ * @example
929
+ * ```typescript
930
+ * // Parse without verification
931
+ * const event = parseWebhookPayload(req.body);
932
+ * console.log(event.meetingId);
933
+ *
934
+ * // Parse with verification
935
+ * const event = parseWebhookPayload(req.body, {
936
+ * signature: req.headers['x-hub-signature'],
937
+ * secret: process.env.WEBHOOK_SECRET,
938
+ * });
939
+ * ```
940
+ */
941
+ declare function parseWebhookPayload(payload: unknown, options?: ParseOptions): WebhookPayload;
942
+
943
+ /**
944
+ * Verify the authenticity of a Fireflies webhook using HMAC SHA-256.
945
+ *
946
+ * Uses timing-safe comparison to prevent timing attacks.
947
+ *
948
+ * @param options - Verification options
949
+ * @returns true if the signature is valid, false otherwise
950
+ *
951
+ * @example
952
+ * ```typescript
953
+ * const isValid = verifyWebhookSignature({
954
+ * payload: req.body,
955
+ * signature: req.headers['x-hub-signature'],
956
+ * secret: process.env.WEBHOOK_SECRET,
957
+ * });
958
+ *
959
+ * if (!isValid) {
960
+ * return res.status(401).send('Invalid signature');
961
+ * }
962
+ * ```
963
+ */
964
+ declare function verifyWebhookSignature(options: VerifyOptions): boolean;
965
+
966
+ export { type AccumulatedTranscript, ActionItem, ActionItemOptions, ActionItemsFilterOptions, ActionItemsMarkdownOptions, ActionItemsResult, AggregatedActionItemsResult, AuthenticationError, type BatchNormalizationOptions, type BatchOptions, type BatchResult, ChunkTimeoutError, type ChunksExportOptions, ConnectionError, Deduplicator, type ExternalQuestion, type ExternalQuestionsResult, FirefliesClient, FirefliesError, GraphQLError, type GraphQLErrorDetail, type MarkdownExportOptions, MeetingInsights, MeetingInsightsOptions, type MultiUserOptions, type MultiUserTranscript, NetworkError, NormalizationOptions, NormalizedMeeting, NotFoundError, ParseOptions, RateLimitError, RealtimeError, SearchMatch, SearchTranscriptOptions, type SpeakerTurn, StreamClosedError, TimeoutError, Transcript, TranscriptAccumulator, type TranscriptWithVideo, TranscriptionChunk, TranscriptsListParams, ValidationError, VerifyOptions, WebhookParseError, WebhookPayload, WebhookVerificationError, aggregateActionItems, analyzeMeetings, batch, batchAll, chunksToMarkdown, collectAll, createNormalizer, extractDomain, filterActionItems, findExternalParticipantQuestions, formatActionItemsMarkdown, getMeetingVideos, getMeetingsForMultipleUsers, hasExternalParticipants, hasVideo, isValidWebhookPayload, normalizeTranscript, normalizeTranscripts, normalizeTranscriptsAll, paginate, parseWebhookPayload, searchTranscript, transcriptToMarkdown, verifyWebhookSignature };