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

NameLocationDescription
q (required)queryOne topic or phrase. Do not concatenate unrelated names; make one call per topic.
channel_idsqueryComma-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.
channelqueryAlias of channel_ids for code-mode clients; the union of both is the scope.
entity_idsqueryComma-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.
aboutqueryComma-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.
byqueryComma-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.
kindqueryComma-separated passage classes: sponsored, organic, mention. Combine with about to read what was said about a brand in ad reads or in organic talk.
afterqueryOnly 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.
beforequeryOnly 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.
sourcequeryRestrict to one transcript source class. arcmira_premium on a plan without Premium transcripts is refused with filter_requires_paid.
limitqueryChunks to return, 1 to 20. Default 5.
srcqueryThe 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"
          }
        }
      }
    }
  }
}