---
title: "Finalise a dictation captured live via Gladia"
method: POST
path: "/v1/dictation/finalize"
tags: ["Desktop"]
---

# Finalise a dictation captured live via Gladia

`POST /v1/dictation/finalize`

## Request

- Base URL: `https://api.quillhub.ai`
- URL: `https://api.quillhub.ai/v1/dictation/finalize`
- Auth: HTTP bearer

Takes a transcript already produced by Gladia (in AssemblyAI shape) and a previously-uploaded WAV key. Inserts a request row in TO_STRUCTURE state with kind='dictation'; the structurer will pick it up and run the light path. Skips the AssemblyAI transcriber entirely.

## Request body

- object
  - `device_id` string, required
  - `key` string, required: S3 key returned by /v1/desktop/recordings/presign. Must live under the caller's uploads/<userId>/ prefix.
  - `filename` string, required
  - `mime_type` string, nullable
  - `size_bytes` integer, required
  - `started_at` string, required: ISO-8601 UTC timestamp.
  - `duration_ms` integer, required
  - `poll_token` string: Signed token returned by POST /v1/dictation/live. Required for trial-funded dictation.
  - `language` string, nullable
  - `workspace_id` integer, nullable: Workspace to route this dictation into. When absent, a DB trigger falls back to the caller's default workspace — the entitlement gate resolves rights against that same effective value.
  - `assembly_raw_result` object, required: Transcript shaped like AssemblyAI's response. The desktop adapter converts Gladia's GET /v2/live/{id} payload into this shape so the structurer + the web's raw-mode renderer don't have to know the difference. NOTE: contents are user-supplied and stored verbatim — keep the structurer/renderer defensive.
    - `text` string, required
    - `words` object[], required
      - `text` string, required
      - `start` number, required
      - `end` number, required
      - `confidence` number
    - `audio_duration` number, nullable
    - `language_code` string, nullable

## Response `201`

Row created in TO_STRUCTURE.

- object
  - `request_id` string, required
  - `status` 'TO_STRUCTURE', required

## Other responses

- `400`: Key does not belong to caller.
- `401`: Unauthenticated.
- `402`: No minutes left and no active subscription.

---

[API](https://skmtc.dev/quillhub/apis/quillhub-public-api.md) · [All operations](https://skmtc.dev/quillhub/apis/quillhub-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/quillhub/apis/quillhub-public-api/revisions/5bd42ee9d967?raw)
