@royalti/syynk 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -76,8 +76,10 @@ const result = await client.transcribe({
76
76
 
77
77
  // Result contains:
78
78
  // - projectId: string
79
+ // - editorUrl: string (URL to open in Syynk editor)
79
80
  // - language: string
80
81
  // - duration: number (seconds)
82
+ // - lyricsText: string (plain text lyrics)
81
83
  // - segments: Segment[]
82
84
  // - words: Word[]
83
85
  ```
@@ -148,28 +150,44 @@ const result = await client.listProjects({
148
150
  });
149
151
 
150
152
  // Result contains:
151
- // - projects: Project[]
153
+ // - projects: ProjectSummary[]
152
154
  // - total: number
153
- // - hasMore: boolean
155
+ // - limit: number
156
+ // - offset: number
154
157
  ```
155
158
 
156
159
  #### `getProject(id, options?)`
157
160
 
158
- Get a single project with segments and words.
161
+ Get a single project with segments and optionally words.
159
162
 
160
163
  ```typescript
161
- const project = await client.getProject('project-id', {
162
- includeWords: true,
163
- includeSegments: true,
164
+ const result = await client.getProject('project-id', {
165
+ includeWords: true, // default: true
164
166
  });
167
+
168
+ // Result contains:
169
+ // - project: Project (id, name, type, status, editorUrl, audioUrl, etc.)
170
+ // - segments: Segment[]
171
+ // - words?: Word[] (if includeWords is true)
172
+ ```
173
+
174
+ #### `getLyrics(id)`
175
+
176
+ Get plain text lyrics for a project.
177
+
178
+ ```typescript
179
+ const result = await client.getLyrics('project-id');
180
+ console.log(result.lyrics);
181
+ // "First line of lyrics\nSecond line\n..."
165
182
  ```
166
183
 
167
184
  #### `deleteProject(id)`
168
185
 
169
- Delete a project.
186
+ Delete a project and all its segments and words.
170
187
 
171
188
  ```typescript
172
189
  await client.deleteProject('project-id');
190
+ console.log('Project deleted');
173
191
  ```
174
192
 
175
193
  #### `getRateLimitInfo()`
@@ -257,6 +275,9 @@ import type {
257
275
  Segment,
258
276
  Word,
259
277
  Project,
278
+ ProjectSummary,
279
+ ProjectResult,
280
+ LyricsResult,
260
281
  ExportFormat,
261
282
  TranscribeResult,
262
283
  ExportResult,
package/dist/index.d.mts CHANGED
@@ -45,10 +45,14 @@ interface TranscribeFileOptions {
45
45
  interface TranscribeResult {
46
46
  /** Unique identifier for the created project */
47
47
  projectId: string;
48
+ /** URL to open the project in the Syynk editor */
49
+ editorUrl: string;
48
50
  /** Detected or specified language code */
49
51
  language: string;
50
52
  /** Audio duration in seconds */
51
53
  duration: number;
54
+ /** Plain text lyrics (segments joined by newlines) */
55
+ lyricsText: string;
52
56
  /** Transcribed segments with line-level timestamps */
53
57
  segments: Segment[];
54
58
  /** Individual words with word-level timestamps */
@@ -73,6 +77,10 @@ interface Segment {
73
77
  speakerId?: string | null;
74
78
  /** Transcription confidence score (0-1) */
75
79
  confidence?: number | null;
80
+ /** ISO 8601 creation timestamp (included in project detail responses) */
81
+ createdAt?: string;
82
+ /** ISO 8601 last update timestamp (included in project detail responses) */
83
+ updatedAt?: string;
76
84
  }
77
85
  /**
78
86
  * A word with precise timestamp within a segment
@@ -92,6 +100,8 @@ interface Word {
92
100
  sortOrder: number;
93
101
  /** Transcription confidence score (0-1) */
94
102
  confidence?: number | null;
103
+ /** ISO 8601 creation timestamp (included in project detail responses) */
104
+ createdAt?: string;
95
105
  }
96
106
  /**
97
107
  * Supported export format identifiers
@@ -120,7 +130,7 @@ interface ExportResult {
120
130
  filename: string;
121
131
  /** MIME type for the content */
122
132
  mimeType: string;
123
- /** File extension (without dot) */
133
+ /** File extension (with dot, e.g., ".lrc") */
124
134
  extension: string;
125
135
  }
126
136
  /**
@@ -133,7 +143,7 @@ interface FormatInfo {
133
143
  name: string;
134
144
  /** Description of the format and its use cases */
135
145
  description: string;
136
- /** File extension (without dot) */
146
+ /** File extension (with dot, e.g., ".lrc") */
137
147
  extension: string;
138
148
  /** MIME type */
139
149
  mimeType: string;
@@ -166,15 +176,13 @@ interface ListProjectsOptions {
166
176
  */
167
177
  interface ProjectsResult {
168
178
  /** Array of projects */
169
- projects: Project[];
179
+ projects: ProjectSummary[];
170
180
  /** Total count of projects matching filters */
171
181
  total: number;
172
182
  /** Current limit */
173
183
  limit: number;
174
184
  /** Current offset */
175
185
  offset: number;
176
- /** Whether there are more results */
177
- hasMore: boolean;
178
186
  }
179
187
  /**
180
188
  * Options for getting a single project
@@ -182,13 +190,11 @@ interface ProjectsResult {
182
190
  interface GetProjectOptions {
183
191
  /** Include word-level timing data (default: true) */
184
192
  includeWords?: boolean;
185
- /** Include segments (default: true) */
186
- includeSegments?: boolean;
187
193
  }
188
194
  /**
189
- * A Syynk project containing synchronized content
195
+ * Project summary returned in list responses
190
196
  */
191
- interface Project {
197
+ interface ProjectSummary {
192
198
  /** Unique project identifier */
193
199
  id: string;
194
200
  /** Project name/title */
@@ -199,25 +205,39 @@ interface Project {
199
205
  status: ProjectStatus;
200
206
  /** Audio/video duration in seconds */
201
207
  durationSeconds: number | null;
202
- /** URL to the audio file (if stored) */
203
- audioUrl: string | null;
204
- /** URL to the video file (for subsync projects) */
205
- videoUrl: string | null;
206
- /** Error message if status is 'error' */
207
- errorMessage?: string | null;
208
+ /** URL to open the project in the Syynk editor */
209
+ editorUrl: string;
208
210
  /** ISO 8601 creation timestamp */
209
211
  createdAt: string;
210
212
  /** ISO 8601 last update timestamp */
211
213
  updatedAt: string;
212
214
  }
213
215
  /**
214
- * Full project result including segments and words
216
+ * Full project details returned from getProject()
215
217
  */
216
- interface ProjectResult extends Project {
217
- /** Project segments (included by default) */
218
+ interface Project extends ProjectSummary {
219
+ /** URL to the audio file (if stored) */
220
+ audioUrl: string | null;
221
+ }
222
+ /**
223
+ * Result of getProject() - includes project details, segments, and optionally words
224
+ */
225
+ interface ProjectResult {
226
+ /** Project details */
227
+ project: Project;
228
+ /** Project segments (always included) */
218
229
  segments: Segment[];
219
- /** Project words (included by default) */
220
- words: Word[];
230
+ /** Project words (included when includeWords is true) */
231
+ words?: Word[];
232
+ }
233
+ /**
234
+ * Result of getLyrics() - plain text lyrics for a project
235
+ */
236
+ interface LyricsResult {
237
+ /** Project ID */
238
+ projectId: string;
239
+ /** Plain text lyrics (segments joined by newlines) */
240
+ lyrics: string;
221
241
  }
222
242
  /**
223
243
  * Rate limit information from API response headers
@@ -269,7 +289,7 @@ interface ApiErrorResponse {
269
289
  *
270
290
  * @example
271
291
  * ```typescript
272
- * import { SyynkClient } from '@syynk/sdk';
292
+ * import { SyynkClient } from '@royalti/syynk';
273
293
  *
274
294
  * const client = new SyynkClient({ apiKey: 'your-api-key' });
275
295
  *
@@ -394,26 +414,40 @@ declare class SyynkClient {
394
414
  * Get a single project by ID
395
415
  *
396
416
  * @param id - Project ID
397
- * @param options - Options for including segments/words
398
- * @returns Project with segments and words
417
+ * @param options - Options for including words
418
+ * @returns Project with segments and optionally words
399
419
  *
400
420
  * @example
401
421
  * ```typescript
402
- * const project = await client.getProject('project-id', {
422
+ * const result = await client.getProject('project-id', {
403
423
  * includeWords: true,
404
424
  * });
405
- * console.log(`Project has ${project.segments.length} segments`);
425
+ * console.log(`Project has ${result.segments.length} segments`);
406
426
  * ```
407
427
  */
408
428
  getProject(id: string, options?: GetProjectOptions): Promise<ProjectResult>;
409
429
  /**
410
- * Delete a project by ID
430
+ * Get plain text lyrics for a project
431
+ *
432
+ * @param id - Project ID
433
+ * @returns Lyrics as plain text (segments joined by newlines)
434
+ *
435
+ * @example
436
+ * ```typescript
437
+ * const result = await client.getLyrics('project-id');
438
+ * console.log(result.lyrics);
439
+ * ```
440
+ */
441
+ getLyrics(id: string): Promise<LyricsResult>;
442
+ /**
443
+ * Delete a project and all its segments and words
411
444
  *
412
445
  * @param id - Project ID
413
446
  *
414
447
  * @example
415
448
  * ```typescript
416
449
  * await client.deleteProject('project-id');
450
+ * console.log('Project deleted');
417
451
  * ```
418
452
  */
419
453
  deleteProject(id: string): Promise<void>;
@@ -568,4 +602,4 @@ declare function isRateLimitError(error: unknown): error is RateLimitError;
568
602
  */
569
603
  declare function isRetryableError(error: unknown): boolean;
570
604
 
571
- export { type ApiErrorResponse, type ApiResponse, AuthenticationError, AuthorizationError, type ExportFormat, type ExportOptions, type ExportResult, type FormatInfo, type GetProjectOptions, type ListProjectsOptions, NetworkError, NotFoundError, type Project, type ProjectResult, type ProjectStatus, type ProjectType, type ProjectsResult, RateLimitError, type RateLimitInfo, type Segment, ServerError, SyynkClient, type SyynkClientOptions, SyynkError, TimeoutError, type TranscribeFileOptions, type TranscribeOptions, type TranscribeResult, ValidationError, type Word, isRateLimitError, isRetryableError, isSyynkError };
605
+ export { type ApiErrorResponse, type ApiResponse, AuthenticationError, AuthorizationError, type ExportFormat, type ExportOptions, type ExportResult, type FormatInfo, type GetProjectOptions, type ListProjectsOptions, type LyricsResult, NetworkError, NotFoundError, type Project, type ProjectResult, type ProjectStatus, type ProjectSummary, type ProjectType, type ProjectsResult, RateLimitError, type RateLimitInfo, type Segment, ServerError, SyynkClient, type SyynkClientOptions, SyynkError, TimeoutError, type TranscribeFileOptions, type TranscribeOptions, type TranscribeResult, ValidationError, type Word, isRateLimitError, isRetryableError, isSyynkError };
package/dist/index.d.ts CHANGED
@@ -45,10 +45,14 @@ interface TranscribeFileOptions {
45
45
  interface TranscribeResult {
46
46
  /** Unique identifier for the created project */
47
47
  projectId: string;
48
+ /** URL to open the project in the Syynk editor */
49
+ editorUrl: string;
48
50
  /** Detected or specified language code */
49
51
  language: string;
50
52
  /** Audio duration in seconds */
51
53
  duration: number;
54
+ /** Plain text lyrics (segments joined by newlines) */
55
+ lyricsText: string;
52
56
  /** Transcribed segments with line-level timestamps */
53
57
  segments: Segment[];
54
58
  /** Individual words with word-level timestamps */
@@ -73,6 +77,10 @@ interface Segment {
73
77
  speakerId?: string | null;
74
78
  /** Transcription confidence score (0-1) */
75
79
  confidence?: number | null;
80
+ /** ISO 8601 creation timestamp (included in project detail responses) */
81
+ createdAt?: string;
82
+ /** ISO 8601 last update timestamp (included in project detail responses) */
83
+ updatedAt?: string;
76
84
  }
77
85
  /**
78
86
  * A word with precise timestamp within a segment
@@ -92,6 +100,8 @@ interface Word {
92
100
  sortOrder: number;
93
101
  /** Transcription confidence score (0-1) */
94
102
  confidence?: number | null;
103
+ /** ISO 8601 creation timestamp (included in project detail responses) */
104
+ createdAt?: string;
95
105
  }
96
106
  /**
97
107
  * Supported export format identifiers
@@ -120,7 +130,7 @@ interface ExportResult {
120
130
  filename: string;
121
131
  /** MIME type for the content */
122
132
  mimeType: string;
123
- /** File extension (without dot) */
133
+ /** File extension (with dot, e.g., ".lrc") */
124
134
  extension: string;
125
135
  }
126
136
  /**
@@ -133,7 +143,7 @@ interface FormatInfo {
133
143
  name: string;
134
144
  /** Description of the format and its use cases */
135
145
  description: string;
136
- /** File extension (without dot) */
146
+ /** File extension (with dot, e.g., ".lrc") */
137
147
  extension: string;
138
148
  /** MIME type */
139
149
  mimeType: string;
@@ -166,15 +176,13 @@ interface ListProjectsOptions {
166
176
  */
167
177
  interface ProjectsResult {
168
178
  /** Array of projects */
169
- projects: Project[];
179
+ projects: ProjectSummary[];
170
180
  /** Total count of projects matching filters */
171
181
  total: number;
172
182
  /** Current limit */
173
183
  limit: number;
174
184
  /** Current offset */
175
185
  offset: number;
176
- /** Whether there are more results */
177
- hasMore: boolean;
178
186
  }
179
187
  /**
180
188
  * Options for getting a single project
@@ -182,13 +190,11 @@ interface ProjectsResult {
182
190
  interface GetProjectOptions {
183
191
  /** Include word-level timing data (default: true) */
184
192
  includeWords?: boolean;
185
- /** Include segments (default: true) */
186
- includeSegments?: boolean;
187
193
  }
188
194
  /**
189
- * A Syynk project containing synchronized content
195
+ * Project summary returned in list responses
190
196
  */
191
- interface Project {
197
+ interface ProjectSummary {
192
198
  /** Unique project identifier */
193
199
  id: string;
194
200
  /** Project name/title */
@@ -199,25 +205,39 @@ interface Project {
199
205
  status: ProjectStatus;
200
206
  /** Audio/video duration in seconds */
201
207
  durationSeconds: number | null;
202
- /** URL to the audio file (if stored) */
203
- audioUrl: string | null;
204
- /** URL to the video file (for subsync projects) */
205
- videoUrl: string | null;
206
- /** Error message if status is 'error' */
207
- errorMessage?: string | null;
208
+ /** URL to open the project in the Syynk editor */
209
+ editorUrl: string;
208
210
  /** ISO 8601 creation timestamp */
209
211
  createdAt: string;
210
212
  /** ISO 8601 last update timestamp */
211
213
  updatedAt: string;
212
214
  }
213
215
  /**
214
- * Full project result including segments and words
216
+ * Full project details returned from getProject()
215
217
  */
216
- interface ProjectResult extends Project {
217
- /** Project segments (included by default) */
218
+ interface Project extends ProjectSummary {
219
+ /** URL to the audio file (if stored) */
220
+ audioUrl: string | null;
221
+ }
222
+ /**
223
+ * Result of getProject() - includes project details, segments, and optionally words
224
+ */
225
+ interface ProjectResult {
226
+ /** Project details */
227
+ project: Project;
228
+ /** Project segments (always included) */
218
229
  segments: Segment[];
219
- /** Project words (included by default) */
220
- words: Word[];
230
+ /** Project words (included when includeWords is true) */
231
+ words?: Word[];
232
+ }
233
+ /**
234
+ * Result of getLyrics() - plain text lyrics for a project
235
+ */
236
+ interface LyricsResult {
237
+ /** Project ID */
238
+ projectId: string;
239
+ /** Plain text lyrics (segments joined by newlines) */
240
+ lyrics: string;
221
241
  }
222
242
  /**
223
243
  * Rate limit information from API response headers
@@ -269,7 +289,7 @@ interface ApiErrorResponse {
269
289
  *
270
290
  * @example
271
291
  * ```typescript
272
- * import { SyynkClient } from '@syynk/sdk';
292
+ * import { SyynkClient } from '@royalti/syynk';
273
293
  *
274
294
  * const client = new SyynkClient({ apiKey: 'your-api-key' });
275
295
  *
@@ -394,26 +414,40 @@ declare class SyynkClient {
394
414
  * Get a single project by ID
395
415
  *
396
416
  * @param id - Project ID
397
- * @param options - Options for including segments/words
398
- * @returns Project with segments and words
417
+ * @param options - Options for including words
418
+ * @returns Project with segments and optionally words
399
419
  *
400
420
  * @example
401
421
  * ```typescript
402
- * const project = await client.getProject('project-id', {
422
+ * const result = await client.getProject('project-id', {
403
423
  * includeWords: true,
404
424
  * });
405
- * console.log(`Project has ${project.segments.length} segments`);
425
+ * console.log(`Project has ${result.segments.length} segments`);
406
426
  * ```
407
427
  */
408
428
  getProject(id: string, options?: GetProjectOptions): Promise<ProjectResult>;
409
429
  /**
410
- * Delete a project by ID
430
+ * Get plain text lyrics for a project
431
+ *
432
+ * @param id - Project ID
433
+ * @returns Lyrics as plain text (segments joined by newlines)
434
+ *
435
+ * @example
436
+ * ```typescript
437
+ * const result = await client.getLyrics('project-id');
438
+ * console.log(result.lyrics);
439
+ * ```
440
+ */
441
+ getLyrics(id: string): Promise<LyricsResult>;
442
+ /**
443
+ * Delete a project and all its segments and words
411
444
  *
412
445
  * @param id - Project ID
413
446
  *
414
447
  * @example
415
448
  * ```typescript
416
449
  * await client.deleteProject('project-id');
450
+ * console.log('Project deleted');
417
451
  * ```
418
452
  */
419
453
  deleteProject(id: string): Promise<void>;
@@ -568,4 +602,4 @@ declare function isRateLimitError(error: unknown): error is RateLimitError;
568
602
  */
569
603
  declare function isRetryableError(error: unknown): boolean;
570
604
 
571
- export { type ApiErrorResponse, type ApiResponse, AuthenticationError, AuthorizationError, type ExportFormat, type ExportOptions, type ExportResult, type FormatInfo, type GetProjectOptions, type ListProjectsOptions, NetworkError, NotFoundError, type Project, type ProjectResult, type ProjectStatus, type ProjectType, type ProjectsResult, RateLimitError, type RateLimitInfo, type Segment, ServerError, SyynkClient, type SyynkClientOptions, SyynkError, TimeoutError, type TranscribeFileOptions, type TranscribeOptions, type TranscribeResult, ValidationError, type Word, isRateLimitError, isRetryableError, isSyynkError };
605
+ export { type ApiErrorResponse, type ApiResponse, AuthenticationError, AuthorizationError, type ExportFormat, type ExportOptions, type ExportResult, type FormatInfo, type GetProjectOptions, type ListProjectsOptions, type LyricsResult, NetworkError, NotFoundError, type Project, type ProjectResult, type ProjectStatus, type ProjectSummary, type ProjectType, type ProjectsResult, RateLimitError, type RateLimitInfo, type Segment, ServerError, SyynkClient, type SyynkClientOptions, SyynkError, TimeoutError, type TranscribeFileOptions, type TranscribeOptions, type TranscribeResult, ValidationError, type Word, isRateLimitError, isRetryableError, isSyynkError };
package/dist/index.js CHANGED
@@ -292,7 +292,7 @@ var SyynkClient = class {
292
292
  if (options?.projectName) {
293
293
  formData.append("projectName", options.projectName);
294
294
  }
295
- return this.request("/api/v1/transcribe/upload", {
295
+ return this.request("/api/v1/transcribe", {
296
296
  method: "POST",
297
297
  body: formData
298
298
  // Don't set Content-Type header - let the browser set it with boundary
@@ -339,9 +339,10 @@ var SyynkClient = class {
339
339
  * ```
340
340
  */
341
341
  async getFormats() {
342
- return this.request("/api/v1/formats", {
342
+ const response = await this.request("/api/v1/export/formats", {
343
343
  method: "GET"
344
344
  });
345
+ return response.formats;
345
346
  }
346
347
  /**
347
348
  * List projects with optional filtering and pagination
@@ -382,15 +383,15 @@ var SyynkClient = class {
382
383
  * Get a single project by ID
383
384
  *
384
385
  * @param id - Project ID
385
- * @param options - Options for including segments/words
386
- * @returns Project with segments and words
386
+ * @param options - Options for including words
387
+ * @returns Project with segments and optionally words
387
388
  *
388
389
  * @example
389
390
  * ```typescript
390
- * const project = await client.getProject('project-id', {
391
+ * const result = await client.getProject('project-id', {
391
392
  * includeWords: true,
392
393
  * });
393
- * console.log(`Project has ${project.segments.length} segments`);
394
+ * console.log(`Project has ${result.segments.length} segments`);
394
395
  * ```
395
396
  */
396
397
  async getProject(id, options) {
@@ -398,9 +399,6 @@ var SyynkClient = class {
398
399
  if (options?.includeWords !== void 0) {
399
400
  params.set("includeWords", String(options.includeWords));
400
401
  }
401
- if (options?.includeSegments !== void 0) {
402
- params.set("includeSegments", String(options.includeSegments));
403
- }
404
402
  const queryString = params.toString();
405
403
  const path = queryString ? `/api/v1/projects/${id}?${queryString}` : `/api/v1/projects/${id}`;
406
404
  return this.request(path, {
@@ -408,13 +406,31 @@ var SyynkClient = class {
408
406
  });
409
407
  }
410
408
  /**
411
- * Delete a project by ID
409
+ * Get plain text lyrics for a project
410
+ *
411
+ * @param id - Project ID
412
+ * @returns Lyrics as plain text (segments joined by newlines)
413
+ *
414
+ * @example
415
+ * ```typescript
416
+ * const result = await client.getLyrics('project-id');
417
+ * console.log(result.lyrics);
418
+ * ```
419
+ */
420
+ async getLyrics(id) {
421
+ return this.request(`/api/v1/projects/${id}/lyrics`, {
422
+ method: "GET"
423
+ });
424
+ }
425
+ /**
426
+ * Delete a project and all its segments and words
412
427
  *
413
428
  * @param id - Project ID
414
429
  *
415
430
  * @example
416
431
  * ```typescript
417
432
  * await client.deleteProject('project-id');
433
+ * console.log('Project deleted');
418
434
  * ```
419
435
  */
420
436
  async deleteProject(id) {
package/dist/index.mjs CHANGED
@@ -254,7 +254,7 @@ var SyynkClient = class {
254
254
  if (options?.projectName) {
255
255
  formData.append("projectName", options.projectName);
256
256
  }
257
- return this.request("/api/v1/transcribe/upload", {
257
+ return this.request("/api/v1/transcribe", {
258
258
  method: "POST",
259
259
  body: formData
260
260
  // Don't set Content-Type header - let the browser set it with boundary
@@ -301,9 +301,10 @@ var SyynkClient = class {
301
301
  * ```
302
302
  */
303
303
  async getFormats() {
304
- return this.request("/api/v1/formats", {
304
+ const response = await this.request("/api/v1/export/formats", {
305
305
  method: "GET"
306
306
  });
307
+ return response.formats;
307
308
  }
308
309
  /**
309
310
  * List projects with optional filtering and pagination
@@ -344,15 +345,15 @@ var SyynkClient = class {
344
345
  * Get a single project by ID
345
346
  *
346
347
  * @param id - Project ID
347
- * @param options - Options for including segments/words
348
- * @returns Project with segments and words
348
+ * @param options - Options for including words
349
+ * @returns Project with segments and optionally words
349
350
  *
350
351
  * @example
351
352
  * ```typescript
352
- * const project = await client.getProject('project-id', {
353
+ * const result = await client.getProject('project-id', {
353
354
  * includeWords: true,
354
355
  * });
355
- * console.log(`Project has ${project.segments.length} segments`);
356
+ * console.log(`Project has ${result.segments.length} segments`);
356
357
  * ```
357
358
  */
358
359
  async getProject(id, options) {
@@ -360,9 +361,6 @@ var SyynkClient = class {
360
361
  if (options?.includeWords !== void 0) {
361
362
  params.set("includeWords", String(options.includeWords));
362
363
  }
363
- if (options?.includeSegments !== void 0) {
364
- params.set("includeSegments", String(options.includeSegments));
365
- }
366
364
  const queryString = params.toString();
367
365
  const path = queryString ? `/api/v1/projects/${id}?${queryString}` : `/api/v1/projects/${id}`;
368
366
  return this.request(path, {
@@ -370,13 +368,31 @@ var SyynkClient = class {
370
368
  });
371
369
  }
372
370
  /**
373
- * Delete a project by ID
371
+ * Get plain text lyrics for a project
372
+ *
373
+ * @param id - Project ID
374
+ * @returns Lyrics as plain text (segments joined by newlines)
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * const result = await client.getLyrics('project-id');
379
+ * console.log(result.lyrics);
380
+ * ```
381
+ */
382
+ async getLyrics(id) {
383
+ return this.request(`/api/v1/projects/${id}/lyrics`, {
384
+ method: "GET"
385
+ });
386
+ }
387
+ /**
388
+ * Delete a project and all its segments and words
374
389
  *
375
390
  * @param id - Project ID
376
391
  *
377
392
  * @example
378
393
  * ```typescript
379
394
  * await client.deleteProject('project-id');
395
+ * console.log('Project deleted');
380
396
  * ```
381
397
  */
382
398
  async deleteProject(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@royalti/syynk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "TypeScript SDK for Syynk API - transcribe audio and export synchronized lyrics/subtitles",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",