Skip to content

Uploading meeting transcripts

Upload a transcript file and attach it to a meeting in Lightfield.

This guide builds on Uploading files. A meeting transcript in Lightfield is a file upload that you attach to a meeting through the meeting API.

You will need:

  • A valid API key
  • The files:create scope to upload and complete the transcript file
  • Either meetings:create or meetings:update, depending on whether you are creating a new meeting or updating an existing one
  • Optional files:read and meetings:read scopes if you want to verify the final attachment

There are two supported patterns:

PatternWhen to useMeeting request
Attach on createYou are creating the meeting and transcript togetherPOST /v1/meetings with relationships.$transcript
Attach on updateThe meeting already exists, or you want to replace the transcript laterPOST /v1/meetings/{id} with relationships.$transcript.replace

In both patterns, the first three steps are identical to the file upload lifecycle:

  1. POST /v1/files
  2. PUT <uploadUrl>
  3. POST /v1/files/{id}/complete

After that, you attach the completed file to the meeting.

Option A: create a meeting with a transcript attached

Section titled “Option A: create a meeting with a transcript attached”

First, complete the transcript file upload using Uploading files. Then create the meeting and set relationships.$transcript to the completed file id.

Pass a single organizer email in $organizerEmail.

Terminal window
curl https://api.lightfield.app/v1/meetings \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Lightfield-Version: 2026-03-01" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"$title": "Customer Call",
"$startDate": "2026-04-07T21:00:00.000Z",
"$endDate": "2026-04-07T21:45:00.000Z",
"$description": "Q2 renewal call with Acme",
"$meetingUrl": "https://meet.google.com/abc-defg-hij",
"$organizerEmail": "alex@acme.com",
"$attendeeEmails": ["alex@acme.com", "jamie@example.com"],
"$privacySetting": "FULL"
},
"relationships": {
"$transcript": "fil_abc123"
}
}'

Use this pattern when you want the meeting and transcript linked in one logical flow.

Option B: attach or replace a transcript on an existing meeting

Section titled “Option B: attach or replace a transcript on an existing meeting”

If the meeting already exists, upload and complete the transcript file first. Then update the meeting by setting relationships.$transcript.replace. This works for both manual and already-synced meetings as long as the caller is allowed to edit the meeting.

Terminal window
curl https://api.lightfield.app/v1/meetings/$MEETING_ID \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Lightfield-Version: 2026-03-01" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"$privacySetting": "METADATA"
},
"relationships": {
"$transcript": {
"replace": "fil_abc123"
}
}
}'

The transcript attachment is driven by relationships.$transcript.replace. The example above also updates $privacySetting in the same request because that field is writable on meeting updates as well.

Replacing a transcript updates the meeting relationship, but it does not delete the previous file automatically.

  1. POST /v1/files
  2. PUT <uploadUrl>
  3. POST /v1/files/{id}/complete
  4. POST /v1/meetings with relationships.$transcript = fileId
  5. Optional: GET /v1/meetings/{id}
  6. Optional: GET /v1/files/{id}/url

Attach or replace transcript on an existing meeting

Section titled “Attach or replace transcript on an existing meeting”
  1. POST /v1/files
  2. PUT <uploadUrl>
  3. POST /v1/files/{id}/complete
  4. POST /v1/meetings/{meetingId} with relationships.$transcript.replace = fileId
  5. Optional: GET /v1/meetings/{meetingId}
  6. Optional: GET /v1/files/{id}/url

After attaching the transcript, retrieve the meeting to confirm the relationship if the caller has access to the transcript under the meeting’s privacy rules. See Meeting privacy and transcript visibility below for what different callers can actually see.

Terminal window
curl https://api.lightfield.app/v1/meetings/$MEETING_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Lightfield-Version: 2026-03-01"

If you also want to confirm transcript retrieval, request a signed download URL for the file:

Terminal window
curl https://api.lightfield.app/v1/files/$FILE_ID/url \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Lightfield-Version: 2026-03-01"
TermMeaning
manual meetingA meeting created directly in Lightfield rather than imported from calendar sync.
synced meetingA meeting backed by synced calendar data.
calendar eventA synced event record from a user’s connected Google or Microsoft calendar.
connected accountA user’s Google or Microsoft account connection in Lightfield, used for sync and privacy settings.
participantA caller counts as a participant if one of their connected-account email addresses appears among the meeting attendees, or, for synced meetings, one of the meeting’s linked calendar events has that user’s userId.
$privacySettingThe privacy level explicitly set on the meeting itself.
accessLevelThe caller-specific visibility returned on a meeting response.
FULLFull meeting content is visible, including the transcript relationship.
METADATAThe meeting is visible, but sensitive fields and the transcript relationship are redacted.
transcriptThe meeting transcript relationship exposed in the API as $transcript.
edit accessSeparate from read access; only admins and participants can update a meeting.

Meeting retrieval is privacy-filtered. In practice, callers will see one of two resolved access levels:

Access levelWhat the caller can see
FULLFull meeting content, including the real title, description, meeting URL, organizer and attendee emails, and the $transcript relationship
METADATAA metadata-safe view of the meeting; sensitive content is redacted and relationships.$transcript is omitted

When a caller only has METADATA access:

  • $title is replaced with a metadata-safe synthesized title
  • $description becomes null
  • $meetingUrl becomes null
  • $meetingPrep becomes null
  • $postMeetingSummary becomes null
  • relationships.$transcript is removed from the response

This means a transcript can be successfully attached to a meeting even if a later GET /v1/meetings/{id} response does not show the transcript relationship for a particular caller.

fields.$privacySetting is the meeting’s stored privacy policy. accessLevel is the caller-specific visibility the API resolves at read time.

These are related, but not identical. For example, a meeting can have $privacySetting = METADATA, while an admin or meeting participant still receives accessLevel = FULL.

Admins and meeting participants always get FULL access.

A caller counts as a participant if either:

  • one of their connected account email addresses appears among the meeting attendees
  • for synced meetings, one of the meeting’s linked calendar events has that user’s userId

Other callers receive the meeting’s resolved privacy setting.

Updating a meeting is more restrictive than viewing it. To update a meeting, the caller must be an admin or a participant. Metadata-only visibility is not enough to attach or replace a transcript.

Creating a meeting does not, by itself, guarantee that the same caller can update it later. If you want a non-admin caller to be able to update the meeting afterward, make sure they qualify as a participant under the rules above.

If a caller can read a meeting in metadata-only form but is not allowed to edit it, POST /v1/meetings/{id} will return 403 Forbidden.

  • Uploading files — Reference guide for the underlying file upload lifecycle.
  • Objects in Lightfield — Learn how meetings relate to other records in Lightfield.
  • API Reference — Full endpoint reference for files, meetings, and other resources.