Skip to main content
Every product on this page is billed in Characters from your account balance. The rules differ by product, so start with the row for the product you integrate: Rates are per plan. Never hard-code them; read the values the service returns, as described in each section.

Speech to Text billing

STT shares the workspace’s Characters balance, STT rate card and History. Read STT capabilities for the account’s Batch rate; use the returned session usage and final task billing for Real-time. Do not assume the two modes have the same rate. Batch submission prices and reserves the task in one call; there is no separate public STT quote endpoint. Real-time reserves capacity while recording and settles confirmed audio when finished. Unused reserved Characters are released. A PARTIAL result charges only the confirmed billable audio; use the returned billing values rather than the length you attempted to send. The duration-based calculation is ceil(billableSeconds × ratePerMinute / 60). The service calculates this from the audio sample count. Optional processing features are included in the base rate, and multiple channels do not multiply the same file timeline’s price. Equal-duration audio at different supported sample rates/encodings has the same charge at the same mode and rate. Read billing.state, reservedCharacters, settledCharacters, releasedCharacters and billableCharacters on the transcription. While reserved, billableCharacters can reflect the hold; it is not proof of final consumption. Monetary quantities here are Characters, not currency. Characters, sample counts and millisecond durations use decimal strings; bounded rates and indices are numbers. Reads, downloads, notification retries and repeated finish do not charge again. See STT availability for current validation and recovery limitations. The separate quote endpoints and product-specific rate tables below apply to Music and Interpretation.

Music and Interpretation: always quote, never estimate

Text-to-Music and Interpretation consume Characters. Nothing is charged by a read call: the cost is always quoted first, then reserved when you accept the quote. Quotes are free.
This section and the rest of this page apply to Text-to-Music and Interpretation only. They do not change how Speech to Text prices and reserves at submission. Both products expose a capabilities endpoint and a quotes endpoint. Read the rate from capabilities and the exact amount from quotes.
  • POST /sound_clone/api/v1/music/projects/{projectId}/quotes
  • POST /sound_clone/api/v1/interpretation/projects/{projectId}/quotes
Never hard-code a rate table into a client: rates are per plan, and the authoritative value for an account is what the service returns for that account.

The formulas

Text-to-Music

durationSec is the project’s selected duration (60, 90, 120 or 180). The rate is the account’s ratePerMinute from capabilities.

Interpretation

The rate is account.charactersPerMinutePerLanguage for the account’s plan, and durationMs is the detected duration of the frozen source. Charging is per new target language: adding a language to an existing project only charges for the language being added, not for the ones that already exist.

Plan rates

These are the current plan rates published by the service. Always prefer the value returned for the specific account. Text-to-Music — ratePerMinute Interpretation — charactersPerMinutePerLanguage
The two products do not share a fallback rule. Text-to-Music is fine with an ENTERPRISE account that has no explicit override and uses the plan default (1200). Interpretation is not: with an ENTERPRISE account and no configured contract rate, quoting fails with code = 47119 instead of silently picking a number. Do not copy one product’s fallback into the other.

Worked examples

Text-to-Music, PRO plan, 90-second song
Text-to-Music, POPULAR plan, 90-second song
Interpretation, PRO plan, 90-second source, two new languages (Spanish and French)
Interpretation, same project, adding a third language later

Reading the numbers safely

The API serializes 64-bit integers as JSON strings to avoid precision loss in JavaScript clients. Every Characters amount — quotedCharacters, totalCharacters, perTargetCharacters, reservedCharacters, shortfall, remainingAfterGeneration, balances.*, targets[].characters — arrives as a string such as "12000".
  • Python: convert with int(value).
  • Node.js: convert with BigInt(value) when the value can exceed Number.MAX_SAFE_INTEGER (9007199254740993); otherwise an explicit numeric parse is fine. Never JSON.stringify a value that is still a BigInt.
  • Never compare these values as strings. "9000" < "10000" is false lexicographically while 9000 < 10000 is true — string comparison gives the wrong answer.
Request bodies are different: send numbers as JSON numbers (durationSec: 90, size: 18432611, expectedVersion: 1). Do not send strings just because responses use strings.

The quote response

A quote tells you the price and whether the account can afford it: Music answers the same questions with affordable, shortfall, remainingAfterGeneration and balances, plus ratePerMinute, rateVersion and quotedCharacters. The balance fields are per response and per product, so do not apply one product’s wording to the other:
  • Interpretation exposes balanceState, which is AVAILABLE or LEDGER_UNAVAILABLE, plus availableCharacters and estimatedRemainingCharacters. When the shared ledger read is unavailable, the two amounts are null and balanceState is LEDGER_UNAVAILABLE — a state, not a zero and not a guess.
  • Text-to-Music exposes balances (which may itself be null when the balance cannot be read) and has no balanceState field at all.
  • account.accessState is a different question again: for Interpretation it is one of ENABLED, FREE_LOCKED, ENTERPRISE_UNRESOLVED, SYNCING or UNRESOLVED; for Text-to-Music it is ENABLED or DISABLED.

Quote lifetime and invalidation

  • A quote lives for quoteTtlSeconds — normally 600 seconds (10 minutes).
  • Using an expired quote fails: Music 47006, Interpretation 47108.
  • Changing the inputs invalidates the quote. For Music that includes editing or regenerating the arrangement; an invalidated quote later fails with 47007.
When a quote expires, request a new one. Nothing has been charged.

ALL_TARGETS_EXIST (Interpretation)

If every requested language already exists for the frozen source, the quote returns:
This is a successful quote, not an error — and it is not something to pay for. Read existingTargets and use the targets that already exist. Never call the generation endpoint with a null quoteId.

Reservation, settlement and release

Charging is a three-phase lifecycle managed by the shared Characters ledger:
  1. Quote — free. It only prices the work.
  2. Reserve — when you accept the quote, the amount is reserved for that operation. In Music you receive reservedCharacters and one job; in Interpretation each target language gets its own reservation and its own reservationCycle.
  3. Settle or release — after the real outcome, the reservation is settled (the Characters are consumed) or released (the Characters go back).
Only the real ledger state may be described as settled or released. A job in RECOVERY_REQUIRED / RECONCILING, a failed HTTP response, a client timeout or an export in RETRY are not proof that a reservation was released, and none of them authorize telling a user that they were refunded. Query the resource and read its billingState / reservation state instead.
Notes that follow from this model:
  • Each Interpretation target language settles or is released independently. One language may settle while another is released — that is the PARTIAL_READY case, and it is not a billing error.
  • Interpretation’s billingState is SETTLED, RESERVED, RELEASED or UNPRICED, derived from the reservation and the target state.
  • A generation is settled at most once per target; retries run against the server’s plan and never double-charge.

Not enough Characters

When the balance does not cover the quote:
  • affordable is false and shortfall tells you how much is missing.
  • Accepting the quote anyway fails with Music 47005 or Interpretation 47110.
Top up and re-quote. Do not split a single generation into smaller requests to work around the balance: the price is a property of the request, not of the remaining balance.

Testing without spending real Characters

There is no “test mode” endpoint. The examples in this repository are written so they can run against a local deterministic stub server that replies with the documented response shapes, which is how they are validated without consuming real Characters or calling a real provider. Point MYVOCAL_API_BASE_URL at your stub to do the same.
Running the examples against the production host performs real, billable work and consumes Characters from the account that owns the API key. Use a stub for development, and check affordable and shortfall before accepting a real quote.