Series
Every path is relative to https://app.lobbe.ai/api/v1, and every request sends Authorization: Bearer $LOBBE_TOKEN. The API reference lists every route and explains the x-lobbe-* fields.
GET /series/readable
Section titled “GET /series/readable”The series you own or joined.
| Property | Value |
|---|---|
| Scopes | series:read |
| Spends minutes | No |
| Rate limit | read: 600 requests per 10 minutes per token |
| Success | 200 |
Response 200
Section titled “Response 200”The series you own, then the ones you joined, each group by name; empty while series are switched off.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
items[] |
object[] |
Yes | The series |
items[].id |
string |
Yes | The series’ id, as seriesId takes it |
items[].name |
string |
Yes | The series’ name |
items[].role |
"owner" | "member" |
Yes | owner when you made the series; member when you joined it |
items[].meetingCount |
integer |
Yes | How many finished meetings meetingsUrl lists for you right now |
items[].url |
string (uri) |
Yes | The series’ page in the web app |
items[].meetingsUrl |
string (uri) |
Yes | GET it with the same token for the series’ finished meetings (listReadyRecordings with seriesId) |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
GET /series/{id}
Section titled “GET /series/{id}”One series you own or joined: its name, its defaults and how many finished meetings it holds.
| Property | Value |
|---|---|
| Scopes | series:read |
| Spends minutes | No |
| Rate limit | read: 600 requests per 10 minutes per token |
| Success | 200 |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path |
string |
Yes | The series’ id |
Response 200
Section titled “Response 200”One series.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
series |
object |
Yes | The series. defaultKind and defaultOutputLanguage are what the app’s “Lobbe settings” start with for a meeting filed in it; submitRecording does not read them |
series.id |
string |
Yes | The series’ id, as seriesId takes it |
series.name |
string |
Yes | The series’ name |
series.access |
"owner" | "member" |
Yes | owner when you made the series; member when you joined it |
series.defaultKind |
"MEETING" | "LECTURE" | "INTERVIEW" | "VOICE_MEMO" | "CALL" |
Yes | The kind of recording, which picks the Lobbe’s template: MEETING, LECTURE, INTERVIEW, VOICE_MEMO or CALL |
series.defaultOutputLanguage |
"MATCH" | "FA" | "EN" |
Yes | A Lobbe language: MATCH (the meeting’s own), FA or EN |
series.titleStyle |
"SESSION" | "TOPIC" |
Yes | How the series’ meetings are titled: SESSION (“Series name + date”: the series’ name and the meeting’s date, with the meeting’s own title beneath) or TOPIC (“Each meeting’s topic”: its own title) |
series.dateCalendar |
"AUTO" | "JALALI" | "GREGORIAN" |
Yes | The calendar of the date in a SESSION title: AUTO (by the Lobbe’s language: Solar Hijri for Persian, Gregorian for English), JALALI (Solar Hijri) or GREGORIAN |
series.meetingCount |
integer |
Yes | How many finished meetings of the series you can read: the ones listReadyRecordings with seriesId lists |
series.lastRecordedAt |
string | null |
Yes | When the newest of those meetings happened (ISO 8601, UTC); null when there is none |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
PATCH /series/{id}
Section titled “PATCH /series/{id}”Change a series you own: its name, type and default language, title style or calendar.
| Property | Value |
|---|---|
| Scopes | series:write |
| Spends minutes | No |
| Rate limit | settings: 60 requests per 10 minutes per token |
| Success | 200 |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path |
string |
Yes | The series’ id |
Request body (application/json)
Section titled “Request body (application/json)”The fields to change, at least one; a field you leave out keeps its value. Owner only: a series that isn’t yours is a 404. A name one of your series already has (ignoring case) is 409 SERIES_NAME_TAKEN. Send at least one field; an empty body is a 400. A field not listed here is a 400.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
No | One line: whitespace runs (line breaks and tabs included) collapse to a single space and the ends are trimmed, then 1–60 characters; any other control character is refused |
defaultKind |
"MEETING" | "LECTURE" | "INTERVIEW" | "VOICE_MEMO" | "CALL" |
No | The kind the app’s “Lobbe settings” start with for a meeting filed in the series: MEETING, LECTURE, INTERVIEW, VOICE_MEMO or CALL |
defaultOutputLanguage |
"MATCH" | "FA" | "EN" |
No | The Lobbe language the app’s “Lobbe settings” start with for a meeting filed in the series: MATCH (the meeting’s own), FA or EN |
titleStyle |
"SESSION" | "TOPIC" |
No | How the series’ meetings are titled: SESSION (“Series name + date”: the series’ name and the meeting’s date, with the meeting’s own title beneath) or TOPIC (“Each meeting’s topic”: its own title) |
dateCalendar |
"AUTO" | "JALALI" | "GREGORIAN" |
No | The calendar of the date in a SESSION title: AUTO (by the Lobbe’s language: Solar Hijri for Persian, Gregorian for English), JALALI (Solar Hijri) or GREGORIAN |
Response 200
Section titled “Response 200”One series.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
series |
object |
Yes | The series. defaultKind and defaultOutputLanguage are what the app’s “Lobbe settings” start with for a meeting filed in it; submitRecording does not read them |
series.id |
string |
Yes | The series’ id, as seriesId takes it |
series.name |
string |
Yes | The series’ name |
series.access |
"owner" | "member" |
Yes | owner when you made the series; member when you joined it |
series.defaultKind |
"MEETING" | "LECTURE" | "INTERVIEW" | "VOICE_MEMO" | "CALL" |
Yes | The kind of recording, which picks the Lobbe’s template: MEETING, LECTURE, INTERVIEW, VOICE_MEMO or CALL |
series.defaultOutputLanguage |
"MATCH" | "FA" | "EN" |
Yes | A Lobbe language: MATCH (the meeting’s own), FA or EN |
series.titleStyle |
"SESSION" | "TOPIC" |
Yes | How the series’ meetings are titled: SESSION (“Series name + date”: the series’ name and the meeting’s date, with the meeting’s own title beneath) or TOPIC (“Each meeting’s topic”: its own title) |
series.dateCalendar |
"AUTO" | "JALALI" | "GREGORIAN" |
Yes | The calendar of the date in a SESSION title: AUTO (by the Lobbe’s language: Solar Hijri for Persian, Gregorian for English), JALALI (Solar Hijri) or GREGORIAN |
series.meetingCount |
integer |
Yes | How many finished meetings of the series you can read: the ones listReadyRecordings with seriesId lists |
series.lastRecordedAt |
string | null |
Yes | When the newest of those meetings happened (ISO 8601, UTC); null when there is none |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
POST /series
Section titled “POST /series”Create a series: its name, type and default language, title style and calendar.
| Property | Value |
|---|---|
| Scopes | series:write |
| Spends minutes | No |
| Rate limit | settings: 60 requests per 10 minutes per token |
| Success | 201 |
Request body (application/json)
Section titled “Request body (application/json)”A new series; only name is required. A name one of your series already has (ignoring case) is 409 SERIES_NAME_TAKEN, and an account that already owns 50 series gets 409 SERIES_LIMIT. A field not listed here is a 400.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | One line: whitespace runs (line breaks and tabs included) collapse to a single space and the ends are trimmed, then 1–60 characters; any other control character is refused |
defaultKind |
"MEETING" | "LECTURE" | "INTERVIEW" | "VOICE_MEMO" | "CALL" |
No | The kind the app’s “Lobbe settings” start with for a meeting filed in the series: MEETING, LECTURE, INTERVIEW, VOICE_MEMO or CALL (default MEETING) |
defaultOutputLanguage |
"MATCH" | "FA" | "EN" |
No | The Lobbe language the app’s “Lobbe settings” start with for a meeting filed in the series: MATCH (the meeting’s own), FA or EN (default MATCH) |
titleStyle |
"SESSION" | "TOPIC" |
No | How the series’ meetings are titled: SESSION (“Series name + date”: the series’ name and the meeting’s date, with the meeting’s own title beneath) or TOPIC (“Each meeting’s topic”: its own title) (default SESSION) |
dateCalendar |
"AUTO" | "JALALI" | "GREGORIAN" |
No | The calendar of the date in a SESSION title: AUTO (by the Lobbe’s language: Solar Hijri for Persian, Gregorian for English), JALALI (Solar Hijri) or GREGORIAN (default AUTO) |
Response 201
Section titled “Response 201”One series.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
series |
object |
Yes | The series. defaultKind and defaultOutputLanguage are what the app’s “Lobbe settings” start with for a meeting filed in it; submitRecording does not read them |
series.id |
string |
Yes | The series’ id, as seriesId takes it |
series.name |
string |
Yes | The series’ name |
series.access |
"owner" | "member" |
Yes | owner when you made the series; member when you joined it |
series.defaultKind |
"MEETING" | "LECTURE" | "INTERVIEW" | "VOICE_MEMO" | "CALL" |
Yes | The kind of recording, which picks the Lobbe’s template: MEETING, LECTURE, INTERVIEW, VOICE_MEMO or CALL |
series.defaultOutputLanguage |
"MATCH" | "FA" | "EN" |
Yes | A Lobbe language: MATCH (the meeting’s own), FA or EN |
series.titleStyle |
"SESSION" | "TOPIC" |
Yes | How the series’ meetings are titled: SESSION (“Series name + date”: the series’ name and the meeting’s date, with the meeting’s own title beneath) or TOPIC (“Each meeting’s topic”: its own title) |
series.dateCalendar |
"AUTO" | "JALALI" | "GREGORIAN" |
Yes | The calendar of the date in a SESSION title: AUTO (by the Lobbe’s language: Solar Hijri for Persian, Gregorian for English), JALALI (Solar Hijri) or GREGORIAN |
series.meetingCount |
integer |
Yes | How many finished meetings of the series you can read: the ones listReadyRecordings with seriesId lists |
series.lastRecordedAt |
string | null |
Yes | When the newest of those meetings happened (ISO 8601, UTC); null when there is none |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
GET /series/{id}/keyterms
Section titled “GET /series/{id}/keyterms”A series’ vocabulary (owner only), and whether the account’s vocabulary applies too.
| Property | Value |
|---|---|
| Scopes | series:read |
| Spends minutes | No |
| Rate limit | read: 600 requests per 10 minutes per token |
| Success | 200 |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path |
string |
Yes | The series’ id |
Response 200
Section titled “Response 200”The series’ vocabulary. Owner only: a series that isn’t yours is a 404.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
keyterms[] |
string[] |
Yes | The series’ own terms, in their saved order (at most 100); a meeting filed in the series is transcribed with them first |
inheritAccountKeyterms |
boolean |
Yes | Whether the account’s vocabulary is used too, after the series’ words and up to 100 terms in all; account terms that don’t fit are left off the end of its list (the app’s “Also use my vocabulary”) |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
PUT /series/{id}/keyterms
Section titled “PUT /series/{id}/keyterms”Replace a series’ vocabulary (owner only); a meeting that uses vocabulary carries its surcharge.
| Property | Value |
|---|---|
| Scopes | series:write |
| Spends minutes | No |
| Rate limit | settings: 60 requests per 10 minutes per token |
| Success | 200 |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path |
string |
Yes | The series’ id |
Request body (application/json)
Section titled “Request body (application/json)”The series’ whole vocabulary, replacing the old one. A meeting keeps the words it was submitted with, and a meeting that uses any costs 20% more. A field not listed here is a 400.
| Field | Type | Required | Description |
|---|---|---|---|
keyterms[] |
string[] |
Yes | The whole new list. Each term is trimmed and its runs of spaces collapse to one; then at most 100 terms, each 1–49 characters and at most 5 words, none containing <, >, {, }, [, ] or \, and no term twice. A list that breaks a rule is a 400 whose message names the first problem |
inheritAccountKeyterms |
boolean |
Yes | Whether the account’s vocabulary is used too, after the series’ words and up to 100 terms in all; account terms that don’t fit are left off the end of its list (the app’s “Also use my vocabulary”) |
Response 200
Section titled “Response 200”The series’ vocabulary. Owner only: a series that isn’t yours is a 404.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
keyterms[] |
string[] |
Yes | The series’ own terms, in their saved order (at most 100); a meeting filed in the series is transcribed with them first |
inheritAccountKeyterms |
boolean |
Yes | Whether the account’s vocabulary is used too, after the series’ words and up to 100 terms in all; account terms that don’t fit are left off the end of its list (the app’s “Also use my vocabulary”) |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
GET /series/{id}/ask/quote
Section titled “GET /series/{id}/ask/quote”What asking this series a question will cost, in minutes, and over how many meetings.
| Property | Value |
|---|---|
| Scopes | series:query |
| Spends minutes | No |
| Rate limit | search: 120 requests per 10 minutes per token |
| Success | 200 |
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path |
string |
Yes | The series’ id |
Response 200
Section titled “Response 200”What one question to this series costs; reading the quote is free.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
minutes |
integer |
Yes | The price in minutes: what askSeries charges, worked out the same way, so the two agree while the series’ meetings are unchanged |
meetingCount |
integer |
Yes | How many finished meetings of the series the question reads: every one’s Lobbe, then as many full transcripts as fit, newest first. Under 2 the quote answers 409 SERIES_ASK_TOO_FEW |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.
POST /series/{id}/ask
Section titled “POST /series/{id}/ask”Ask a whole series a question, answered across its finished meetings; each answer is charged.
| Property | Value |
|---|---|
| Scopes | series:query |
| Spends minutes | Yes |
| Rate limit | ask: 30 requests per 10 minutes per token |
| Success | 200 |
This route can spend minutes: send an Idempotency-Key header, and a retry with the same key returns the first outcome instead of charging again. See Idempotency and retries.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path |
string |
Yes | The series’ id |
Idempotency-Key |
header |
string |
No | Recommended. Make one key (8–64 characters, a random UUID say) once per new meeting or question, and send that same key unchanged on every retry of that request; never reuse it for a different request. A replay returns the original outcome and never charges twice. Keys are the owner’s for good: they never expire. |
Request body (application/json)
Section titled “Request body (application/json)”The question, with a price ceiling if you want one. A field not listed here is a 400.
| Field | Type | Required | Description |
|---|---|---|---|
question |
string |
Yes | The question, trimmed, 1–500 characters |
maxMinutes |
integer |
No | The most you agree to pay, in minutes (at least 1): when the price is higher, the question is refused with 409 PRICE_ABOVE_MAX (its details carry minutes and maxMinutes) and nothing is charged; absent = no ceiling |
idempotencyKey |
string |
No | The idempotency key in the body, instead of the Idempotency-Key header (8–64 characters); the header wins when both are sent |
Response 200
Section titled “Response 200”The answer across the series’ meetings, already charged; a replay with the same idempotency key returns it again and never charges twice.
| Field | Type | Always present | Description |
|---|---|---|---|
schemaVersion |
1 |
Yes | Always 1 within API v1 |
answer |
string |
Yes | The answer. [n] marks the claim that citations[n - 1] supports, numbered 1, 2, … in reading order |
citations[] |
object[] |
Yes | Where the series says it: at most 5 turns, from any of its meetings, in the order the answer first cites them |
citations[].startMs |
number |
Yes | When the cited turn starts, in milliseconds from the start of the meeting’s audio |
citations[].speaker |
string | null |
Yes | Who spoke it: the turn’s speaker label as transcribed (e.g. speaker_0), never a name given to the voice; null when the turn has none |
citations[].recordingId |
string |
Yes | The meeting the turn is from, one of the series’ meetings |
minutes |
integer |
Yes | What this answer charged, in minutes; a refusal is charged too |
refused |
boolean |
Yes | true when Lobbe declines to answer from what was said: answer says why, and it is still charged |
Errors answer { error: { code, message, details? } }, and code is the contract: see Errors.