Greetings and welcome to the documentation of the tl;dv API! This API is designed to seamlessly integrate tl;dv functionalities into your applications, making it easier for your users to access transcripts, notes, or import your meetings. Let's explore the details together.
Current API Version: v1alpha1 (v1 Alpha 1).
You are pioneering the tl;dv API, and we're excited to have you on board! Embark with us on the alpha phase adventure! Expect upcoming changes as we sculpt this API masterpiece, evolving towards the stable v1 release. Your invaluable feedback during this period will be our guiding star. Anticipate a slew of updates, and maybe a surprise or two – who said versioning can't be thrilling?
In the tl;dv API universe, we're currently all about that production data. So there is no alternate realities or sandbox just yet. We're working on it, though, so stay tuned!
Production API Endpoint: https://pasta.tldv.io (brace yourselves, this endpoint may choose to change its pasta shape, but we will keep you updated)
To unlock the tl;dv Public API's treasure trove, you need the key – THE API key - that's it. It's the golden ticket to seamless integration.
Once you have your API key, you can include it in the header of all your API requests.
x-api-key: YOUR_API_KEY
Replace YOUR_API_KEY with the actual key. If you're using a client library, it should be as simple as setting the header value.
All API requests must be made over HTTPS. Requests made over plain HTTP will be rejected.
Each request must include a valid API key. Requests without a valid key will return an authentication error.
The tl;dv Public API follows the same underlying permission model as the web application, with additional plan-based constraints applied to automation and export capabilities.
Seeing a meeting in the web app does not automatically guarantee programmatic (API) access.
Meeting ownership is determined by the calendar invite organizer or the meeting organizer (if the meeting was created spontaneously)
If you rely on API access, make sure:
To summarize:
| Meeting Organizer Plan | UI Access | API Access |
|---|---|---|
| Free | ✅ Yes (if shared) | ❌ No |
| Pro / Business | ✅ Yes | ✅ Yes |
| Enterprise | ✅ Yes | ✅ Yes |
Webhooks allow you to receive real-time notifications from tl;dv when key events occur in your workspace.
| Trigger | Fires when … |
|---|---|
| MeetingReady | A meeting has finished processing and is ready to be used in your applications. |
| TranscriptReady | A meeting transcript has been generated and is available. |
Webhooks can be configured at different levels, depending on your needs:
You can enable one or both triggers ("MeetingReady", "TranscriptReady") at the level that makes the most sense for your setup. This gives you control over how broadly you want setup your webhooks.
When creating a subscription you can ask tl;dv to embed extra data in the payload through the include option (in the app: the Include meeting transcript checkbox). Sections are opt-in and only offered on the triggers that support them:
| Section | Trigger | Adds |
|---|---|---|
transcript |
MeetingReady | data.transcript, the same object the TranscriptReady webhook sends (id, meetingId and the data sentences). It is null when the meeting has no completed transcript, and the key is absent when the section is not enabled. |
Embedding the transcript makes the payload considerably larger (roughly 1–2 KB per minute of speech, so a few hundred KB for a long meeting). Make sure your endpoint accepts bodies of that size and answers with a 2xx quickly; tl;dv waits at most 10 seconds for a response before retrying.
When something goes wrong, the API returns a JSON body that describes what happened. The shape of that body depends on the type of error: validation errors (bad or invalid request data) use one format, and all other errors use a simpler format. Here’s what to expect.
Returned when the request is malformed or fails validation (e.g. invalid parameters, missing required fields, wrong types). Use this to fix the request and retry.
| Field | Type | Description |
|---|---|---|
message |
string | A short summary of the problem (e.g. Invalid query params, check 'errors' property for more info.). |
errors |
array | List of validation issues. Each item has property (the field that failed) and constraints (key-value pairs describing what went wrong). |
Example (invalid filter on GET /meetings — e.g. meetingType must be internal or external):
{
"message": "Invalid query params, check 'errors' property for more info.",
"errors": [
{
"property": "meetingType",
"constraints": { "isEnum": "meetingType must be one of the following values: internal, external" }
}
]
}
Used for authentication, authorization, not-found, and server errors. Same structure for all of these status codes.
| Field | Type | Description |
|---|---|---|
name |
string | Error code or type (e.g. UnauthorizedError, NotFoundError). |
message |
string | Human-readable description of the error. |
Example:
{
"name": "NotFoundError",
"message": "Meeting not found"
}
Check the HTTP status code and the name / message fields to decide whether to retry, fix the request, or contact support.
Need assistance, have a brilliant idea, or just want to say hello? Our support team is ready and waiting at support@tldv.io. Alternatively, drop by via the Intercom Widget.
Have fun! 🎉
Meetings (or recordings) related endpoints. With tl;dv you can manage your meetings. So far you can only import new ones, but more functionalities are coming soon.
Import a meeting, recording, or other media from a URL. The URL must be publicly accessible, and the media must be in a supported format.
MeetingImportControllerBody
| name required | string The name of the meeting/recording imported |
| url required | string <url> The url of the meeting/recording imported. Important: the url must be publicly accessible and the media must be in a supported format. Supported formats are: .mp3, .mp4, .wav, .m4a, .mkv, .mov, .avi, .wma, .flac. |
| happenedAt | string\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d.... The date of the meeting/recording. If not provided, the current date will be used |
| dryRun | boolean For testing purposes: whether to run the import as a dry run. If true, the import will not be persisted to the database, and nothing will be run. |
| participants | Array of strings An array of emails of the invited participants to the meeting/recording |
| phoneNumber | string <= 64 characters A phone number associated with the meeting/recording, e.g. the other party of a phone call. It is stored and returned verbatim on the meeting (GET /meetings/{id}) and in the MeetingReady webhook.Max 64 characters. |
object <= 20 properties Flat key/value object with your own identifiers (record ids, call ids, ...) so you can correlate the meeting when it comes back on GET /meetings/{id} and in the MeetingReady webhook. Values are stored and returned verbatim. Limits: at most 20 keys; keys must match ^[A-Za-z0-9_-]{1,64}$; values must be strings of at most 256 characters, numbers or booleans. Nested objects and arrays are not accepted. |
{- "name": "string",
- "url": "string",
- "happenedAt": "string",
- "dryRun": true,
- "participants": [
- "string"
], - "phoneNumber": "+1 555 010 0100",
- "metadata": {
- "crmRecordId": "rec_123",
- "callId": 42,
- "inbound": true
}
}{- "success": true,
- "jobId": "string",
- "message": "string"
}| query | string The query to search for |
| page | number > 0 The page number to return. Default is 1 |
| limit | number ( 0 .. 100 ] The number of results to return per page. Default is 50. Max is 100. The total number of results cannot exceed 10,000. If this limit is exceeded, refine the date range or period. |
string or string The date to search from | |
string or string The date to search to | |
| onlyParticipated | boolean Whether to only return meetings the user participated in. Default is false |
| meetingType | string Enum: "internal" "external" Filters meetings by type: internal (all participants from the same organization) or external (includes at least one participant from another organization). Defaults to both if not provided |
const axios = require('axios'); let config = { method: 'get', maxBodyLength: Infinity, url: 'https://pasta.tldv.io/v1alpha1/meetings?<query-params>', headers: { 'Content-Type': 'application/json', 'x-api-key': '••••••' } }; axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });
{- "page": 0,
- "pages": 0,
- "total": 0,
- "pageSize": 0,
- "results": [
- {
- "id": "string",
- "name": "string",
- "happenedAt": "string",
- "url": "string",
- "duration": 0,
- "organizer": {
- "name": "string",
- "email": "string"
}, - "invitees": [
- {
- "name": "string",
- "email": "string"
}
], - "template": "string",
- "extraProperties": {
- "conferenceId": "string"
}, - "phoneNumber": "+1 555 010 0100",
- "metadata": {
- "crmRecordId": "rec_123",
- "callId": "call_456"
}
}
]
}Get a meeting by its id. The meeting is returned in a human readable format
| meetingId required | string[^\/#\?]+? |
const axios = require('axios'); let config = { method: 'get', maxBodyLength: Infinity, url: 'https://pasta.tldv.io/v1alpha1/meetings/653663ac7c8dbd00130f11d9', headers: { 'Content-Type': 'application/json', 'x-api-key': '••••••' } }; axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });
{- "id": "string",
- "name": "string",
- "happenedAt": "string",
- "url": "string",
- "duration": 0,
- "organizer": {
- "name": "string",
- "email": "string"
}, - "invitees": [
- {
- "name": "string",
- "email": "string"
}
], - "template": "string",
- "extraProperties": {
- "conferenceId": "string"
}, - "phoneNumber": "+1 555 010 0100",
- "metadata": {
- "crmRecordId": "rec_123",
- "callId": "call_456"
}
}Returns an HTTP redirect to a signed, expiring download URL for the meeting recording.
Redirect behavior:
Location header to obtain the signed URL.Signed URL TTL: The signed URL expires 6 hours after issuance.
| meetingId required | string[^\/#\?]+? |
const axios = require('axios'); let config = { method: 'get', maxBodyLength: Infinity, url: 'https://pasta.tldv.io/v1alpha1/meetings/653663ac7c8dbd00130f11d9/download', headers: { 'Content-Type': 'application/json', 'x-api-key': '••••••' } }; axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });
Transcripts related endpoints. With tl;dv you can get the transcript of a meeting, in a structured format.
Get the transcript of a meeting by its id. The transcript is returned in a human readable format. The transcript is returned only if it is complete
| meetingId required | string[^\/#\?]+? |
const axios = require('axios'); let config = { method: 'get', maxBodyLength: Infinity, url: 'https://pasta.tldv.io/v1alpha1/meetings/653663ac7c8dbd00130f11d9/transcript', headers: { 'Content-Type': 'application/json', 'x-api-key': '••••••' } }; axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });
{- "id": "string",
- "meetingId": "string",
- "data": [
- {
- "speaker": "string",
- "text": "string",
- "startTime": 0,
- "endTime": 0
}
]
}Notes related endpoints. With tl;dv you can get the notes of a meeting, in a structured format and in Markdown format.
Get the notes of a meeting by its id. The notes are returned in a human readable format
| meetingId required | string[^\/#\?]+? |
const axios = require('axios'); let config = { method: 'get', maxBodyLength: Infinity, url: 'https://pasta.tldv.io/v1alpha1/meetings/653663ac7c8dbd00130f11d9/notes', headers: { 'Content-Type': 'application/json', 'x-api-key': '••••••' } }; axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });
{- "structuredNotes": [
- {
- "segmentId": "string",
- "timestamp": 0,
- "text": "string",
- "topicId": "string"
}
], - "markdownContent": "string",
- "topics": [
- {
- "id": "string",
- "order": 0,
- "title": "string",
- "summary": "string"
}
]
}Highlights (or notes) related endpoints. With tl;dv you can get the highlights of your meetings.
(deprecated) Get the meetings notes of a meeting, by its id. The meetings notes are returned in a human readable format and they are returned only if the transcript is complete. Use the /meetings/:meetingId/notes endpoint instead.
| meetingId required | string[^\/#\?]+? |
const axios = require('axios'); let config = { method: 'get', maxBodyLength: Infinity, url: 'https://pasta.tldv.io/v1alpha1/meetings/653663ac7c8dbd00130f11d9/highlights', headers: { 'Content-Type': 'application/json', 'x-api-key': '••••••' } }; axios.request(config) .then((response) => { console.log(JSON.stringify(response.data)); }) .catch((error) => { console.log(error); });
{- "meetingId": "string",
- "data": [
- {
- "text": "string",
- "startTime": 0,
- "source": "manual",
- "topic": {
- "title": "string",
- "summary": "string"
}
}
]
}| id required | string non-empty Unique identifier for the webhook payload |
| event required | string Value: "MeetingReady" The event type that triggered this webhook |
required | object (MeetingWebhookPayload) Meeting data included in a MeetingReady webhook event |
| executedAt required | string non-empty The date and time the webhook was executed |
{- "id": "webhook-123",
- "event": "MeetingReady",
- "data": {
- "id": "meeting-123",
- "name": "Team Standup Meeting",
- "happenedAt": "2024-01-15T10:00:00Z",
- "template": {
- "id": "template-1",
- "label": "Standup Template"
}, - "extraProperties": {
- "conferenceId": "conf-123"
}, - "phoneNumber": "+1 555 010 0100",
- "metadata": {
- "crmRecordId": "rec_123"
}, - "duration": 1800,
- "notes": {
- "markdownContent": "## Summary\n- Discussed progress and blockers",
- "structuredNotes": [
- {
- "segmentId": "segment-1",
- "timestamp": 12,
- "text": "Discussed progress and blockers",
- "topicId": "topic-1"
}
], - "topics": [
- {
- "id": "topic-1",
- "order": 0,
- "title": "Progress update",
- "summary": "Where the team stands"
}
]
}, - "transcript": {
- "id": "transcript-123",
- "meetingId": "meeting-123",
- "data": [
- {
- "speaker": "John Doe",
- "text": "Hello everyone, welcome to our standup meeting.",
- "startTime": 0,
- "endTime": 5
}
]
}
}
}This webhook is sent when a meeting transcript is ready. You can configure this webhook to receive notifications when transcripts are successfully generated.
| id required | string non-empty Unique identifier for the webhook payload |
| event required | string Value: "TranscriptReady" The event type that triggered this webhook |
required | object (GetTranscriptByMeetingIdResponse) |
| executedAt required | string non-empty The date and time the webhook was executed |
{- "id": "webhook-456",
- "event": "TranscriptReady",
- "data": {
- "id": "meeting-123",
- "meetingId": "meeting-123",
- "data": {
- "transcript": "Hello everyone, welcome to our standup meeting. Today we will discuss our progress and any blockers...",
- "segments": [
- {
- "startTime": 0,
- "endTime": 5,
- "text": "Hello everyone, welcome to our standup meeting."
}
]
}
}
}