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

# Get Transcription

> Returns the current status and (once complete) the transcript for a `docId` returned by `POST /api/createTranscription`. Use this as an alternative to webhook delivery when hosting a public webhook receiver isn't an option (for example, when the consumer is behind Cloudflare with IP-whitelisting requirements that the Xosum Cloud Functions infrastructure can't satisfy).

**Recommended polling cadence:** every 5–10 seconds per in-flight job. Most `single_voice` jobs finish within seconds; `phone_call` jobs may take a few minutes.

**Rate limit:** 60 requests per minute per API key, fixed wall-clock-minute window. A `429` response includes a `Retry-After` header (seconds) indicating when the next window opens — sleep at least that long before retrying.


Poll for the status and result of a transcription job by its `docId`. This is the alternative to receiving the result via [your webhook](/api-reference/webhooks/transcription) — useful when you can't host a publicly reachable receiver (for example, when your network requires IP whitelisting that the Xosum Cloud Functions infrastructure can't provide).

## Polling pattern

Most jobs finish in seconds (`single_voice`) to a few minutes (`phone_call`). Poll every **5–10 seconds** until `status` becomes `transcribed` or `failed`, then stop.

```bash theme={null}
curl -H "Authorization: Bearer $XOSUM_API_KEY" \
  "https://app.xosum.am/api/getTranscription?docId=$DOC_ID"
```

```python Python theme={null}
import os, time, requests

API_KEY = os.environ["XOSUM_API_KEY"]
doc_id = "XYZ123"

while True:
    r = requests.get(
        "https://app.xosum.am/api/getTranscription",
        params={"docId": doc_id},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    if r.status_code == 429:
        time.sleep(int(r.headers.get("Retry-After", "5")))
        continue
    r.raise_for_status()
    body = r.json()
    if body["status"] in ("transcribed", "failed"):
        print(body)
        break
    time.sleep(7)
```

## Rate limit

* **60 requests per minute per API key**, fixed wall-clock-minute window — the counter resets at the top of each minute, not as a rolling window.
* On a `429` response, the `Retry-After` header tells you how many seconds until the next window opens. Sleep for at least that long before retrying.
* The recommended 5–10 second cadence per in-flight job stays well under the limit for a handful of parallel jobs.

## Response field availability

The base fields (`docId`, `status`, `createdAt`, `type`, `duration`, `metadata`) are always returned. The fields below appear only once `status` reaches a terminal value:

| When `status` is | Additional fields                                      |
| ---------------- | ------------------------------------------------------ |
| `transcribed`    | `transcription`, `title`, `resolution`, `languageCode` |
| `failed`         | `error`                                                |

The `transcription` field contains plain text when `type` is `single_voice` and diarized text with inline `Խոսնակ 1:` / `Խոսնակ 2:` speaker labels when `type` is `phone_call`.


## OpenAPI

````yaml GET /api/getTranscription
openapi: 3.0.3
info:
  title: Xosum.am API
  description: >
    The Xosum.am API enables business customers to upload audio for
    transcription and receive results via webhook. All transcription results are
    also accessible via the web interface at
    [https://app.xosum.am](https://app.xosum.am).

    API access is exclusive to Business plan users. Authentication is handled
    via Bearer API keys.
  version: 1.0.0
servers:
  - url: https://app.xosum.am
    description: Production API server
security:
  - BearerAuth: []
paths:
  /api/getTranscription:
    get:
      tags:
        - Transcription
      summary: Poll the status and result of a transcription job
      description: >
        Returns the current status and (once complete) the transcript for a
        `docId` returned by `POST /api/createTranscription`. Use this as an
        alternative to webhook delivery when hosting a public webhook receiver
        isn't an option (for example, when the consumer is behind Cloudflare
        with IP-whitelisting requirements that the Xosum Cloud Functions
        infrastructure can't satisfy).


        **Recommended polling cadence:** every 5–10 seconds per in-flight job.
        Most `single_voice` jobs finish within seconds; `phone_call` jobs may
        take a few minutes.


        **Rate limit:** 60 requests per minute per API key, fixed
        wall-clock-minute window. A `429` response includes a `Retry-After`
        header (seconds) indicating when the next window opens — sleep at least
        that long before retrying.
      operationId: getTranscription
      parameters:
        - name: docId
          in: query
          required: true
          schema:
            type: string
          description: The document ID returned by `POST /api/createTranscription`.
      responses:
        '200':
          description: Current status and (once complete) the transcript.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetTranscriptionResponse'
        '400':
          description: Bad request — missing `docId` query parameter.
        '401':
          description: Unauthorized — missing or invalid API key.
        '404':
          description: >
            Recording not found. Also returned when the `docId` exists but
            belongs to a different user — this is intentional, to avoid leaking
            cross-tenant existence.
        '405':
          description: Method not allowed. Use `GET`.
        '429':
          description: Rate limit exceeded. The response includes a `Retry-After` header.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the next rate-limit window opens.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'
        '500':
          description: Server error.
      security:
        - BearerAuth: []
components:
  schemas:
    GetTranscriptionResponse:
      type: object
      description: >
        Polling response for a transcription job. The base fields are always
        returned; the additional fields below are populated only once `status`
        reaches a terminal value (`transcribed` or `failed`).
      required:
        - docId
        - status
      properties:
        docId:
          type: string
          description: The same ID returned by `POST /api/createTranscription`.
        status:
          type: string
          enum:
            - uploading
            - processing
            - converting
            - transcribed
            - failed
          description: >
            Current job state. Terminal states are `transcribed` and `failed`;
            clients should stop polling once one is reached.
        createdAt:
          type: string
          format: date-time
          nullable: true
          description: ISO-8601 timestamp of when the job was created.
        type:
          type: string
          enum:
            - single_voice
            - phone_call
          nullable: true
          description: Echoes the `type` passed when the job was created.
        duration:
          type: number
          nullable: true
          description: >-
            Audio duration in seconds. Populated after the recording is
            processed.
        metadata:
          type: object
          description: The same metadata object passed to `POST /api/createTranscription`.
        transcription:
          type: string
          nullable: true
          description: >
            Present when `status` is `transcribed`. For `type: phone_call`, the
            text is diarized with inline `Խոսնակ 1:` / `Խոսնակ 2:` speaker
            labels. For `type: single_voice`, the text is plain with no labels.
        title:
          type: string
          nullable: true
          description: AI-generated short title. Present when `status` is `transcribed`.
        resolution:
          type: string
          nullable: true
          description: >-
            AI-generated one-paragraph summary. Present when `status` is
            `transcribed`.
        languageCode:
          type: string
          nullable: true
          description: >-
            BCP-47 language code of the detected language, e.g. `hy-AM`. Present
            when `status` is `transcribed`.
        error:
          type: string
          nullable: true
          description: Human-readable error message. Present when `status` is `failed`.
    RateLimitError:
      type: object
      properties:
        error:
          type: string
          example: Rate limit exceeded. Max 60 requests per minute.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key

````