---
title: "POST /orders/{order}/dub — Dub an order"
url: https://lumean.app/tr/developers/docs/api/post-orders-order-dub
locale: tr
description: "Dub an order"
generated: 2026-11-08
operationId: dubbing.store
method: POST
path: "/orders/{order}/dub"
scopes: [orders.write]
spec_version: 1.0.0
---

# POST /orders/{order}/dub

**Dub an order**

Dubs a finished Cartesia or ElevenLabs voice-over order into another language, keeping
the timing: every dubbed phrase starts where the source phrase starts, and the track
length matches. The service translates — you do not send any text.

Creates a NEW order (one fragment) of the dub service: source `cartesia` →
`cartesia_dub`, source `elevenlabs` → `elevenlabs_dub` (the new order's `task_type` is
the dub service code). Track readiness as with any order: the WS channel
`private-order.task.{orderId}` or polling `GET /orders/{order}`. The track
`output/chunks/0/result.mp3` is in `result.files[]`, the subtitles `subtitles.srt` are in
`result.service_files[]`; `POST /storage/url` gives a download link.

**Body:**

- `target_language` (required) — the dub language from the options' `languages`;
- `voice_id` — the dub voice; omitted — the template voice (the source order's snapshot
  or `template_id`). Same format as in the service template: Cartesia — a catalog voice
  or your own clone id, ElevenLabs — a 20-character voice id;
- `model_id` — a model from the options' `models`; omitted — the template model;
- `template_id` — your template of the same service as the source: the voice and model
  come from it. Someone else's template or a template of another service gives `422`,
  nothing is charged;
- `name` — the new order's name (default "<source name> → EN").

**Source:** only your own finished order with stored files, a single track (not the
paragraph mode), no longer than `max_source_chars`. The dub language must differ from
the source language: for a Cartesia source a match is refused at once (`422`); an
ElevenLabs source language is unknown (`auto`), so such a dub fails at the worker and is
refunded in full.

**Payment:** per source character, translation included — Cartesia 1.35 Cartesia
characters, ElevenLabs 1.5 ElevenLabs characters (plus the service minimum). The
subscription quota goes first (by the source service entitlement), the rest is PAYG
from the balance. A failed dub refunds the money in full. Get the price in advance with
`GET /orders/{order}/dub/quote`.

The dub cost is charged against your key's token quota. The check runs **before** the
order is created: if exceeded, you get `429` and no order is created. The same request
(same source and fields) within a minute of the first gets `409` `duplicate_order` —
protection against double submission.

**Required key permission:** `orders.write`.

- Gerekli izin: `orders.write`

## İstek

```bash
curl -X POST 'https://api.lumean.app/api/public/orders/{order}/dub' \
  -H 'Accept: application/json' \
  -H 'X-API-KEY: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "target_language": "en"
}'
```

## Parametreler

| Alan | Yer | Tür | Zor. | Açıklama |
| --- | --- | --- | --- | --- |
| `order` | path | `string` | zorunlu | Order UUID — 36 characters shaped like `9f8b2c1a-4d3e-4f5a-8b9c-0d1e2f3a4b5c`, not a number. Take it from the `id` field: `POST /orders` returns it on creation and `GET /orders` lists it. Someone else’s order will not open with your key — you get a `404`. |
| `X-Locale` | header | `string` | — | Language of the localised texts in the response (`message`, labels, failure reasons), an ISO-639-1 code. Optional; without it — the key owner’s account language, then `Accept-Language`, then the default language. An unknown or unsupported code is skipped as if it were absent. |
| `X-Timezone` | header | `string` | — | IANA time zone (`Europe/Moscow`) in which the response shows moments in time — ISO-8601 with an offset. Optional; without it dates come in UTC. An invalid zone is ignored. The server returns the applied zone in the response header of the same name. |

## İstek gövdesi

Dubbing a finished voice-over order: the dub language and, optionally, the voice, model,
template and name. The server takes the billable length and source files from the
source order itself.

Content-Type: `application/json`

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `target_language` | `string` — ≤ 16 karakter | zorunlu | The dub language — a value from `languages` of `GET /orders/dubbing/options` for the source kind. Must differ from the source language (`422` `dub_same_language`). Required for creation, optional for the quote. |
| `voice_id` | `string` — ≤ 64 karakter — nullable | — | The dub voice. Omitted — the template voice: the source order's template snapshot or `template_id`. Same format as in the service template: Cartesia — a catalog voice or your own clone id (UUID), ElevenLabs — a 20-character voice id. |
| `model_id` | `string` — ≤ 64 karakter — nullable | — | The dub model from the options' `models`. Omitted — the template model, otherwise `default_model`. |
| `template_id` | `string` — ≤ 64 karakter — nullable | — | Your template of the same service as the source (`cartesia` or `elevenlabs`): the voice, model and voice settings come from it instead of the source order's snapshot. Explicit `voice_id` and `model_id` override it. Someone else's or a deleted template, or a template of another service gives `422` on `template_id`, nothing is charged. |
| `name` | `string` — ≤ 120 karakter — nullable | — | The new order's name, up to 120 characters. Omitted — "<source name> → <LANG>". |

**Örnek**

```json
{
  "target_language": "en"
}
```

## Gövde senaryoları

### Language only

The voice and model come from the source order's template snapshot.

```json
{
  "target_language": "en"
}
```

### Own voice and model

A dub voice from the service catalog and a model from the options.

```json
{
  "target_language": "en",
  "voice_id": "5d2f0a1c-8b3e-4f5a-9c6d-7e8f9a0b1c2d",
  "model_id": "sonic-3",
  "name": "Chapter 1 (EN)"
}
```

### Voice from another template

The voice and model come from your template of the same service.

```json
{
  "target_language": "de",
  "template_id": "01a1701b-c1eb-7000-8000-000000000000"
}
```

## Yanıtlar

### 201 — The dub order is created.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Success flag. Branch on the HTTP status code instead: any 2xx response carries `true` here, while an error comes back in a different shape that need not contain this field at all. |
| `message` | `string` | zorunlu | A human-readable note in the account language. Fine to show to a user; do not parse it — the wording changes without notice and is not an error code. |
| `data` | `Order` | zorunlu | A **new** dub order (`task_type` is `cartesia_dub` or `elevenlabs_dub`). The source order is left untouched. |
| `data.id` | `string` | zorunlu | Order UUID. Use it in `/orders/{order}/…` paths and when calling `POST /orders/{order}/retry`. |
| `data.user_id` | `integer` | zorunlu | ID of the order owner. For orders created with an API key this is always the key owner — a key never sees someone else’s order. |
| `data.name` | `string` | zorunlu | Order name: the downloaded file name and the ZIP archive name are derived from it. |
| `data.template` | `Template` | — | The template the order was created from. Present only for orders that have a `template_id`; template-less orders (`sfx`/`music` created by `task_type`) omit it. Its `config` holds the settings THIS order runs with: the template configuration at the moment the order was created, with `config_override` applied on top; editing the template later does not change it. In the `GET /orders` list `config` is `null` — the full configuration comes from `GET /orders/{order}`. The template may have been deleted since: it is still shown here, but `GET /templates/{template}` returns `404` and a new order with that `template_id` returns `422`. Orders created before this API version (late September 2026) have no snapshot: their `config` is the current template configuration with `config_override` applied, and editing the template changes it. |
| `data.template.id` | `string` | zorunlu | Template UUID. Put it into `template_id` when creating an order. |
| `data.template.user_id` | `integer` | zorunlu | ID of the template owner. |
| `data.template.slug` | `string` | zorunlu | Short public identifier used for sharing. `null` on a template that was never shared. |
| `data.template.name` | `string` | zorunlu | Template name — for humans only; it does not affect generation. |
| `data.template.service_key` | `string` | zorunlu | Code of the service whose schema validates `config`: `elevenlabs`, `lumimg`, and so on. |
| `data.template.service` | `Service \| null` — nullable | zorunlu | The template’s service for reference: name and pricing, without configuration schemas. `null` means no service with that code exists any more. |
| `data.template.config` | `object` | zorunlu | Generation settings: voice, model, speed and so on — the set of keys is defined by the service. Look up allowed values in `GET /templates/config-options?service=<code>`; anything outside the schema is rejected with `422`. Inside an order (`template` in `GET /orders/{order}`) this is the order’s own settings — the snapshot taken at creation with `config_override` applied, not the template’s current configuration (for orders created before late September 2026 — the current template configuration with `config_override`). |
| `data.template.is_public` | `boolean` | zorunlu | Whether the template is published in the shared catalogue. |
| `data.template.folder_id` | `string` | zorunlu | UUID of the folder holding the template, or `null` for the root. The folder tree is visible in `GET /templates/browse`. |
| `data.template.created_at` | `string` — date-time — nullable | zorunlu | When the template was created, ISO 8601. |
| `data.template.updated_at` | `string` — date-time — nullable | zorunlu | When the template last changed, ISO 8601. |
| `data.template_id` | `string` | zorunlu | UUID of the template used, or `null` when the order was created without one. |
| `data.task_type` | `TaskType` — `tts` · `image` · `txt2img` · `remix` · `image_edit` · `voice_clone` · `sfx` · `music` · `voice_search` · `cartesia_dub` · `elevenlabs_dub` | zorunlu | Task type — it determines what goes into `task_data` and what comes back in `result`. |
| `data.status` | `OrderStatus` — `created` · `pending` · `in_progress` · `completed` · `result_delivered` · `failed` · `compensated` · `cancelled` · `partially_completed` | zorunlu | Current state of the order. There are five terminal values — `completed`, `result_delivered`, `failed`, `compensated` and `cancelled`; there is nothing to poll for after those. `partially_completed` is NOT terminal: some chunks succeeded and some failed. The finished files are already downloadable, and the failed fragments can be requeued via `POST /orders/{order}/items/retry-failed` — after the retry the order can move on to `completed`. `compensated` and `failed` mean the order closed without a result. `compensated` is the normal outcome: no fragment succeeded (a generation failure, or every fragment was rejected by the content policy), the order’s lock is released and the quota returned; only the fee for `policy_flagged` attempts is withheld (see `items[].status`). `failed` is rare: the order failed while its input files were being prepared (the refund is made right away), or the automatic refund did not go through — such an order is settled by support. If at least one fragment is ready, a failure yields `partially_completed` instead: what is done is paid for, and what failed can be retried. |
| `data.price_units` | `integer` | zorunlu | The amount locked for the order, in LMC minor units. Do not display this number as-is: the real value is `price_units / 10^precision`, where `precision` comes from the asset alongside. A display-ready value sits in the neighbouring decimal field. |
| `data.price_formatted` | `number` — nullable | zorunlu | The same amount as `price_units`, expressed in whole LMC and ready to display. `null` until the cost is settled. |
| `data.currency_asset` | `Asset` | zorunlu | The amount's asset is always LMC. Its `precision` is what converts minor units into the real value. |
| `data.currency_asset.id` | `integer` | zorunlu | Internal identifier of the asset. |
| `data.currency_asset.code` | `string` | zorunlu | Asset code: `LUMC` is the internal currency, `TOKEN` the generation tokens. |
| `data.currency_asset.kind` | `AssetKind` — `money` · `unit` | zorunlu | Kind of asset: money or consumable units. It decides whether an amount counts as a payment or as quota consumption. |
| `data.currency_asset.precision` | `integer` | zorunlu | Number of decimal places. **The load-bearing field:** every integer amount in this asset is divided by `10^precision` to obtain the real value. Do not assume the divisor is 100. |
| `data.currency_asset.name` | `string` | zorunlu | Display name of the asset, in the account language. |
| `data.currency_asset.deleted_at` | `string` — date-time — nullable | zorunlu | When the asset was retired, ISO 8601. `null` while it is in use. |
| `data.currency_asset.created_at` | `string` — date-time — nullable | zorunlu | When the asset was created, ISO 8601. |
| `data.currency_asset.updated_at` | `string` — date-time — nullable | zorunlu | When the asset last changed, ISO 8601. |
| `data.total_tokens` | `integer` — nullable | zorunlu | The order's full cost in tokens: the original chunks plus every retry and regeneration. This is a quota unit, not money. |
| `data.total_duration_ms` | `integer` — nullable | zorunlu | Total length of the produced audio in milliseconds. This is the result's duration, not the time spent generating it. |
| `data.task_data` | `object` — nullable | zorunlu | The task input exactly as the server accepted it: text, references to uploaded files, resolved settings. The set of keys depends on `task_type`. |
| `data.result` | `object` — nullable | zorunlu | Execution result. `files[]` holds the primary files; `service_files[]` holds auxiliary ones (subtitles `.srt`/`.vtt`/`.lrc`, alignment) for TTS orders. Paths are **absolute** and ready to pass to `POST /storage/url`. `null` while the order is unfinished, and also for a failed order: the public surface does not expose error internals. |
| `data.created_at` | `string` — date-time — nullable | zorunlu | When the order was created, ISO 8601. |
| `data.updated_at` | `string` — date-time — nullable | zorunlu | When the order last changed, ISO 8601. It advances on every status transition, which makes it a cheap “something happened” signal. |
| `data.files_expire_at` | `string` — nullable | zorunlu | Retention of the order's files. `files_expire_at` is the deletion moment (`null` when the order has not finished yet, or the files are already gone); `files_expired` means nothing is left to download. |
| `data.files_expired` | `boolean` | zorunlu | `true` means retention has elapsed and the files are already deleted: no link can be issued, and the order has to be created again. |
| `data.retention` | `object` | zorunlu | Retention deadlines by file level. For a stitched order the per-fragment tracks are removed earlier than the result itself. |
| `data.retention.chunks` | `object` | zorunlu | Lifetime of the per-fragment tracks — pause editing, re-stitching and per-fragment regeneration all operate on them. |
| `data.retention.chunks.expires_at` | `string` | zorunlu | When the per-fragment tracks disappear, ISO 8601. Until then pause editing, re-stitching and per-fragment regeneration remain available. `null` means the order has not finished yet (the countdown has not started) or the fragments are already gone. |
| `data.retention.chunks.expired` | `boolean` | zorunlu | `true` means the per-fragment tracks are gone: editing and re-stitching are rejected. The finished result may still be available — check `retention.files`. |
| `data.retention.chunks.expires_early` | `boolean` | zorunlu | `true` means the fragments will disappear before the result (the order is stitched into a separate file). `false` means the fragments are the result, and both levels expire together. |
| `data.retention.chunks.reason` | `string` — `chunks_purged` · `storage_expired` · `null` — nullable | zorunlu | Why the fragments are unavailable: `chunks_purged` — removed on their own schedule while the result is still there; `storage_expired` — every file of the order is gone. `null` means the fragments are available. |
| `data.retention.files` | `object` | zorunlu | Lifetime of every file of the order, including the result. Mirrors the top-level `files_expire_at` / `files_expired` fields. |
| `data.retention.files.expires_at` | `string` — nullable | zorunlu | When every file of the order will be deleted, ISO 8601. The same value as `files_expire_at` — the top-level field is kept for compatibility. |
| `data.retention.files.expired` | `boolean` | zorunlu | Same as `files_expired`: nothing is left to download. |
| `data.eta_seconds` | `integer` — nullable | zorunlu | Estimated time remaining, in seconds — present only while the order is running. `null` once it is finished, and before it starts. |
| `data.eta_at` | `string` — date-time — nullable | zorunlu | Expected completion moment, ISO 8601 — the same forecast as `eta_seconds`, expressed as an absolute time. |
| `data.completed_chunks` | `integer` — nullable | zorunlu | How many source chunks are already finished. Retries and regenerations are excluded — counting them would push progress past 100%. |
| `data.total_chunks` | `integer` — nullable | zorunlu | How many source chunks the order has in total. Zero means the split has not happened yet. |
| `data.progress_percent` | `integer` — nullable | zorunlu | Completion percentage, 0–100 — derived from `completed_chunks` and `total_chunks`, so there is no need to compute it yourself. |
| `data.stitching` | `boolean` | zorunlu | `true` means the audio is being stitched and the result is not final yet. This also happens with `status = completed`: after a fragment is regenerated the final track is rebuilt, and until stitching ends `result` points to the previous track. Download the result once `stitching = false`. |
| `data.paragraphs` | `array<object>` — nullable | zorunlu | Per-paragraph summary: index, fragment count, aggregate status, progress and audio file (`result_file`). `null` means the order uses ordinary mode — use `items[]` instead. To get paragraphs, create the order with `config_override.generation_mode = paragraph` (see that field for details). |
| `data.paragraphs[].paragraph_index` | `integer` | zorunlu | Zero-based index of the paragraph. |
| `data.paragraphs[].chunks_count` | `integer \| number` | zorunlu | How many chunks the paragraph was split into. |
| `data.paragraphs[].completed_chunks` | `string \| integer` | zorunlu | How many of the paragraph’s chunks are already finished. |
| `data.paragraphs[].status` | `string` | zorunlu | Aggregate status of the paragraph: derived from its chunks’ statuses rather than stored separately. It uses its own, shorter vocabulary: `pending`, `in_progress`, `failed`, `completed` — a chunk blocked by moderation also reads as `failed`. Only the original chunks count, so a successful retry of a failed fragment does NOT change the paragraph status: check the fragment itself in `items[]`. |
| `data.paragraphs[].progress_percent` | `integer` | zorunlu | Paragraph completion percentage, 0–100. |
| `data.paragraphs[].result_file` | `string` — nullable | zorunlu | The whole paragraph stitched into one audio file: an absolute path, or a structure carrying path and size. Download it via `POST /storage/url`, same as the other order files. `null` means two different things depending on `chunks_count`: with `chunks_count = 1` the paragraph has no file of its own and never will — the paragraph *is* that single fragment, so take its `result_file` from `items[]` under the same `paragraph_index`; with `chunks_count > 1` the stitch has not happened yet — a multi-chunk paragraph gets its file ONLY after stitching, never in advance. |
| `data.items` | `array<OrderItem>` | — | The order’s chunks. Present in the detailed `GET /orders/{order}` response; the list endpoint `GET /orders` omits the field — use `GET /orders/{order}/items` instead. |
| `data.items[].id` | `string` | zorunlu | Chunk UUID. Use it in `/orders/{order}/items/{item}/…` paths. |
| `data.items[].order_id` | `string` | zorunlu | UUID of the order this chunk belongs to. |
| `data.items[].item_type` | `string` | zorunlu | What the record is: `chunk` is an original fragment, `retry` a free re-run of a failed one, `regeneration` a paid redo of a finished one. Retries and regenerations are separate records sharing the same `chunk_index`: the full attempt history is kept, and the last one is what the result plays. |
| `data.items[].chunk_index` | `integer` — nullable | zorunlu | Zero-based position of the fragment within the order. It defines the order in which the final file is assembled. |
| `data.items[].paragraph_index` | `string` | zorunlu | The paragraph this fragment belongs to — filled in only for the original fragments of a paragraph-mode order. It is `null` both in ordinary mode and on retry or regeneration records: those carry no paragraph link of their own and inherit it from the parent fragment via `parent_item_id`. The mode is switched on by the `generation_mode` key in the order's `config_override`. |
| `data.items[].parent_item_id` | `string` | zorunlu | UUID of the source chunk — present on `retry` and `regeneration` records. `null` on an original chunk. |
| `data.items[].original_text_length` | `integer` | zorunlu | Length of the text the fragment was created with. It is the ceiling for `text` in `regenerate`. |
| `data.items[].current_text_length` | `integer` | zorunlu | Length of the fragment’s current text: after a regeneration it differs from `original_text_length`. |
| `data.items[].price_units` | `integer` | zorunlu | Cost of the fragment in **tokens** — not money. The monetary amount lives on the order itself, in its own `price_units` field (LMC there, tokens here; the names match, the units do not). |
| `data.items[].consumed_units` | `integer` | zorunlu | How many tokens were actually charged for this fragment. Zero while the fragment is unfinished. |
| `data.items[].remaining_locked` | `integer` | zorunlu | How many tokens are still reserved for the fragment. Drops to zero once the fragment finishes or is cancelled. |
| `data.items[].status` | `string` | zorunlu | Fragment state: `pending` waits for a worker, `processing` is in flight, `completed` is done, `failed` hit a technical error, and `policy_flagged` was rejected by the content policy. The difference between the last two dictates the fix: `failed` is cured by retrying as is, whereas `policy_flagged` requires rewording — retrying the same text is rejected again. A `policy_flagged` attempt on ElevenLabs is not free: it consumes the provider’s resources even without a result, so a fixed per-attempt fee is withheld from the amount that would otherwise be returned for the fragment (on quota-funded orders — the equivalent in tokens). It is withheld only from what is being returned — nothing is charged beyond the order’s lock, and the balance never goes negative. The money part shows up in the transaction history as `policy_block_fee`; from the quota, simply fewer tokens are returned. |
| `data.items[].result_file` | `object \| string \| null` — nullable | zorunlu | The finished fragment’s file: an absolute path, or a structure carrying path and size. Download it via `POST /storage/url`, same as order files. `null` until the fragment is ready. |
| `data.items[].duration_ms` | `integer` — nullable | zorunlu | Duration of the produced audio in milliseconds — the length of the recording, not the generation time. `null` for non-audio tasks. |
| `data.items[].attempt_number` | `integer` | zorunlu | Attempt number for this fragment, starting at 1. It grows with every retry. |
| `data.items[].can_retry` | `boolean` | zorunlu | Whether a free retry is allowed right now. It already accounts for status, task type and exhausted attempts, so you need not re-check the conditions. |
| `data.items[].can_regenerate` | `boolean` | zorunlu | Whether a paid regeneration is allowed right now. Available for finished fragments only. |
| `data.items[].created_at` | `string` — date-time — nullable | zorunlu | When the fragment was created, ISO 8601. |
| `data.items[].updated_at` | `string` — date-time — nullable | zorunlu | When the fragment last changed, ISO 8601. |
| `data.items[].failure_reason` | `string` — nullable | — | The reason the fragment failed, for display to the user — localised text in the request language, not a machine code (do not branch on it, the wording changes). Present only on `failed` and `policy_flagged`; everything else, and a failure whose reason could not be determined, gets `null`. |
| `data.tokens_from_quota` | `integer` — nullable | — | How many of the spent tokens were covered by the subscription quota. `null` means the quota covered nothing. |
| `data.tokens_from_payg` | `integer` — nullable | — | How many tokens were paid for out of the LMC balance, beyond the quota. `null` means there was no top-up. |
| `data.tokens_spent` | `integer` — nullable | — | The sum of the two fields above: how many tokens were charged for the order (quota + top-up). Orders covered by an unlimited subscription and free versions are excluded — an unlimited order has `null` here; the generated volume is `total_tokens`. Retries are excluded — they are not billed again. |
| `data.queue_position` | `integer` — nullable | — | The order’s place in the queue: how many orders are ahead of it, `0` means next. Present for any task type while the order waits for a free worker (for `voice_search`, until the check is done); once processing starts, the field is gone. A missing key means "not queued", not "position unknown". |
| `data.queue_wait_seconds` | `integer` — nullable | — | Estimated wait in the queue, in seconds. Computed only for voice search; for other tasks, and while no statistics exist, it is `null`. An estimate, not a promise — recomputed on every response. |

**Örnek**

```json
{
  "success": true,
  "message": "string",
  "data": {
    "id": "string",
    "user_id": 1,
    "name": "string",
    "template": {
      "id": "string",
      "user_id": 1,
      "user": {
        "id": 1,
        "email": "string",
        "lang_code": "string",
        "timezone": "string",
        "display_currency": "string",
        "has_telegram": true,
        "created_at": "2026-07-17T12:34:56+00:00",
        "updated_at": "2026-07-17T12:34:56+00:00",
        "referral_code": "string",
        "referral": {
          "kind": "partner",
          "code": "string",
          "program_id": "string",
          "commission_rate": 1
        },
        "preferred_domain": "string",
        "email_verified_at": "string",
        "is_admin": true,
        "is_beta_tester": true,
        "allowed_models": "string",
        "referrer_id": 1,
        "deleted_at": "2026-07-17T12:34:56+00:00",
        "blocked_at": "2026-07-17T12:34:56+00:00",
        "is_blocked": true,
        "tickets_banned_at": "string",
        "is_tickets_banned": true,
        "tickets_ban_reason": "string",
        "voice_clone_banned_at": "string",
        "is_voice_clone_banned": true,
        "voice_clone_ban_reason": "string",
        "is_super_admin": true,
        "admin_permissions": [
          "string"
        ],
        "admin_roles": [
          {
            "name": null,
            "display_name": null
          }
        ],
        "referrer": null,
        "referral_link": "string",
        "active_referral_program": null,
        "wallets": [
          null
        ],
        "telegram": {
          "id": null,
          "telegram_id": null,
          "username": null,
          "first_name": null,
          "last_name": null,
          "is_bot_blocked": null,
          "created_at": null,
          "updated_at": null
        },
        "subscriptions": [
          null
        ],
        "order_settings": {
          "order_delay_enabled": null,
          "order_delay_seconds": null
        },
        "entitlements": [
          null
        ]
      },
      "slug": "string",
      "name": "string",
      "service_key": "string",
      "service": {
        "id": 1,
        "code": "string",
        "name": null,
        "display_name": "string",
        "label": null,
        "payg_access": "string",
        "billing_mode": null,
        "unit_asset_id": 1,
        "unit_asset": null,
        "required_entitlement_id": 1,
        "required_entitlement": null,
        "units_per_call": 1,
        "units_per_char": 1,
        "units_per_image": 1,
        "units_per_second": 1,
        "min_billable_chars": 1,
        "lumcoin_per_token": 1,
        "lumc_precision": 1,
        "price_lumc_minor": 1,
        "unit_size": 1,
        "uses_money_first_pricing": true,
        "rate_unit": "string",
        "display_category": "string",
        "is_premium": true,
        "display_order": 1,
        "metadata": "string",
        "is_active": true,
        "maintenance_mode": true,
        "access_level": "string",
        "maintenance_auto_resume": true,
        "maintenance_started_at": "string",
        "maintenance_note": "string",
        "config_schema": "string",
        "default_config": "string",
        "validation_schema": "string",
        "routing_config": "string",
        "task_types": "string",
        "default_task_type": "string",
        "features": "string",
        "cost_config": "string",
        "created_at": "2026-07-17T12:34:56+00:00",
        "updated_at": "2026-07-17T12:34:56+00:00"
      },
      "config": [],
      "is_public": true,
      "folder_id": "string",
      "folder": {
        "id": "string",
        "user_id": 1,
        "user": {
          "id": null,
          "email": null,
          "lang_code": null,
          "timezone": null,
          "display_currency": null,
          "has_telegram": null,
          "created_at": null,
          "updated_at": null,
          "referral_code": null,
          "referral": null,
          "preferred_domain": null,
          "email_verified_at": null,
          "is_admin": null,
          "is_beta_tester": null,
          "allowed_models": null,
          "referrer_id": null,
          "deleted_at": null,
          "blocked_at": null,
          "is_blocked": null,
          "tickets_banned_at": null,
          "is_tickets_banned": null,
          "tickets_ban_reason": null,
          "voice_clone_banned_at": null,
          "is_voice_clone_banned": null,
          "voice_clone_ban_reason": null,
          "is_super_admin": null,
          "admin_permissions": null,
          "admin_roles": null,
          "referrer": null,
          "referral_link": null,
          "active_referral_program": null,
          "wallets": null,
          "telegram": null,
          "subscriptions": null,
          "order_settings": null,
          "entitlements": null
        },
        "name": "string",
        "templates": [
          null
        ],
        "created_at": "2026-07-17T12:34:56+00:00",
        "updated_at": "2026-07-17T12:34:56+00:00"
      },
      "created_at": "2026-07-17T12:34:56+00:00",
      "updated_at": "2026-07-17T12:34:56+00:00"
    },
    "template_id": "string",
    "task_type": "tts",
    "status": "created",
    "price_units": 1,
    "price_formatted": 1,
    "currency_asset": {
      "id": 1,
      "code": "string",
      "kind": "money",
      "precision": 1,
      "name": null,
      "is_active": true,
      "is_default": true,
      "default_balance": 1,
      "deleted_at": "2026-07-17T12:34:56+00:00",
      "created_at": "2026-07-17T12:34:56+00:00",
      "updated_at": "2026-07-17T12:34:56+00:00"
    },
    "total_tokens": 1,
    "total_duration_ms": 1,
    "": {
      "queue_position": 1,
      "queue_wait_seconds": 1
    },
    "task_data": [
      "string"
    ],
    "result": [
      "string"
    ],
    "created_at": "2026-07-17T12:34:56+00:00",
    "updated_at": "2026-07-17T12:34:56+00:00",
    "files_expire_at": "string",
    "files_expired": true,
    "retention": {
      "chunks": {
        "expires_at": "string",
        "expired": true,
        "expires_early": true,
        "reason": "chunks_purged"
      },
      "files": {
        "expires_at": "string",
        "expired": true
      }
    },
    "eta_seconds": "string",
    "eta_at": "string",
    "completed_chunks": "string",
    "total_chunks": "string",
    "progress_percent": "string",
    "stitching": true,
    "paragraphs": [
      {
        "paragraph_index": 1,
        "chunks_count": 1,
        "completed_chunks": "string",
        "status": "string",
        "progress_percent": 1,
        "result_file": "string"
      }
    ],
    "dubbing_source": {
      "voice_id": "string",
      "eligible": true
    },
    "source": "bot",
    "user": {
      "id": 1,
      "email": "string",
      "lang_code": "string",
      "timezone": "string",
      "display_currency": "string",
      "has_telegram": true,
      "created_at": "2026-07-17T12:34:56+00:00",
      "updated_at": "2026-07-17T12:34:56+00:00",
      "referral_code": "string",
      "referral": {
        "kind": "partner",
        "code": "string",
        "program_id": "string",
        "commission_rate": 1
      },
      "preferred_domain": "string",
      "email_verified_at": "string",
      "is_admin": true,
      "is_beta_tester": true,
      "allowed_models": "string",
      "referrer_id": 1,
      "deleted_at": "2026-07-17T12:34:56+00:00",
      "blocked_at": "2026-07-17T12:34:56+00:00",
      "is_blocked": true,
      "tickets_banned_at": "string",
      "is_tickets_banned": true,
      "tickets_ban_reason": "string",
      "voice_clone_banned_at": "string",
      "is_voice_clone_banned": true,
      "voice_clone_ban_reason": "string",
      "is_super_admin": true,
      "admin_permissions": [
        "string"
      ],
      "admin_roles": [
        {
          "name": "string",
          "display_name": "string"
        }
      ],
      "referrer": null,
      "referral_link": "string",
      "active_referral_program": {
        "id": 1,
        "code": "string",
        "name": "string",
        "inviter_reward_percent": 1,
        "invitee_reward_percent": 1,
        "is_default": true,
        "is_active": true,
        "inviter_reward_wallet_purpose": "string",
        "invitee_reward_wallet_purpose": "string",
        "reward_on": null,
        "rules": "string",
        "created_at": "2026-07-17T12:34:56+00:00",
        "updated_at": "2026-07-17T12:34:56+00:00"
      },
      "wallets": [
        {
          "id": 1,
          "user_id": 1,
          "asset_id": 1,
          "purpose": "string",
          "balance": 1,
          "locked_balance": 1,
          "balance_formatted": 1,
          "locked_balance_formatted": 1,
          "balance_converted": {
            "currency": null,
            "amount": null,
            "symbol": null,
            "precision": null
          },
          "asset": null,
          "user": null,
          "deleted_at": "2026-07-17T12:34:56+00:00",
          "created_at": "2026-07-17T12:34:56+00:00",
          "updated_at": "2026-07-17T12:34:56+00:00",
          "system_key": "string"
        }
      ],
      "telegram": {
        "id": 1,
        "telegram_id": "string",
        "username": "string",
        "first_name": "string",
        "last_name": "string",
        "is_bot_blocked": true,
        "created_at": "2026-07-17T12:34:56+00:00",
        "updated_at": "2026-07-17T12:34:56+00:00"
      },
      "subscriptions": [
        {
          "id": 1,
          "user_id": 1,
          "user": null,
          "status": null,
          "billing_anchor_at": "2026-07-17T12:34:56+00:00",
          "current_period_start": "2026-07-17T12:34:56+00:00",
          "current_period_end": "2026-07-17T12:34:56+00:00",
          "canceled_at": "2026-07-17T12:34:56+00:00",
          "items": [
            null
          ],
          "created_at": "2026-07-17T12:34:56+00:00",
          "updated_at": "2026-07-17T12:34:56+00:00"
        }
      ],
      "order_settings": {
        "order_delay_enabled": true,
        "order_delay_seconds": 1
      },
      "entitlements": [
        {
          "id": 1,
          "user_id": 1,
          "entitlement_id": 1,
          "entitlement": null,
          "source_subscription_item_id": 1,
          "starts_at": "2026-07-17T12:34:56+00:00",
          "ends_at": "2026-07-17T12:34:56+00:00",
          "status": null,
          "created_at": "2026-07-17T12:34:56+00:00",
          "is_unlimited": "string"
        }
      ]
    },
    "execution_meta": "string",
    "routing": {
      "nominal_service_key": "string",
      "effective_service_key": "string",
      "is_rerouted": true
    },
    "refunds": [
      {
        "id": 1,
        "user_id": 1,
        "user": {
          "id": "string",
          "email": "string",
          "name": "string"
        },
        "admin_id": 1,
        "admin": {
          "id": "string",
          "email": "string",
          "name": "string"
        },
        "type": "string",
        "type_label": "string",
        "status": "string",
        "status_label": "string",
        "invoice_id": 1,
        "payment_id": 1,
        "order_id": "string",
        "order": {
          "id": "string",
          "status": "string",
          "task_type": "string"
        },
        "refund_amount": 1,
        "refund_amount_formatted": 1,
        "currency": {
          "id": "string",
          "code": "string",
          "precision": 1,
          "is_provider_currency": true
        },
        "units_amount": 1,
        "units_asset": {
          "id": "string",
          "code": "string"
        },
        "reason": "string",
        "admin_note": "string",
        "metadata": "string",
        "completed_at": "string",
        "created_at": "string",
        "updated_at": "string"
      }
    ],
    "compensation": {
      "kind": "string",
      "is_partial": null
    },
    "items": [
      []
    ],
    "chunks": [
      {
        "chunk_index": 1,
        "item_id": "string",
        "status": "string",
        "failure_reason": "string",
        "text_length": "string",
        "can_regenerate": "string",
        "can_retry": "string",
        "versions_count": 1,
        "current": {
          "item_id": "string",
          "version": 1,
          "type": "string",
          "result_file": "string",
          "duration_ms": 1,
          "service_files": "string",
          "created_at": "string",
          "tokens": 1,
          "paid_with": "mixed",
          "quota_tokens": 1,
          "payg_tokens": 1,
          "lmc_minor": 1,
          "lmc": 1
        },
        "history": [
          "string"
        ],
        "attempts": [
          {
            "item_id": "string",
            "type": "string",
            "status": "string",
            "attempt_number": 1,
            "created_at": "string",
            "failure_reason": "string",
            "admin_free": true,
            "tokens": 1,
            "paid_with": "string",
            "quota_tokens": 1,
            "payg_tokens": 1,
            "lmc_minor": 1,
            "lmc": 1
          }
        ]
      }
    ],
    "operations": [
      {
        "id": "string",
        "type": "string",
        "status": "string",
        "result_file": "string",
        "paragraph_index": "string",
        "created_at": "string",
        "updated_at": "string"
      }
    ]
  }
}
```

### 401 — The key is missing, unknown, disabled or expired.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Always `false` in error responses. |
| `message` | `string` | zorunlu | Error text in the key's language (set through the `X-Locale` header). |
| `data` | `null` — nullable | zorunlu | Always `null` when the request is rejected before processing. |

**Örnek**

```json
{
  "success": false,
  "message": "API key is missing. Provide it in the X-API-KEY header.",
  "data": null
}
```

### 402 — Not enough money for the part beyond the subscription quota (`reason: insufficient_balance`), or the plan forbids a top-up (`insufficient_allowance`) — as with order creation.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Always `false` in error responses. |
| `message` | `string` | zorunlu | Error text in the key's language (set through the `X-Locale` header). |
| `reason` | `string` — `insufficient_balance` · `insufficient_allowance` · `payg_topup_required` | zorunlu | Machine-readable failure reason — branch on this, not on the message text. |
| `error_code` | `string` — `insufficient_balance` · `insufficient_allowance` · `payg_topup_required` | zorunlu | The same machine-readable code as in `reason` — a second name for the field. The values always match; branch on either. |
| `shortfall_tokens` | `integer` | — | How many tokens the subscription quota did not cover — these are the ones paid from LMC. |
| `shortfall_lmc` | `number` | — | Top-up cost in LMC, ready to show to the user. |
| `shortfall_lmc_minor` | `integer` | — | The same amount in LMC minor units — for exact arithmetic without rounding loss. |
| `quote_token` | `string` — nullable | — | The signed price quote: return it unchanged in the repeat request together with `confirm_payg_topup: true`. |
| `expires_at` | `string` — date-time — nullable | — | The price is fixed until this moment. Afterwards, repeat the request to get a fresh quote. |

**Örnek**

```json
{
  "success": false,
  "message": "Insufficient balance to cover the part of the order beyond the subscription quota.",
  "reason": "insufficient_balance",
  "error_code": "insufficient_balance"
}
```

### 403 — The key lacks the required permission, or the object belongs to another user.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Always `false` in error responses. |
| `message` | `string` | zorunlu | Error text in the key's language (set through the `X-Locale` header). |

**Örnek**

```json
{
  "success": false,
  "message": "This API key does not have permission to perform this action."
}
```

### 404 — The order is not found or does not belong to the key owner.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `message` | `string` | zorunlu | Error overview. |

**Örnek**

```json
{
  "success": false,
  "message": "Resource not found."
}
```

### 409 — `reason: duplicate_order` — the same dub was created less than a minute ago.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Always `false` in error responses. |
| `message` | `string` | zorunlu | Error text in the key's language (set through the `X-Locale` header). |
| `reason` | `string` — `quote_mismatch` | zorunlu | Machine-readable failure reason — branch on this, not on the message text. |
| `error_code` | `string` — `quote_mismatch` | zorunlu | The same machine-readable code as in `reason` — a second name for the field. The values always match; branch on either. |
| `actual_lmc_minor` | `integer` | zorunlu | What the top-up costs right now (LMC minor units). |
| `quoted_lmc_minor` | `integer` | zorunlu | The price you agreed to earlier (LMC minor units). |

**Örnek**

```json
{
  "success": false,
  "message": "The pay-as-you-go quote is stale — request a fresh one.",
  "reason": "quote_mismatch",
  "error_code": "quote_mismatch",
  "actual_lmc_minor": 380000000,
  "quoted_lmc_minor": 360000000
}
```

### 422 — `reason`: `dub_source_unavailable` (not a finished Cartesia/ElevenLabs voice-over, files expired, no timings, paragraph order, the source is being regenerated or stitched); `dub_source_too_long` (the body carries `source_chars`, `max_source_chars`); `dub_same_language`; `service_not_found` (dubbing is not available to the key owner); field validation errors.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `message` | `string` | zorunlu | A summary of the validation errors in words, in the response language (`X-Locale`). |
| `errors` | `object` | zorunlu | A per-field breakdown: the key names a request field, the value lists the complaints about it. |
| `errors.*` | `array<string>` — rastgele anahtarlar | — |  |

**Örnek**

```json
{
  "message": "string",
  "errors": {
    "key": [
      "string"
    ]
  }
}
```

### 429 — The key's token quota is exceeded, `reason: limit_exceeded` — the subscription usage limit is exhausted, or `reason: concurrency_limit_exceeded` — concurrent task slots are busy (`Retry-After`).

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Always `false` in error responses. |
| `message` | `string` | zorunlu | Error text in the key's language (set through the `X-Locale` header). |
| `reason` | `string` | zorunlu | Machine-readable failure reason — branch on this, not on the message text. |
| `error_code` | `string` | zorunlu | The same machine-readable code as in `reason` — a second name for the field. The values always match; branch on either. |
| `retry_after` | `integer` — nullable | — | How many seconds to wait before retrying (the same value is in the `Retry-After` header). |

**Örnek**

```json
{
  "success": false,
  "message": "Too many attempts. Please wait a moment and try again.",
  "reason": "rate_limit_exceeded",
  "error_code": "rate_limit_exceeded",
  "retry_after": 30
}
```

### 503 — Dubbing of this kind is temporarily not accepted.

**Yanıt alanları**

| Alan | Tür | Zor. | Açıklama |
| --- | --- | --- | --- |
| `success` | `boolean` | zorunlu | Always `false` in error responses. |
| `message` | `string` | zorunlu | Error text in the key's language (set through the `X-Locale` header). |

**Örnek**

```json
{
  "success": false,
  "message": "Service temporarily unavailable."
}
```

---

- Bu sayfa tarayıcıda: https://lumean.app/tr/developers/docs/api/post-orders-order-dub
- Makine tarafından okunabilir tam başvuru: https://api.lumean.app/docs/llm.md
