Recipes
Meetings, transcripts & summaries
One recipe answers a whole family of questions - “what meetings has this contact had?”, “what was the sentiment?”, “where’s the summary?”, “give me the transcript.” They’re all reads: start from a contact, follow the association to the meeting, read the meeting’s AI summary, highlights and sentiment - then hop one more link to the recording for the transcript itself and the media. The same pattern works from a company or deal - pass ?associations=meeting on any of them.
Before you start
Two things carry through every step. These are all reads - meetings and recordings are ingested by the call integrations (Recall.ai, Fathom, Clari…), so there’s no create endpoint, and their AI fields fill in asynchronously (wait for the recording’s status_code: "TRANSCRIPT_DONE"). And like ai_about, the AI fields - and the raw transcript - come back as JSON-encoded strings to parse; ai_formatted_transcript is already an object.
Step 1 · List the meetings on a contact
Retrieve the contact and embed its meetings by passing ?associations=meeting. Embedded associations come back as {id, association_name} pairs - ids only.
Take a meeting id from associations.meeting.records into Step 2. Got several? Fetch them all in one call with Hydrate by IDs (object=meeting). More than 100 meetings on one record are paged with the dedicated associations endpoint.
curl 'https://api.dreamteamcrm.ai/api/v1/objects/contact/records/1015634?associations=meeting' \
-H 'Authorization: Bearer <YOUR_TOKEN>'{
"id": 1015634,
"type": "contact",
"properties": {
"first_name": "Ada",
"last_name": "Chen",
"email": "ada@example.com",
"owner_id": 1000052
},
"associations": {
"meeting": {
"records": [
{ "id": 1090142, "association_name": "contact_meeting_assoc" },
{ "id": 1090143, "association_name": "contact_meeting_assoc" }
],
"metadata": {
"total": 2,
"has_more": false
}
}
},
"created_at": "2026-08-10T09:57:24.713Z",
"updated_at": "2026-08-28T22:21:16.889Z",
"created_by": 1000052
}Step 2 · Read the meeting - summary, highlights, sentiment
Retrieve the meeting by an id from Step 1. It carries the meeting intelligence: ai_sentiment (Good / Neutral / Bad) as a plain value, and ai_meeting_summary, ai_meeting_highlights, ai_meeting_post_brief as JSON-encoded strings - parse each after reading. participants is a comma-separated list of attendee emails.
The meeting does not hold the transcript - that lives on the recording. Continue to Step 3 for the transcript and media.
curl 'https://api.dreamteamcrm.ai/api/v1/objects/meeting/records/1090142' \
-H 'Authorization: Bearer <YOUR_TOKEN>'{
"id": 1090142,
"type": "meeting",
"properties": {
"title": "Analytical Engines - Q3 renewal call",
"start_at": "2026-08-14T15:00:00Z",
"end_at": "2026-08-14T15:30:00Z",
"external": true,
"user_id": 1000052,
"participants": "sam@example.com, ada@example.com",
"ai_sentiment": "Good",
"ai_meeting_summary": "{\"meeting_type\":\"Check-in\",\"tags\":[{\"tag_type\":\"topic\",\"value\":\"Renewal\",\"render_type\":\"badge\"}],\"content\":[{\"title\":\"Summary\",\"icon_category\":\"lucide-file-text\",\"value\":\"Ada walked through the Q3 renewal timeline and two open blockers; agreed to follow up on pricing.\"}]}",
"ai_meeting_highlights": "[{\"heading\":\"Renewal timeline\",\"highlight_callout\":\"Ada confirmed a Q3 renewal target.\",\"highlight_details\":\"...\",\"timestamp\":\"06:14\"}]",
"ai_meeting_post_brief": "Sam walked Ada through the Q3 renewal plan and agreed to reconnect Monday after sharing pricing."
},
"created_at": "2026-08-14T15:31:02.221Z",
"updated_at": "2026-08-14T15:48:10.984Z",
"created_by": 1000052
}Step 3 · Follow the recording for the transcript
The transcript and media live on the recording, one link on from the meeting. It’s two calls - use the tabs to switch between them: first read the meeting’s recording association for the id, then retrieve the recording.
The recording gives you two transcript shapes: transcript (the raw provider transcript, a JSON-encoded string of segments) and ai_formatted_transcript (a cleaned object of speaker turns with timestamps). audio_url and video_url are time-limited signed URLs - fetch them promptly and don’t store the URL itself.
Wait for status_code: "TRANSCRIPT_DONE" before relying on the transcript fields.
# meeting → recording id
curl 'https://api.dreamteamcrm.ai/api/v1/objects/meeting/records/1090142?associations=recording' \
-H 'Authorization: Bearer <YOUR_TOKEN>'{
"id": 1090142,
"type": "meeting",
"associations": {
"recording": {
"records": [
{
"id": 1090777,
"association_name": "meeting_recording_assoc"
}
],
"metadata": {
"total": 1,
"has_more": false
}
}
}
}# read the recording
curl 'https://api.dreamteamcrm.ai/api/v1/objects/recording/records/1090777' \
-H 'Authorization: Bearer <YOUR_TOKEN>'{
"id": 1090777,
"type": "recording",
"properties": {
"provider_name": "recall",
"status": "completed",
"status_code": "TRANSCRIPT_DONE",
"duration_seconds": 1842,
"recording_started_at": "2026-08-14T15:00:12Z",
"recording_completed_at": "2026-08-14T15:30:54Z",
"audio_url": "https://recordings.dreamteamcrm.ai/1090777/audio.mp3?X-Amz-Signature=...",
"video_url": "https://recordings.dreamteamcrm.ai/1090777/video.mp4?X-Amz-Signature=...",
"audio_file": 1090780,
"video_file": 1090781,
"transcript": "{\"version\":\"1.0\",\"provider\":\"recall\",\"duration_seconds\":1842.0,\"participants\":[{\"id\":\"100\",\"name\":\"Sam\",\"is_host\":true},{\"id\":\"300\",\"name\":\"Ada\",\"is_host\":false}],\"segments\":[{\"speaker_id\":\"100\",\"speaker_name\":\"Sam\",\"start_time\":13.9,\"end_time\":15.3,\"text\":\"Hi Ada, thanks for hopping on.\"}]}",
"ai_formatted_transcript": {
"metadata": {
"hasTimestamps": true,
"hasSpeakers": true,
"totalSegments": 315,
"segmentationType": "speaker_turns",
"participants": ["Sam", "Ada"]
},
"segments": [
{
"speaker": "Sam",
"text": "Hi Ada, thanks for hopping on.",
"timestamp": "0:13",
"timestampSeconds": 13.949221
}
]
}
},
"created_at": "2026-08-14T15:31:04.915Z",
"updated_at": "2026-08-14T15:35:04.159Z",
"created_by": 1000052
}See also
Retrieve a record and Hydrate by IDs are the endpoints this recipe composes - use them directly to test each call live. To discover every field on meeting or recording yourself, call Describe Object.