Skip to content
← Public packages

@charlesmatte/granola

Search and read Granola meeting notes, summaries and transcripts from any agent; manage webhooks and legal holds safely.

src/audit/list.ts

42 lines · 2.2 KB · TypeScript
Raw
import { listEndpoint, pageSpec, parseWithAccount } from '../lib/api.ts'
import { DATE_PATTERN } from '../lib/validate.ts'

/**
 * List workspace audit events (`GET /v1/audit`): sign-ins, sharing, member changes, API and MCP
 * access, and more, newest-collected first, with actor and request context.
 * Needs an Audit API key (Enterprise; admin creates it in Settings → Connectors → Audit API keys; https://docs.granola.ai/audit).
 * Personal and workspace API keys get 404. Events cover the last year. Action catalogue: https://docs.granola.ai/audit-events
 *
 * @param input.account - Account name (secret `granola-<account>`). Required. @param input.secretName - Secret override.
 * @param input.action - Exact action or dotted prefix, lowercase (`workspace` matches `workspace.member_added`).
 * @param input.occurredAfter - `YYYY-MM-DD` or ISO date-time (within the last year). @param input.occurredBefore - same.
 * @param input.limit - Max events (1-5000, default 100). @param input.paginate - Follow cursors (default true). @param input.cursor - Resume.
 * @returns `{ account, count, events: [{ id, action, occurred_at, collected_at, actor, data, context }], hasMore, cursor }`
 *
 * @example
 * import listAudit from 'kody:@charlesmatte/granola/audit/list'
 *
 * const logins = await listAudit({ account: 'work-admin', action: 'auth', occurredAfter: '2026-09-01' })
 */
export default async function listGranolaAuditEvents(input: unknown) {
	const p = parseWithAccount<{ action?: string; occurredAfter?: string; occurredBefore?: string; limit?: number; cursor?: string; paginate?: boolean }>(
		input,
		{
			action: { type: 'string', pattern: /^[a-z][a-z0-9_.-]*$/, maxLength: 200 },
			occurredAfter: { type: 'string', pattern: DATE_PATTERN },
			occurredBefore: { type: 'string', pattern: DATE_PATTERN },
			...pageSpec(5000),
		},
		'audit/list',
	)
	const r = await listEndpoint(p.acct, {
		path: '/v1/audit',
		itemsKey: 'events',
		query: { action: p.action, occurred_after: p.occurredAfter, occurred_before: p.occurredBefore },
		limit: p.limit ?? 100,
		maxPageSize: 30,
		cursor: p.cursor,
		paginate: p.paginate ?? true,
	})
	return { account: p.acct.account, count: r.count, events: r.items, hasMore: r.hasMore, cursor: r.cursor, pages: r.pages }
}