> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.sofer.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.sofer.ai/_mcp/server.

# Get Document Translation

GET https://api.sofer.ai/v1/documents/{document_id}/translations/{target_language}

Get the translation for a target language and style, including current status,
remaining billable words, estimated API cost, and translated content.

The service rebuilds the document's current paragraphs or pages and compares
their hashes with the hashes stored during translation. Changed source content
is returned as stale and becomes billable again when translation is requested.

Reference: https://docs.sofer.ai/api-reference/translate/get-document-translation

## Authentication

- `Authorization` header (bearer token, required) — Bearer authentication of the form `Bearer <token>`, where token is your auth token.

## Request

### Path parameters

- `document_id` (UUID, required) — Stable document ID.
- `target_language` (enum, required) — Target language used when the translation was created, or `auto` for automatic direction selection.
  - Allowed values: `auto`, `en`, `he`, `yi`

### Query parameters

- `translation_style` (string, optional) — Translation style ID. Built-ins are `default`, `learning_english` for an English target, and `sefer_hebrew` for a Hebrew target. Omit this to use `default`. Custom style IDs come from `/v1/translation-styles`.

## Response

### 200

- `document_id` (UUID, required) — Stable source document ID.
- `target_language` (enum, required) — Requested translation language. With `auto`, each segment reports its concrete language in its own `target_language` field.
  - Allowed values: `auto`, `en`, `he`, `yi`
- `translation_style` (string, required) — Translation style ID used for this independently stored target-language translation.
- `status` (string, required) — Overall translation status.
- `completed_segments` (integer, required) — Number of successfully translated paragraphs or pages.
- `failed_segments` (integer, required) — Number of failed paragraphs or pages.
- `source_word_count` (integer, required) — Total visible words across the document's current paragraphs or pages, including content that already has a current translation.
- `billable_word_count` (integer, required) — Words in missing, failed, forced, or stale segments that still need translation. Cached current segments are excluded, so this can be zero even when `source_word_count` is not.
- `estimated_api_cost_cents` (double, required) — Estimated API balance reservation for the current `billable_word_count`, in cents, at USD 0.25 per 1,000 words. For example, `25` means USD 0.25 and `250` means USD 2.50. This is an estimate of remaining work, not a historical invoice, and normally becomes zero after all current segments are translated.
- `segments` (list of DocumentTranslationSegment, required) — Paragraph- or page-level results for this target language and translation style.
- `total_segments` (integer, optional) — Total paragraphs or pages in the translation job.
- `created_at` (datetime, optional) — When the translation job was created.
- `updated_at` (datetime, optional) — When the translation job was last updated.
- `error` (string, optional) — Overall job error, if any.

## Errors

### 401 Authentication Error

Authentication error

### 404 Document Not Found

Document not found or not owned by the authenticated API user.

### 429 Rate Limit Error

Rate limit exceeded, or you have used up your quota

## Types

### DocumentTranslationSegment

- `segment_id` (string, required) — Stable paragraph or page ID used to pair source and translated content.
- `segment_index` (integer, required) — One-based paragraph or page order in the document.
- `source_hash` (string, required) — Hash of the exact source content used for this translation. It is compared with the current source hash to detect edits.
- `status` (string, required) — Segment translation status.
- `is_stale` (boolean, required) — True when the current source hash differs from `source_hash`; requesting translation again updates only stale or missing segments unless `force` is true.
- `source_text` (string, optional) — Exact visible source paragraph. OCR page responses may omit this because the page structure is represented in HTML.
- `source_language` (string, optional) — Detected source language.
- `target_language` (string, optional) — Translation target language.
- `start_time` (double, optional) — Source start time in seconds when the document is a transcription.
- `end_time` (double, optional) — Source end time in seconds when the document is a transcription.
- `speaker` (string, optional) — Speaker label when the document is a transcription.
- `content` (string, optional) — Sanitized translated HTML. HTML preserves paragraph direction, emphasis, source quotations, and OCR page layout that plain text would lose.
- `error` (string, optional) — Error message if this segment failed.

## Examples

**Response**

```json
{
  "document_id": "d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32",
  "target_language": "auto",
  "translation_style": "translation_style",
  "status": "status",
  "completed_segments": 1,
  "failed_segments": 1,
  "source_word_count": 1,
  "billable_word_count": 1,
  "estimated_api_cost_cents": 1.1,
  "segments": [
    {
      "segment_id": "segment_id",
      "segment_index": 1,
      "source_hash": "source_hash",
      "status": "status",
      "is_stale": true,
      "source_text": "source_text",
      "source_language": "source_language",
      "target_language": "target_language",
      "start_time": 1.1,
      "end_time": 1.1,
      "speaker": "speaker",
      "content": "content",
      "error": "error"
    },
    {
      "segment_id": "segment_id",
      "segment_index": 1,
      "source_hash": "source_hash",
      "status": "status",
      "is_stale": true,
      "source_text": "source_text",
      "source_language": "source_language",
      "target_language": "target_language",
      "start_time": 1.1,
      "end_time": 1.1,
      "speaker": "speaker",
      "content": "content",
      "error": "error"
    }
  ],
  "total_segments": 1,
  "created_at": "2024-01-15T09:30:00Z",
  "updated_at": "2024-01-15T09:30:00Z",
  "error": "error"
}
```

**SDK Code**

```python
import requests

url = "https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto"

headers = {"Authorization": "Bearer <apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto';
const options = {method: 'GET', headers: {Authorization: 'Bearer <apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <apiKey>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto")
  .header("Authorization", "Bearer <apiKey>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto', [
  'headers' => [
    'Authorization' => 'Bearer <apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <apiKey>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.sofer.ai/v1/documents/d5e9c84f-c2b2-4bf4-b4b0-7ffd7a9ffc32/translations/auto")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```