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

# Paid text: closed until the first dub is charged

> Why the transcript of a new Rask API project answers 409 dub_payment_required, which operations are closed, and how a dub opens them.

Transcription and translation have no price of their own in this API: **the dub pays for the text.** On a project created through v3, the transcript, segments, versions and subtitles stay closed until a dub of that project has been charged.

A closed operation answers 409 [`dub_payment_required`](https://docs.api.rask.ai/errors/dub_payment_required). Subtitle outputs report it too, as `available: false` with `unavailable_reason: dub_payment_required`.

## Why there is no free preparation

A project dubs by itself after translation. `auto_dub` defaults to `true`, and `auto_dub: false` answers 403 [`prepare_mode_not_enabled`](https://docs.api.rask.ai/errors/prepare_mode_not_enabled): a project without the auto-dub is not available. To choose voices before the dub is paid, send `speaker_voices` when you create the project.

[createProject](https://docs.api.rask.ai/operations/createProject.md) also checks the money up front. A balance that cannot cover the auto-dub estimate answers 402 [`insufficient_balance`](https://docs.api.rask.ai/errors/insufficient_balance), and a price cap (`expected_cost_minutes`) below the current total answers 409 [`cost_changed`](https://docs.api.rask.ai/errors/cost_changed). [createProjectCopies](https://docs.api.rask.ai/operations/createProjectCopies.md) does the same. The text of each copy opens separately, as the table below says.

## How it opens

Usually you do nothing. The auto-dub is charged when translation ends, and the text opens with that charge.

| What happens | Does the text open? |
| - | - |
| The auto-dub is charged | Yes |
| [createDub](https://docs.api.rask.ai/operations/createDub.md) is charged | Yes |
| The dub stage of a [localization run](https://docs.api.rask.ai/v3/recipes/localization-run.md) is charged | Yes |
| The project uses a free dubbing variant (`free_dubbing`), so its dub costs 0 | Open from the start |
| A copy in its source's target language and variant, of a source whose dub was charged | Open from the start: the copy reuses that dub |
| A copy in its source's target language and variant, of a source not dubbed yet | Not by itself: such a copy has no auto-dub, so [createDub](https://docs.api.rask.ai/operations/createDub.md) opens it |
| [generateSegments](https://docs.api.rask.ai/operations/generateSegments.md) is charged | **No.** It voices chosen lines and does not open the text |
| The only dub charge is refunded, because the dub failed | **It closes again** |

## If the auto-dub was skipped

The balance or the price can change between the request and the moment translation ends. Then the auto-dub is skipped, nothing is charged, and the text stays closed: `auto_dub.state` is `skipped`, and `auto_dub.skipped_reason` is `insufficient_balance` or `cost_changed`. The reason is null
when the dub could not start for another reason, for example because the key that created the project was revoked.

To open it, add minutes if needed, then estimate the dub. When its `total_minutes` is within the price cap the project was
created with (`auto_dub.max_minutes`), send it as `expected_cost_minutes`, with an `Idempotency-Key` you save first and send again on a retry. When it is
higher, the skip is what kept the higher price from being charged: ask whoever accepted the first price before you dub.
In the example below, the estimate's `total_minutes` is 1.

```typescript TypeScript theme={null}
const { data: estimate } = await rask.dubbing.estimateDub({ path: { project_id: projectId }, body: {} });

const { data: job } = await rask.dubbing.createDub({
  path: { project_id: projectId },
  body: { expected_cost_minutes: 1 },
  idempotencyKey: dubKey,
});
```

```python Python theme={null}
estimate = client.dubbing.estimate_dub(project_id)

job = client.dubbing.create_dub(project_id, expected_cost_minutes=1, idempotency_key=dub_key)
```

```go Go theme={null}
estimate, err := client.Dubbing.EstimateDub(ctx, projectID, &api.EstimateDubRequest{})
if err != nil {
	return err
}

job, err := client.Dubbing.CreateDub(ctx, projectID, api.CreateDubRequest{
	ExpectedCostMinutes: 1,
}, rask.WithIdempotencyKey(dubKey))
if err != nil {
	return err
}
```

```java Java theme={null}
Estimate estimate = rask.dubbing().estimateDub(projectId, EstimateDubRequest.builder().build()).data();

Job job = rask.dubbing().createDub(
        projectId,
        CreateDubRequest.builder().expectedCostMinutes(1).build(),
        RequestOptions.builder().idempotencyKey(dubKey).build()).data();
```

```php PHP theme={null}
$estimate = $rask->dubbing->estimateDub($projectId, []);

$job = $rask->dubbing->createDub($projectId, ['expected_cost_minutes' => 1], ['idempotency_key' => $dubKey]);
```

```bash cURL theme={null}
curl -X POST "https://api.rask.ai/v3/projects/$PROJECT_ID/dub/estimate" \
  -H "Authorization: Bearer $RASK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

DUB_KEY=$(uuidgen)
curl -X POST "https://api.rask.ai/v3/projects/$PROJECT_ID/dub" \
  -H "Authorization: Bearer $RASK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $DUB_KEY" \
  -d '{"expected_cost_minutes": 1}'
```

A trial project cannot do this. It is dubbed only once, automatically, so [createDub](https://docs.api.rask.ai/operations/createDub.md) answers 403 [`trial_project_dub_not_allowed`](https://docs.api.rask.ai/errors/trial_project_dub_not_allowed). Create a new project instead.

## What is closed and what stays open

| Closed until a dub is charged | Stays open |
| - | - |
| [getTranscript](https://docs.api.rask.ai/operations/getTranscript.md) | [getProject](https://docs.api.rask.ai/operations/getProject.md), apart from the subtitle outputs |
| [listSegments](https://docs.api.rask.ai/operations/listSegments.md), [getSegment](https://docs.api.rask.ai/operations/getSegment.md) | [listProjectOutputs](https://docs.api.rask.ai/operations/listProjectOutputs.md), apart from the subtitle outputs |
| [createSegment](https://docs.api.rask.ai/operations/createSegment.md), [updateSegment](https://docs.api.rask.ai/operations/updateSegment.md), [deleteSegment](https://docs.api.rask.ai/operations/deleteSegment.md) | [listSpeakers](https://docs.api.rask.ai/operations/listSpeakers.md), [getSpeaker](https://docs.api.rask.ai/operations/getSpeaker.md), [updateSpeakerVoice](https://docs.api.rask.ai/operations/updateSpeakerVoice.md) |
| [splitSegment](https://docs.api.rask.ai/operations/splitSegment.md), [mergeSegments](https://docs.api.rask.ai/operations/mergeSegments.md), [selectTranslationVariant](https://docs.api.rask.ai/operations/selectTranslationVariant.md) | [listProjectVoices](https://docs.api.rask.ai/operations/listProjectVoices.md), [listVoices](https://docs.api.rask.ai/operations/listVoices.md) |
| [retranslateSegments](https://docs.api.rask.ai/operations/retranslateSegments.md), [importTranscript](https://docs.api.rask.ai/operations/importTranscript.md) | [estimateDub](https://docs.api.rask.ai/operations/estimateDub.md), [createDub](https://docs.api.rask.ai/operations/createDub.md) |
| [getProjectSubtitles](https://docs.api.rask.ai/operations/getProjectSubtitles.md) | [estimateLocalization](https://docs.api.rask.ai/operations/estimateLocalization.md), [createLocalization](https://docs.api.rask.ai/operations/createLocalization.md) |
| [listTranscriptVersions](https://docs.api.rask.ai/operations/listTranscriptVersions.md), [createTranscriptVersion](https://docs.api.rask.ai/operations/createTranscriptVersion.md), [getTranscriptVersion](https://docs.api.rask.ai/operations/getTranscriptVersion.md) | [estimateSegmentGeneration](https://docs.api.rask.ai/operations/estimateSegmentGeneration.md), [generateSegments](https://docs.api.rask.ai/operations/generateSegments.md) |
| [listTranscriptVersionSegments](https://docs.api.rask.ai/operations/listTranscriptVersionSegments.md), [restoreTranscriptVersion](https://docs.api.rask.ai/operations/restoreTranscriptVersion.md) | [getTranslationSettings](https://docs.api.rask.ai/operations/getTranslationSettings.md), [updateTranslationSettings](https://docs.api.rask.ai/operations/updateTranslationSettings.md) |

The outputs held back are `dubbed_subtitles`, `source_subtitles`, `source_subtitles_speakers`, `target_subtitles` and `target_subtitles_speakers`. In the contract, closed operations carry `x-rask-operation.dub_payment_gate`, and the [operation table](https://docs.api.rask.ai/v3/concepts/operation-table.md) marks them.

The rule covers projects created through v3. Projects created in other ways are not gated.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.