AgileTTS

The sovereign voice of the Agile suite: text → audio in Italian, voice cloning with tracked consent. Data never leaves the European Union; no external provider speaks on our behalf without saying so.

OpenAI-compatible APIkeys per product and tenantstreamingusage metering

Who it is for

AgileTTS speaks on a product's behalf whenever a natural Italian voice is needed and the data cannot leave the European Union:

If you need to integrate, start from the API documentation; if you need to evaluate the service, start from the plans below.

Plans and licences

One licence per company: the licence holds the keys (one per product), the scopes they may use, and the agreed quota and rate. Prices are set by Agile Software case by case — this page publishes no figures.

PlanScopesMonthly quota of charactersLimit per minuteDurationPrice
prova (trial)speech, stream, voices with low ceilingsreduced, enough to evaluatereducedmandatory expiry: after it, the key answers 403 KEY_EXPIREDon request
standardspeech, stream, voices; one key per product, rotation and revocationagreed in the company planagreed in the company planagreed, renewableon request
enterpriseas standard, plus the company console, its users and the audit of operationsagreed, with this month's consumption in the consoleagreed per company, not per single keyagreed, renewableon request

Quota and rate are the two ceilings of the company plan: the regia writes them, the company administrator reads them together with this month's consumption, and they are the very same number the service refuses on (429 QUOTA_EXCEEDED, 429 RATE_LIMIT). A refusal stays a refusal: no silent fallback to third parties.

Request a licence

The form reaches the regia — the control room of Agile Software — which answers with the plan, the ceilings and the key. No credit card and no self-activation: a licence is issued by a person.

How long we keep this data: a request notified to the regia is deleted 180 days after the notice, the fact of a request refused by the honeypot field 30 days after it, and a request not yet notified is never deleted — the round on the box counts and logs every deletion, without the email.

Service status

reading…

This page reads GET /health of the front end from your own browser, with no libraries and no intermediary: if the service does not answer it says so, and shows nothing made up. A 503 is an answer, not a hole: during a redeploy the front end declares the shutdown and says when to retry.

Why us

The market reference for AgileTTS is ElevenLabs, which is also what the products use today. Our numbers below are measurements taken in the repository, each with the file that produced it and its date; the leader's column is a measurement pending the vault key: our own scoped copy (agiletts__elevenlabs__api_key) has been blocked since 21/9 and the box has no tool to read it, so the elevenlabs arm of the bench has never run. A number that has not been measured does not get written.

What is comparedAgileTTS — measurement and sourceElevenLabs
Italian pronunciation (amounts, dates, acronyms, POD, IBAN)241 cases out of 241, 0 errors — banco/lessico/verifica_lessico.py --autoprova, measured 30/9/2026measurement pending the vault key
The service does not alter the engine's audiothe same bytes as the engine, in block and in streaming; the service's overhead is 10.7 ms p50 in block and 3.2 ms in streaming — banco/tts/prova_parita_fronte_motore.py (36/36), measured 29/9/2026measurement pending the vault key
An honest refusal when the queue is fullthe 503 arrives before the first byte, with Retry-After: 0 truncated streams and 0 errors over 40 runs — banco/tts/prova_carico_fronte.py §F, measured 29/9/2026measurement pending the vault key
A restart does not throw away whoever is speaking3 phone calls out of 3 get their audio (they were 0 out of 3), address silent for 0.25 s — banco/tts/capienza_chiusura.py, measured 30/9/2026 in docs/NOVITA.mdmeasurement pending the vault key
Spoken texts are left nowhere0 traces across 9 files of the front end's disk, 26 paths probed with 12 needles (the journal included) — fronte/prova_ritenzione.py, measured 29/9/2026measurement pending the vault key
Three conversations at once above real timenot yet: on the real engine the real-time factor is 1.41 with one conversation and 2.83 with three — docs/OBIETTIVI.md obj. 3, measured 21/9/2026. The goal is open and the number is written where it can be seenmeasurement pending the vault key

The differences that need no bench — they are verified by reading the repository, not by talking:

How to use it

Endpoint https://api.agiletts.agile.software. Key in the Authorization: Bearer ats_… header (or X-Api-Key). The body is that of OpenAI's /v1/audio/speech.

curl https://api.agiletts.agile.software/v1/audio/speech \
  -H "Authorization: Bearer $AGILETTS_KEY" -H "Content-Type: application/json" \
  -d '{"model":"agiletts","input":"Buongiorno, come posso aiutarla?","voice":"serena","response_format":"wav"}' \
  -o saluto.wav

With the official OpenAI client you just change base_url and the key:

from openai import OpenAI
client = OpenAI(base_url="https://api.agiletts.agile.software/v1", api_key=AGILETTS_KEY)
with client.audio.speech.with_streaming_response.create(model="agiletts", voice="serena",
        input="Il corso dura sei mesi.", response_format="pcm") as r:
    r.stream_to_file("frase.pcm")   # pcm = 24 kHz, 16 bit, mono

Endpoints

Method and pathWhat it does
POST /v1/audio/speechmodel = agiletts, input (≤ 2000 characters), voice, response_format = wav | pcm (24 kHz) | pcm16k (telephony) | mp3, speed 0.5–2.0, stream: true to receive the audio in chunks while it is synthesized (pcm/pcm16k only)
GET /v1/modelsthe available models
GET /v1/voicesthe voices the key can use (id, language, rate)
GET /v1/usageyour key's usage: requests, characters, milliseconds, audio produced — never the texts
GET /healthstate of the front end and the engine

Errors

HTTPcodemeaning
401KEY_MISSING, KEY_INVALIDkey missing or unknown
403KEY_REVOKED, SCOPE_NOT_ALLOWEDkey revoked or without the permission (speech, stream, voices)
404UNKNOWN_VOICE, UNKNOWN_MODELvoice or model that does not exist
413TEXT_TOO_LONGover 2000 characters
429RATE_LIMIT, QUOTA_EXCEEDEDtoo many requests per minute or monthly character quota exhausted
503BUSY, ENGINE_DOWNengine busy or unavailable: Retry-After says when to retry. No silent fallback to third parties.

Rules

For integrators

To move a product onto the front end — one at a time, on the owner's "go" and with the rollback ready — the step-by-step guide is in docs/ADOZIONE.md. For those who prefer the command line there is client/agiletts-cli.py, the pure standard-library client: synthesis to a file, reading models, voices and your key's usage.