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

# Apply a flat rewrite map to the segments' `speaker_label`...



## OpenAPI

````yaml /openapi.json post /admin/jobs/transcriptions/{job_id}/relabel-speakers
openapi: 3.0.0
info:
  title: Kair Voice
  version: '1.0'
servers:
  - url: http://0.0.0.0:8000/api
security: []
tags:
  - name: Admin
  - name: ApiKey
  - name: Auth
  - name: Concerns
  - name: Device
  - name: Graph
  - name: Health
  - name: Job
  - name: Session
  - name: Workshop
  - name: Workspace
paths:
  /admin/jobs/transcriptions/{job_id}/relabel-speakers:
    post:
      tags:
        - Admin
      summary: Apply a flat rewrite map to the segments' `speaker_label`...
      operationId: post-admin-jobs-transcriptions-job-id-relabel-speakers
      parameters:
        - name: job_id
          schema:
            type: string
            format: uuid
          in: path
          required: true
          deprecated: false
          explode: true
      requestBody:
        content:
          application/json; charset=utf-8:
            schema:
              $ref: '#/components/schemas/AdminTranscriptionRelabelRequest'
        required: true
      responses:
        '200':
          description: ''
          content:
            application/json; charset=utf-8:
              schema:
                $ref: '#/components/schemas/AdminTranscriptionDetail'
        '401':
          description: ''
          content:
            application/json; charset=utf-8:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: ''
          content:
            application/json; charset=utf-8:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: ''
          content:
            application/json; charset=utf-8:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    AdminTranscriptionRelabelRequest:
      type: object
      title: AdminTranscriptionRelabelRequest
      description: |-
        Body for `POST /admin/jobs/transcriptions/:job_id/relabel-speakers`.

        Two complementary rewrite mechanisms, applied in order:

        1. `relabels` — flat rewrite map applied to every segment whose
        `speaker_label` matches a key. To merge S4 into S1 AND rename S1 to
        "Moderator", the client should send both rules already resolved:
        `{"S4": "Participant", "S1": "Moderator"}`. This is the bulk path
        and is the only one that propagates to Neo4j `:SpeakerIdentity`.

        2. `segment_overrides` — per-segment fixes for cases where one
        misclustered segment shouldn't drag its whole speaker group with it.
        Applied AFTER `relabels`, so the operator can do "merge S1+S2 into
        Moderator AND override segment X to be Participant" in one save.
        Single-segment moves are intentionally Postgres-only — too small a
        sample to meaningfully shift centroid clusters in Neo4j.
      required:
        - relabels
      properties:
        relabels:
          type: object
          additionalProperties:
            type: string
        segment_overrides:
          type: array
          default: []
          items:
            $ref: '#/components/schemas/AdminTranscriptionSegmentOverride'
    AdminTranscriptionDetail:
      type: object
      title: AdminTranscriptionDetail
      required:
        - id
        - workspace_id
        - status
        - progress
        - error
        - segment_count
        - segments
        - created_at
        - content_visible
        - elevation_required
        - session_was_deleted
      properties:
        id:
          type: string
          description: '`jobs.id` (same id the admin list returns).'
        transcription_id:
          type: string
          description: '`transcriptions.id` — the row that backs this job''s output.'
        session_id:
          type: string
        workspace_id:
          type: string
        status:
          type: string
        progress:
          type: number
          format: float
        error:
          type: string
        detected_language:
          type: string
        forced_language:
          type: string
        diarisation_model_version:
          type: string
        transcription_text:
          type: string
        segment_count:
          type: integer
          format: int32
        speaker_count:
          type: integer
          format: int32
        duration_ms:
          type: integer
          format: int32
        avg_confidence:
          type: number
          format: float
        segments:
          type: array
          items:
            $ref: '#/components/schemas/AdminTranscriptionSegment'
        created_at:
          type: string
        completed_at:
          type: string
        content_visible:
          type: boolean
          description: >-
            True iff `transcription_text` and segment `text` are populated
            normally.

            False means the admin is not a native member of this session AND has

            not elevated; content fields contain a placeholder & the UI should

            show the "View content (audited)" banner.
        elevation_required:
          type: boolean
          description: |-
            True iff the admin needs to POST `/admin/content-elevate` w/ a
            reason to see content. False either when the admin has access
            natively (member/owner/share) or has already elevated.
        session_was_deleted:
          type: boolean
          description: |-
            Set when this transcription's content was redacted via session
            deletion (i.e. transcription_text contains a `[redacted-…]`
            placeholder). Lets the UI show a "Deleted session" badge instead
            of a confused "Workspace-level" one.
        deletion_event_kind:
          type: string
          description: |-
            When `session_was_deleted` is true, this is the matching
            `gdpr_log.event_kind` — e.g. `session_deleted_by_owner` or
            `account_erasure_session_redacted`. Lets the UI render an honest
            "why" without exposing actual user identifiers. `None` when no
            matching gdpr_log row was found (older deletions before the audit
            pipeline existed; or non-redacted transcriptions).
    ErrorResponse:
      type: object
      title: ErrorResponse
      required:
        - success
        - message
      properties:
        success:
          type: boolean
        message:
          type: string
    AdminTranscriptionSegmentOverride:
      type: object
      title: AdminTranscriptionSegmentOverride
      required:
        - segment_id
        - new_speaker_label
      properties:
        segment_id:
          type: string
          format: uuid
        new_speaker_label:
          type: string
    AdminTranscriptionSegment:
      type: object
      title: AdminTranscriptionSegment
      required:
        - id
        - start_ms
        - end_ms
        - text
      properties:
        id:
          type: string
        start_ms:
          type: integer
          format: int32
        end_ms:
          type: integer
          format: int32
        speaker_label:
          type: string
        text:
          type: string
        confidence:
          type: number
          format: float

````