← Public packages
@charlesmatte/granola
Search and read Granola meeting notes, summaries and transcripts from any agent; manage webhooks and legal holds safely.
src/notes/transcript.ts
53 lines · 2.3 KB · TypeScriptimport { listEndpoint, pageSpec, parseWithAccount } from '../lib/api.ts'
import { transcriptToText, type TranscriptItem } from '../lib/transcript.ts'
import { NOTE_ID_PATTERN } from '../lib/validate.ts'
/**
* Fetch a meeting transcript in cursor pages (`GET /v1/notes/{note_id}/transcript`, up to 100
* items per page) — works for transcripts too large for ./notes/get. By default fetches the whole
* transcript and returns both the raw items and a readable text rendering.
*
* @param input.account - Account name (secret `granola-<account>`). Required. @param input.secretName - Secret override.
* @param input.noteId - `not_…` id (from ./notes/list). Required.
* @param input.format - `'text'` (default: `[m:ss] Speaker: text`, same-speaker lines merged), `'items'` (raw), or `'both'`.
* @param input.timestamps - Include `[m:ss]` offsets in text (default true).
* @param input.limit - Max items (1-50000, default 50000 = whole transcript). @param input.paginate - Follow cursors (default true).
* @param input.cursor - Continue from a previous `cursor`.
* @returns `{ account, noteId, count, text?, items?, hasMore, cursor, pages }`
*
* @example
* import transcript from 'kody:@charlesmatte/granola/notes/transcript'
*
* const t = await transcript({ account: 'work', noteId: 'not_1d3tmYTlCICgjy' })
*/
export default async function getGranolaTranscript(input: unknown) {
const p = parseWithAccount<{ noteId: string; format?: 'text' | 'items' | 'both'; timestamps?: boolean; limit?: number; cursor?: string; paginate?: boolean }>(
input,
{
noteId: { type: 'string', required: true, pattern: NOTE_ID_PATTERN },
format: { type: 'enum', values: ['text', 'items', 'both'] },
timestamps: { type: 'boolean' },
...pageSpec(50000),
},
'notes/transcript',
)
const r = await listEndpoint<TranscriptItem>(p.acct, {
path: `/v1/notes/${p.noteId}/transcript`,
itemsKey: 'transcript',
limit: p.limit ?? 50000,
maxPageSize: 100,
cursor: p.cursor,
paginate: p.paginate ?? true,
})
const format = p.format ?? 'text'
return {
account: p.acct.account,
noteId: p.noteId,
count: r.count,
...(format !== 'items' ? { text: transcriptToText(r.items, { timestamps: p.timestamps }) } : {}),
...(format !== 'text' ? { items: r.items } : {}),
hasMore: r.hasMore,
cursor: r.cursor,
pages: r.pages,
}
}