> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arcmira.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Arcmira has three API capabilities: Search (entities, mentions, appearances, commercial intelligence), Monitors (trackers plus alert delivery), and Transcripts (read, generate, correct). Community Review is the cross-surface correction layer.
> Discover pages at https://docs.arcmira.com/llms.txt, then fetch the matching page's .md export. Each capability has a self-contained '<capability> for coding agents' page; prefer it.
> Auth: Authorization: Bearer arc_sk_... or x-api-key: arc_sk_... (x-api-key wins if both are sent). Never put keys in browser code. Check GET /v1/me for tier, scopes, and remaining rows before metered pulls.
> Search: resolve names with GET /v1/entities/lookup and pin ent_* IDs before pulling metered rows. Only person entities have appearances. Mention and recommendation rows carry canonical numeric timestamps in start_seconds/end_seconds (integer seconds; 0 means full episode); the MM:SS string fields are deprecated. Commercial routes need Pro+ tier AND the recommendations:read scope and bill 10 rows per row.
> Monitors: a tracker watches one entity; a monitor groups trackers with shared delivery (email, Slack, HMAC-signed webhooks). Create trackers with POST /v1/trackers, then attach by id: POST /v1/monitors/{id}/trackers { trackerIds: [...] }. Each fired alert occurrence debits 100 rows. Poll GET /v1/monitors/{id}/alerts?n= for recent deliveries. Send Idempotency-Key on every POST/PATCH.
> Transcripts: switch on the access field (unlocked, locked, premium_pending, not_transcribed, unauthenticated). Honor Retry-After when polling POST /v1/transcriptions jobs. Corrections (POST /v1/videos/{video_id}/corrections; kinds line_edit, speaker_reassign, speaker_identify, add_person, entity_tag, segment_rewrite) cost 0 rows; anchored kinds need revision + anchor.contentHash (djb2 base-36); handle 409 (re-anchor) and 412 (expectedSeq). segment_rewrite replaces an inclusive segment range with new segments (empty replacements array deletes; timestamps repaired server-side).
> Community Review is free (0 rows) and surface-typed: POST /v1/feedback with a type matching the surface you called, the reproducing query, and corrections targeting public IDs (ent_*, men_*, com_*). Nothing auto-applies. Do not send untyped notes.
> Errors: switch on error.code, follow doc_url, quote X-Request-Id to support. Honor Retry-After on 429. Retries of POST/PATCH must reuse the same Idempotency-Key; replays return Idempotency-Replayed: true.

# Get a video transcript

> Returns segments, speakers, and entity annotations for a video. Transcript surfaces are premium-only. Access requires a permanent per-video unlock (paid tiers). Cost is always quoted in rows and 15-minute blocks: 75 rows per 15-minute block of video, minimum one block. `access` states: `unlocked` (full premium transcript), `locked` (premium transcript exists — ~5 teaser segments + `meta.quote`; pass `?unlock=true` to debit the quoted rows and receive the full transcript in the same request), `premium_pending` (a preliminary analysis exists but premium transcription has not run — the payload carries ONLY `detected` entity-type counts `{ people, organizations, products, topics }` plus the quote; run the premium analysis via POST /v1/transcriptions; `unlock=true` is ignored in this state), `not_transcribed` (not in the index — submit via POST /v1/transcriptions). Unlocks are permanent — subsequent reads are free, and an unlock bought before the premium transcript existed makes the later premium generation free. The response `meta.revision` is an opaque id for the served transcript + approved-correction state; echo it back when submitting corrections.



## OpenAPI

````yaml /openapi/arcmira-v1.json get /v1/transcripts/{video_id}
openapi: 3.1.0
info:
  title: Arcmira API
  version: 1.0.0
  contact:
    name: Arcmira
    url: https://arcmira.com
servers:
  - url: https://api.arcmira.com
security: []
paths:
  /v1/transcripts/{video_id}:
    get:
      tags:
        - Transcripts
      summary: Get a video transcript
      description: >-
        Returns segments, speakers, and entity annotations for a video.
        Transcript surfaces are premium-only. Access requires a permanent
        per-video unlock (paid tiers). Cost is always quoted in rows and
        15-minute blocks: 75 rows per 15-minute block of video, minimum one
        block. `access` states: `unlocked` (full premium transcript), `locked`
        (premium transcript exists — ~5 teaser segments + `meta.quote`; pass
        `?unlock=true` to debit the quoted rows and receive the full transcript
        in the same request), `premium_pending` (a preliminary analysis exists
        but premium transcription has not run — the payload carries ONLY
        `detected` entity-type counts `{ people, organizations, products, topics
        }` plus the quote; run the premium analysis via POST /v1/transcriptions;
        `unlock=true` is ignored in this state), `not_transcribed` (not in the
        index — submit via POST /v1/transcriptions). Unlocks are permanent —
        subsequent reads are free, and an unlock bought before the premium
        transcript existed makes the later premium generation free. The response
        `meta.revision` is an opaque id for the served transcript +
        approved-correction state; echo it back when submitting corrections.
      operationId: get_transcript
      parameters:
        - schema:
            type: string
            enum:
              - 'true'
            description: >-
              Explicit purchase action: debits 75 rows per 15-minute block and
              grants the permanent per-video unlock in the same request. Without
              it, locked viewers receive only the teaser segments.
          required: false
          description: >-
            Explicit purchase action: debits 75 rows per 15-minute block and
            grants the permanent per-video unlock in the same request. Without
            it, locked viewers receive only the teaser segments.
          name: unlock
          in: query
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptResponse'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
        '401':
          description: Authentication error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
        '402':
          description: >-
            Not enough rows remaining to unlock. Note: this response uses a bare
            { error, quote } body rather than the standard v1 error envelope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TranscriptPaymentRequired'
        '403':
          description: Permission error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
        '404':
          description: Not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
        '500':
          description: Server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      type:
                        type: string
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      doc_url:
                        type: string
                      request_id:
                        type: string
                    required:
                      - type
                      - code
                      - message
                      - doc_url
                      - request_id
                required:
                  - error
      security:
        - bearerAuth: []
        - apiKeyAuth: []
components:
  schemas:
    TranscriptResponse:
      type: object
      properties:
        video:
          $ref: '#/components/schemas/TranscriptVideo'
        access:
          type: string
          enum:
            - unlocked
            - locked
            - premium_pending
            - not_transcribed
            - unauthenticated
          description: >-
            Access state. Values: unlocked (full premium transcript in this
            payload), locked (a premium transcript exists; you receive only ~5
            teaser segments — pass unlock=true to debit the quoted rows and
            receive the full transcript), premium_pending (a preliminary
            analysis exists but the premium transcript has not been generated;
            payload carries only detected entity-type counts plus the quote —
            submit POST /v1/transcriptions to generate), not_transcribed (video
            is not in the index; submit POST /v1/transcriptions),
            unauthenticated (no authenticated caller; teaser only).
        segments:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptSegment'
          description: >-
            Transcript segments. Full list when unlocked; first ~5 teaser
            segments when locked/unauthenticated; empty for premium_pending and
            not_transcribed.
        speakers:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptSpeaker'
          description: >-
            Diarized speakers. Filtered to teaser segments when locked; empty
            when no diarized transcript exists.
        annotations:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptAnnotation'
          description: >-
            Entity annotations as character spans inside segment text.
            Restricted to teaser segments when locked.
        detected:
          type: object
          properties:
            people:
              type: integer
            organizations:
              type: integer
            products:
              type: integer
            topics:
              type: integer
          required:
            - people
            - organizations
            - products
            - topics
          description: >-
            Distinct-entity counts by type from the preliminary analysis. Only
            present when access is premium_pending (deliberately minimal: no
            names, ids, or timestamps).
        edits:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
                description: Edit row id. Use it to withdraw the edit.
              segmentIndex:
                type: integer
              originalText:
                type: string
              correctedText:
                type: string
              status:
                type: string
                description: Review status, e.g. "pending".
              mine:
                type: boolean
                description: 'Always true: only your own pending edits are returned here.'
            required:
              - id
              - segmentIndex
              - originalText
              - correctedText
              - status
              - mine
          description: Your own pending line edits. Only present when access is unlocked.
        speakerIdentifications:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
                description: Identification row id. Use it to withdraw the identification.
              speakerId:
                type: integer
              entityId:
                type:
                  - integer
                  - 'null'
              entityName:
                type:
                  - string
                  - 'null'
              status:
                type: string
                description: Review status, e.g. "pending".
            required:
              - id
              - speakerId
              - entityId
              - entityName
              - status
          description: >-
            Your own pending speaker identifications. Only present when access
            is unlocked.
        speakerEdits:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
                description: Speaker edit row id. Use it to withdraw the edit.
              seq:
                type:
                  - integer
                  - 'null'
                description: >-
                  Per-video sequence number the edit was submitted with. Null
                  for one-off submissions.
              editType:
                type: string
                description: Edit kind, e.g. "reassign" or "split".
              selection:
                type: object
                properties:
                  startIndex:
                    type: integer
                  startChar:
                    type:
                      - integer
                      - 'null'
                  endIndex:
                    type:
                      - integer
                      - 'null'
                  endChar:
                    type:
                      - integer
                      - 'null'
                required:
                  - startIndex
                  - startChar
                  - endIndex
                  - endChar
              target:
                type: object
                properties:
                  kind:
                    type: string
                    description: >-
                      Target kind. Values: existing (an existing speaker id),
                      new (a newly minted speaker), role (a non-person voice
                      role).
                  speakerId:
                    type:
                      - integer
                      - 'null'
                  label:
                    type:
                      - string
                      - 'null'
                  role:
                    type:
                      - string
                      - 'null'
                required:
                  - kind
                  - speakerId
                  - label
                  - role
              status:
                type: string
                description: Review status, e.g. "pending".
            required:
              - id
              - seq
              - editType
              - selection
              - target
              - status
          description: >-
            Your own pending speaker reassigns/splits for the current revision.
            Only present when access is unlocked.
        entityTags:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
                description: Entity tag row id. Use it to withdraw the tag.
              seq:
                type:
                  - integer
                  - 'null'
                description: >-
                  Per-video sequence number the tag was submitted with. Null for
                  one-off submissions.
              segmentIndex:
                type: integer
              charStart:
                type: integer
              charEnd:
                type: integer
              selectedText:
                type:
                  - string
                  - 'null'
                description: The text that was selected, for client-side re-anchoring.
              entity:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  slug:
                    type: string
                  type:
                    type: string
                required:
                  - id
                  - name
                  - slug
                  - type
              status:
                type: string
                description: Review status, e.g. "pending".
            required:
              - id
              - seq
              - segmentIndex
              - charStart
              - charEnd
              - selectedText
              - entity
              - status
          description: Your own pending entity tags. Only present when access is unlocked.
        segmentRewrites:
          type: array
          items:
            type: object
            properties:
              id:
                type: integer
                description: Rewrite row id. Use it to withdraw the rewrite.
              seq:
                type:
                  - integer
                  - 'null'
                description: >-
                  Per-video sequence number the rewrite was submitted with. Null
                  for one-off submissions.
              startIndex:
                type: integer
                description: First source segment index (inclusive).
              endIndex:
                type: integer
                description: Last source segment index (inclusive).
              replacements:
                type: array
                items:
                  type: object
                  properties:
                    text:
                      type: string
                    speaker:
                      type: integer
                    start:
                      type: number
                      description: >-
                        Explicit start pin in seconds, when the submitter set
                        one.
                    end:
                      type: number
                      description: Explicit end pin in seconds, when the submitter set one.
                  required:
                    - text
                description: Replacement segments. Empty array means the range is deleted.
              status:
                type: string
                description: Review status, e.g. "pending".
            required:
              - id
              - seq
              - startIndex
              - endIndex
              - replacements
              - status
          description: >-
            Your own pending segment rewrites for the current revision. Re-apply
            them (with pending speaker edits, in seq order) to rebuild your
            projection. Only present when access is unlocked.
        meta:
          type: object
          properties:
            diarized:
              type: boolean
              description: True when the transcript has speaker diarization.
            locked:
              type: boolean
              description: True for every access state except unlocked.
            revision:
              type: string
              description: >-
                Opaque id for the served transcript + approved-correction state.
                Echo it back when submitting corrections. Absent until a premium
                transcript exists (not_transcribed / premium_pending).
            quote:
              $ref: '#/components/schemas/TranscriptQuote'
            overLimit:
              type: boolean
              description: >-
                Only present (true) when an unlock=true purchase in this request
                consumed the rest of the included row allocation.
            devPreview:
              type: boolean
              description: >-
                Local development only: true when a non-premium transcript is
                served to an unlock holder under wrangler dev. Never present in
                production.
            usageLimit:
              type: object
              properties:
                message:
                  type: string
                ctaLabel:
                  type: string
                ctaHref:
                  type: string
              required:
                - message
                - ctaLabel
                - ctaHref
              description: >-
                Only present for authenticated callers whose account is over its
                usage limit; describes the blocking state before any spend
                action.
          required:
            - diarized
            - locked
            - quote
      required:
        - video
        - access
        - segments
        - speakers
        - annotations
        - meta
    TranscriptPaymentRequired:
      type: object
      properties:
        error:
          type: string
          description: Human-readable reason the unlock could not be charged.
        quote:
          allOf:
            - $ref: '#/components/schemas/TranscriptQuote'
            - description: The quote that could not be afforded.
      required:
        - error
        - quote
    TranscriptVideo:
      type:
        - object
        - 'null'
      properties:
        videoId:
          type: string
          description: YouTube video id (11 characters).
        title:
          type: string
          description: Video title. Empty string when unknown.
        channelName:
          type: string
          description: Channel name. Empty string when unknown.
        channelId:
          type: string
          description: YouTube channel id. Empty string when unknown.
        publishedAt:
          type: string
          description: Video publish timestamp. Empty string when unknown.
        durationSeconds:
          type: number
          description: >-
            Video duration in SECONDS. 0 when the duration could not be
            determined.
        viewCount:
          type: integer
          description: View count at index time. Absent when never fetched.
      required:
        - videoId
        - title
        - channelName
        - channelId
        - publishedAt
        - durationSeconds
      description: >-
        Video metadata. Null only when the video is not in the index and no
        public metadata could be fetched.
    TranscriptSegment:
      type: object
      properties:
        index:
          type: integer
          description: 0-based segment index. Corrections anchor on this index.
        start:
          type: number
          description: >-
            Segment start in SECONDS from the beginning of the video (2 decimal
            places).
        end:
          type: number
          description: >-
            Segment end in SECONDS from the beginning of the video (2 decimal
            places).
        text:
          type: string
          description: Segment display text.
        speaker:
          type: integer
          description: >-
            Diarization speaker id (see speakers[]). Absent for non-diarized
            transcripts.
      required:
        - index
        - start
        - end
        - text
    TranscriptSpeaker:
      type: object
      properties:
        id:
          type: integer
          description: Stable diarization speaker id referenced by segments[].speaker.
        label:
          type: string
          description: Display label, e.g. "Speaker 1" or the diarizer's name guess.
        role:
          type: string
          description: Diarizer role guess, e.g. "host". Absent when not inferred.
        confidence:
          type: string
          description: >-
            Diarizer confidence label for the role/name guess. Absent when not
            provided.
        voiceRole:
          type: string
          description: >-
            Non-person voice role from an approved speaker edit. Values: clip
            (audio clip played in the video), other (other non-person audio).
            Absent for normal speakers.
        entity:
          type: object
          properties:
            id:
              type: integer
              description: Raw integer entity id of the identified person.
            name:
              type: string
              description: Person name.
            slug:
              type: string
              description: Person URL slug.
          required:
            - id
            - name
            - slug
          description: >-
            Identified person entity. Present when the speaker has an approved
            identification (or the caller's own pending one).
      required:
        - id
        - label
    TranscriptAnnotation:
      type: object
      properties:
        segmentIndex:
          type: integer
          description: Segment the annotation belongs to.
        charStart:
          type: integer
          description: Start character offset within the segment text.
        charEnd:
          type: integer
          description: End character offset (exclusive) within the segment text.
        entityId:
          type: integer
          description: >-
            Raw integer entity id. Use /v1/entities/cards for batched display
            metadata.
        entityType:
          type: string
          description: >-
            Entity type. Values: person (an individual), organization (a company
            or institution; legacy rows may read company or brand), product (a
            product or service), topic (a subject or theme), channel (a media
            source such as a YouTube channel), unknown (type was never
            classified).
        name:
          type: string
          description: Canonical entity name.
        slug:
          type: string
          description: Entity URL slug.
      required:
        - segmentIndex
        - charStart
        - charEnd
        - entityId
        - entityType
        - name
        - slug
    TranscriptQuote:
      type:
        - object
        - 'null'
      properties:
        quarters:
          type: integer
          description: Number of 15-minute blocks in the video, ceiling'd, minimum 1.
        rows:
          type: integer
          description: 'Total unlock cost in rows: 75 rows per 15-minute block.'
      required:
        - quarters
        - rows
      description: >-
        Unlock cost quote in rows and 15-minute blocks. Null when the video
        duration could not be determined.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: arc_sk_*
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````