Retrieve spoken transcript slices for one topic
GET /v1/search
Search indexed YouTube and podcast transcripts for passages matching a word or phrase. Returns passage text, source metadata, publication dates, and timestamped watch links. Narrow to passages about an entity with `about`, or passages where a person speaks with `by`. Scope with `channel_ids` (or `channel`) and `entity_ids` (a person id filters to that person's appearances). Filter to sponsored, organic or mention passages with `kind`. Every filter takes ids, never names: resolve a name first with GET /v1/entities/resolve, or the call answers 400 id_required naming the parameter. Results carry names beside ids (filters.about, filters.by, chunk about and speakers_by). Use one topic per call. Search results include text on every plan within the plan's publication-date window. Explicitly requesting source=arcmira_premium on a plan without Premium transcripts is refused with filter_requires_paid. An after later than the plan's freshness gate is refused with freshness_requires_paid rather than widened. A window the gate cut carries freshness (delay_days, served_through), unlock, and a note that says where results on this plan stop. Uses 4 credits per chunk returned past the first 5. Every gate is a typed error whose error.unlock.url names the plan that lifts it; pass src=mcp-tool only from the Arcmira MCP server.
Parameters
| Name | Location | Description |
|---|
| q (required) | query | One topic or phrase. Do not concatenate unrelated names; make one call per topic. |
| channel_ids | query | Comma-separated YouTube channel ids (UC...), at most 8. Pass every show in scope unless drilling into one. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve. |
| channel | query | Alias of channel_ids for code-mode clients; the union of both is the scope. |
| entity_ids | query | Comma-separated entity ids (ent_{n}), at most 8. A person id filters to that person's appearances; a channel id widens channel_ids. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve. |
| about | query | Comma-separated entity ids (ent_{n}), at most 8. Only passages about these entities: excerpt pins, exact-name mentions and ad verdicts. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve. |
| by | query | Comma-separated person ids (ent_{n}), at most 8. Only passages where one of these people speaks the query words. A passage can include other speakers' lines; each line with a known speaker starts with that speaker's name. A non-person id is refused with invalid_query naming its type. Speaker labels cover a minority of shows; an empty result carries a note saying whether the person is labeled anywhere. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve. |
| kind | query | Comma-separated passage classes: sponsored, organic, mention. Combine with about to read what was said about a brand in ad reads or in organic talk. |
| after | query | Only media published at or after this instant. An after later than your plan's freshness gate is refused with freshness_requires_paid rather than widened. An ISO 8601 date (2026-09-01) or datetime with offset (2026-09-01T00:00:00Z), read in UTC. The window is half-open: after is inclusive, before is exclusive. |
| before | query | Only media published before this instant, so before=2026-09-02 includes all of 2026-09-01. An ISO 8601 date (2026-09-01) or datetime with offset (2026-09-01T00:00:00Z), read in UTC. The window is half-open: after is inclusive, before is exclusive. |
| source | query | Restrict to one transcript source class. arcmira_premium on a plan without Premium transcripts is refused with filter_requires_paid. |
| limit | query | Chunks to return, 1 to 20. Default 5. |
| src | query | The surface making this call. The Arcmira MCP server sends mcp-tool so every unlock link in a gate attributes to the directory install. Omit from your own client. |
Responses
200 Success
{
"description": "Success",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
},
"RateLimit-Limit": {
"$ref": "#/components/headers/RateLimit-Limit"
},
"RateLimit-Remaining": {
"$ref": "#/components/headers/RateLimit-Remaining"
},
"RateLimit-Reset": {
"$ref": "#/components/headers/RateLimit-Reset"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TranscriptSearchResponse"
}
}
}
}
400 InvalidRequest
{
"$ref": "#/components/responses/InvalidRequest"
}
401 AuthenticationError
{
"$ref": "#/components/responses/AuthenticationError"
}
402 QuotaExceeded
{
"$ref": "#/components/responses/QuotaExceeded"
}
403 PermissionError
{
"$ref": "#/components/responses/PermissionError"
}
404 NotFound
{
"$ref": "#/components/responses/NotFound"
}
429 RateLimited
{
"$ref": "#/components/responses/RateLimited"
}
500 ServerError
{
"$ref": "#/components/responses/ServerError"
}
503 search_unavailable. Search is unavailable right now. Retry-After carries the wait; nothing was charged.
{
"description": "search_unavailable. Search is unavailable right now. Retry-After carries the wait; nothing was charged.",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
},
"Retry-After": {
"$ref": "#/components/headers/Retry-After"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
Operation definition
{
"tags": [
"Search"
],
"operationId": "search",
"summary": "Retrieve spoken transcript slices for one topic",
"description": "Search indexed YouTube and podcast transcripts for passages matching a word or phrase. Returns passage text, source metadata, publication dates, and timestamped watch links. Narrow to passages about an entity with `about`, or passages where a person speaks with `by`. Scope with `channel_ids` (or `channel`) and `entity_ids` (a person id filters to that person's appearances). Filter to sponsored, organic or mention passages with `kind`. Every filter takes ids, never names: resolve a name first with GET /v1/entities/resolve, or the call answers 400 id_required naming the parameter. Results carry names beside ids (filters.about, filters.by, chunk about and speakers_by). Use one topic per call. Search results include text on every plan within the plan's publication-date window. Explicitly requesting source=arcmira_premium on a plan without Premium transcripts is refused with filter_requires_paid. An after later than the plan's freshness gate is refused with freshness_requires_paid rather than widened. A window the gate cut carries freshness (delay_days, served_through), unlock, and a note that says where results on this plan stop. Uses 4 credits per chunk returned past the first 5. Every gate is a typed error whose error.unlock.url names the plan that lifts it; pass src=mcp-tool only from the Arcmira MCP server.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"schema": {
"type": "string",
"minLength": 2,
"description": "One topic or phrase. Do not concatenate unrelated names; make one call per topic."
},
"required": true,
"description": "One topic or phrase. Do not concatenate unrelated names; make one call per topic.",
"name": "q",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Comma-separated YouTube channel ids (UC...), at most 8. Pass every show in scope unless drilling into one. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve."
},
"required": false,
"description": "Comma-separated YouTube channel ids (UC...), at most 8. Pass every show in scope unless drilling into one. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve.",
"name": "channel_ids",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Alias of channel_ids for code-mode clients; the union of both is the scope."
},
"required": false,
"description": "Alias of channel_ids for code-mode clients; the union of both is the scope.",
"name": "channel",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Comma-separated entity ids (ent_{n}), at most 8. A person id filters to that person's appearances; a channel id widens channel_ids. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve."
},
"required": false,
"description": "Comma-separated entity ids (ent_{n}), at most 8. A person id filters to that person's appearances; a channel id widens channel_ids. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve.",
"name": "entity_ids",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Comma-separated entity ids (ent_{n}), at most 8. Only passages about these entities: excerpt pins, exact-name mentions and ad verdicts. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve."
},
"required": false,
"description": "Comma-separated entity ids (ent_{n}), at most 8. Only passages about these entities: excerpt pins, exact-name mentions and ad verdicts. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve.",
"name": "about",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Comma-separated person ids (ent_{n}), at most 8. Only passages where one of these people speaks the query words. A passage can include other speakers' lines; each line with a known speaker starts with that speaker's name. A non-person id is refused with invalid_query naming its type. Speaker labels cover a minority of shows; an empty result carries a note saying whether the person is labeled anywhere. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve."
},
"required": false,
"description": "Comma-separated person ids (ent_{n}), at most 8. Only passages where one of these people speaks the query words. A passage can include other speakers' lines; each line with a known speaker starts with that speaker's name. A non-person id is refused with invalid_query naming its type. Speaker labels cover a minority of shows; an empty result carries a note saying whether the person is labeled anywhere. Ids only: a name answers 400 id_required. Resolve names first with GET /v1/entities/resolve.",
"name": "by",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Comma-separated passage classes: sponsored, organic, mention. Combine with about to read what was said about a brand in ad reads or in organic talk."
},
"required": false,
"description": "Comma-separated passage classes: sponsored, organic, mention. Combine with about to read what was said about a brand in ad reads or in organic talk.",
"name": "kind",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Only media published at or after this instant. An after later than your plan's freshness gate is refused with freshness_requires_paid rather than widened. An ISO 8601 date (2026-09-01) or datetime with offset (2026-09-01T00:00:00Z), read in UTC. The window is half-open: after is inclusive, before is exclusive."
},
"required": false,
"description": "Only media published at or after this instant. An after later than your plan's freshness gate is refused with freshness_requires_paid rather than widened. An ISO 8601 date (2026-09-01) or datetime with offset (2026-09-01T00:00:00Z), read in UTC. The window is half-open: after is inclusive, before is exclusive.",
"name": "after",
"in": "query"
},
{
"schema": {
"type": "string",
"description": "Only media published before this instant, so before=2026-09-02 includes all of 2026-09-01. An ISO 8601 date (2026-09-01) or datetime with offset (2026-09-01T00:00:00Z), read in UTC. The window is half-open: after is inclusive, before is exclusive."
},
"required": false,
"description": "Only media published before this instant, so before=2026-09-02 includes all of 2026-09-01. An ISO 8601 date (2026-09-01) or datetime with offset (2026-09-01T00:00:00Z), read in UTC. The window is half-open: after is inclusive, before is exclusive.",
"name": "before",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"arcmira_premium",
"creator_captions",
"third_party_quick"
],
"description": "Restrict to one transcript source class. arcmira_premium on a plan without Premium transcripts is refused with filter_requires_paid."
},
"required": false,
"description": "Restrict to one transcript source class. arcmira_premium on a plan without Premium transcripts is refused with filter_requires_paid.",
"name": "source",
"in": "query"
},
{
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 20,
"default": 5,
"description": "Chunks to return, 1 to 20. Default 5."
},
"required": false,
"description": "Chunks to return, 1 to 20. Default 5.",
"name": "limit",
"in": "query"
},
{
"schema": {
"type": "string",
"enum": [
"mcp-tool"
],
"description": "The surface making this call. The Arcmira MCP server sends mcp-tool so every unlock link in a gate attributes to the directory install. Omit from your own client."
},
"required": false,
"description": "The surface making this call. The Arcmira MCP server sends mcp-tool so every unlock link in a gate attributes to the directory install. Omit from your own client.",
"name": "src",
"in": "query"
}
],
"responses": {
"200": {
"description": "Success",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
},
"RateLimit-Limit": {
"$ref": "#/components/headers/RateLimit-Limit"
},
"RateLimit-Remaining": {
"$ref": "#/components/headers/RateLimit-Remaining"
},
"RateLimit-Reset": {
"$ref": "#/components/headers/RateLimit-Reset"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TranscriptSearchResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/InvalidRequest"
},
"401": {
"$ref": "#/components/responses/AuthenticationError"
},
"402": {
"$ref": "#/components/responses/QuotaExceeded"
},
"403": {
"$ref": "#/components/responses/PermissionError"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/ServerError"
},
"503": {
"description": "search_unavailable. Search is unavailable right now. Retry-After carries the wait; nothing was charged.",
"headers": {
"X-Request-Id": {
"$ref": "#/components/headers/X-Request-Id"
},
"X-Arcmira-Version": {
"$ref": "#/components/headers/X-Arcmira-Version"
},
"Retry-After": {
"$ref": "#/components/headers/Retry-After"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}