L’API di riconoscimento vocale di Hushscript accetta audio registrato tramite
/v1/, poi permette al tuo script di controllare il job e leggere la
trascrizione. È un flusso di trascrizione online, non un endpoint per lo
streaming in diretta o per accedere direttamente al modello di riconoscimento.
Il server MCP usa lo stesso account, saldo e token bearer se il tuo
client preferisce gli strumenti alle chiamate HTTP.
Trascrizione audio e video tramite API
L’API di trascrizione audio accetta file audio già preparati, comprese le registrazioni vocali. Per un’integrazione STT (speech-to-text), invia file registrati: lo streaming in diretta dal microfono non è disponibile. Per trascrivere un video, carica così com’è un file MP4 o MOV con una traccia audio: il server legge la traccia audio e ignora il video. Estrai prima l’audio da qualsiasi altro formato video; l’API non accetta un URL video. Il flusso nel browser è spiegato nella pagina Da video a testo.
Avvio rapido
L’API richiede un token di accesso personale, e ci sono due modi per
ottenerne uno. Una persona ne crea uno sotto Token nella
pagina MCP dell’account, sceglie i
suoi scope e decide se può acquistare minuti. Oppure un agente apre un
proprio account senza un titolare umano: POST /v1/agent/accounts
avvia una registrazione a pagamento, e
POST /v1/agent/accounts/{signup_id}/claim scambia il suo segreto monouso di
attivazione con un account vero e un primo token. In entrambi i casi il
token viene mostrato una sola volta e ha la forma
hsr1:<region>:pat.<id>.<secret>. Anche un token generato tramite l’accesso
OAuth del server MCP funziona qui; vedi Connessione. Un
token non può mai generare, elencare o revocare altri token, e un account ne
può avere al massimo 25 attivi; il flusso completo per gli account agente,
inclusa la rotazione delle credenziali, è la guida
Uso automatizzato.
Una volta ottenuto un token, chiama l’API direttamente. Questo esempio rappresenta un nuovo account personale prima della verifica della carta o di un acquisto; un account creato da un agente parte con il pacchetto di minuti che ha pagato:
curl https://api.hushscript.com/v1/account \
-H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"
{
"balance_seconds": 0,
"held_seconds": 0,
"credits_expire_at": null,
"card_on_file": false,
"data_region": "eu",
"limits": {
"max_active_jobs": 50,
"max_daily_seconds": 144000,
"active_jobs": 0,
"used_today_seconds": 0
}
}
La risposta contiene il saldo in secondi, i secondi trattenuti dai job in
corso, credits_expire_at (sempre null, perché i minuti non scadono), la presenza di una carta salvata, la regione
dei dati e i limiti di ammissione (max_active_jobs, max_daily_seconds, e
quanto è già stato usato). Il limite giornaliero è il limite effettivo attuale dell’account, non un valore da fissare nel codice. POST /v1/uploads controlla i minuti disponibili, non la carta: senza minuti sufficienti restituisce 3001 insufficient_balance.
L’API di riconoscimento vocale è gratuita?
Non esiste un piano API gratuito generale, ma puoi provare il flusso prima di scrivere codice: l’anteprima pubblica trascrive fino a cinque minuti di una registrazione prima dell’accesso. Un account personale idoneo riceve poi 30 minuti gratuiti dopo la verifica della carta (vedi i prezzi per i dettagli); un account creato da un agente non riceve i minuti di benvenuto e parte con il pacchetto acquistato durante la registrazione. Un job API completo richiede comunque un account e minuti.
Automatizzare dall’inizio alla fine
Le stesse chiamate /v1/ funzionano con un token creato da una persona nell’app o ottenuto da un agente dopo l’attivazione dell’account a seguito della registrazione a pagamento (vedi Uso automatizzato). Salvare una carta richiede il Checkout ospitato in un browser; un agente può guidarlo. Gli acquisti successivi fuori sessione possono comunque essere rifiutati se l’emittente della carta richiede un’autenticazione.
-
Leggi l’account.
GET /v1/account. Se devi acquistare minuti ecard_on_fileè false, salva prima una carta. -
Salva una carta, una volta sola.
POST /v1/billing/setup-sessionrestituisce uncheckout_url, unsession_ide unexpires_at:curl -X POST https://api.hushscript.com/v1/billing/setup-session \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_a1B2c3D4e5F6g7H8", "session_id": "seti_1PxYzQ2eZvKYlo2C", "expires_at": "2026-09-11T15:45:00Z" }Apri l’URL in un browser che controlli e completa la pagina Stripe ospitata; non viene addebitato nulla e Hushscript non vede mai la carta. Poi
GET /v1/billing/cardsla elenca con il suo id.POST /v1/billing/cards/defaultcambia quella predefinita se l’account ne possiede più di una. -
Acquista minuti.
GET /v1/billing/packselenca i cinque pacchetti conid,seconds,amountecurrency:curl https://api.hushscript.com/v1/billing/packs \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"POST /v1/billing/purchaseconpack,quick_payment_method_id(l’id della carta salvata) e unidempotency_keyaddebita la carta fuori sessione e risponde con il nuovobalance_seconds:curl -X POST https://api.hushscript.com/v1/billing/purchase \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293" \ -H "Content-Type: application/json" \ -d '{ "pack": "300min", "quick_payment_method_id": "pm_2QeT4bY7uX9mK3nP", "idempotency_key": "purchase-2026-09-11-02" }'{ "balance_seconds": 18000 }Questo richiede lo scope
billing, la fatturazione attivata sul token e la fatturazione attivata per l’account. Una richiesta senza l’id di una carta, o con una carta rifiutata, viene respinta con4021 pat_purchase_requires_app; una carta che l’emittente vuole verificare viene respinta con4023 pat_purchase_requires_authentication. Nessuno dei due errori apre una pagina che non può essere completata. -
Carica.
POST /v1/uploadsconsize_bytes,duration_seconds(da 15 secondi a 10 ore), untitleopzionale,transcription_options,matter_codee unidempotency_key:curl -X POST https://api.hushscript.com/v1/uploads \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293" \ -H "Content-Type: application/json" \ -d '{ "size_bytes": 41943040, "duration_seconds": 1200, "title": "Q3 board call", "transcription_options": { "speaker_detection": true }, "idempotency_key": "upload-2026-09-11-02" }'matter_codeè testo libero di al massimo 64 caratteri, e ha senso solo per un token che appartiene a uno spazio di lavoro: compare accanto al job nell’attività del pool e nei report di utilizzo di quello spazio di lavoro. Uno spazio di lavoro la cui politica sui codici pratica è impostata come obbligatoria rifiuta un caricamento che arriva senza, conorg_matter_code_required.client_codeviene accettato e ignorato, perché il cliente è un attributo della pratica, impostato da un amministratore dello spazio di lavoro.Il caricamento riserva credito e restituisce un
job_idcon una prima pagina di URL prefirmati per le parti:{ "job_id": "job_5e2a91cf4d7b6081a9f3c2e4b5d6a7c8", "part_urls": [ { "n": 1, "url": "https://r2.hushscript.com/uploads/job_5e2a91cf.../part-1?X-Amz-Signature=..." } ] }Esegui
PUTdi ogni parte sul suo URL (parti da 32 MiB per impostazione predefinita, l’ultima più piccola):curl -X PUT "https://r2.hushscript.com/uploads/job_5e2a91cf.../part-1?X-Amz-Signature=..." \ --data-binary @part-01.binRecupera altre pagine da
GET /v1/uploads/{job}/part-urls?start=<n>, e chiamaPOST /v1/uploads/{job}/heartbeatben entro il timeout di inattività di 20 minuti durante un trasferimento lungo. Quando gli URL prefirmati non sono disponibili, o una parte fallisce,PUT /v1/uploads/{job}/parts/{n}invia invece i byte di quella parte attraverso l’API; unPUTripetuto sostituisce la parte, quindi i nuovi tentativi sono sicuri. Formati supportati: mp3, m4a, mp4 o mov (si usa la traccia audio, le tracce video vengono ignorate), wav, flac, ogg o opus, verificati sul server; estrai l’audio da qualsiasi altro formato video prima di caricarlo. -
Avvia e attendi.
POST /v1/uploads/{job}/completeconnedetagdi ogni parte inviata a un URL prefirmato (omettipartsse ogni parte è passata attraverso l’API):curl -X POST https://api.hushscript.com/v1/uploads/job_5e2a91cf4d7b6081a9f3c2e4b5d6a7c8/complete \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293" \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "n": 1, "etag": "\"9f86d081884c7d65\"" } ] }'Poi interroga periodicamente
GET /v1/jobs/{id}:statepassa attraversouploading,queuedeprocessingfino adoneofailed, e un job completato porta untranscript_id:curl https://api.hushscript.com/v1/jobs/job_5e2a91cf4d7b6081a9f3c2e4b5d6a7c8 \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"{ "id": "job_5e2a91cf4d7b6081a9f3c2e4b5d6a7c8", "state": "done", "transcript_id": "trs_2b6e1d4a9f7c3088a1b2c3d4e5f6a7b9" } -
Leggi il risultato.
GET /v1/transcripts/{id}restituisce i metadati e il corpo completo, con i nomi dei parlanti, la lingua rilevata, i tag e la data di eliminazione automatica:curl https://api.hushscript.com/v1/transcripts/trs_2b6e1d4a9f7c3088a1b2c3d4e5f6a7b9 \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"GET /v1/transcriptsrestituisce l’elenco a pagine.
Le opzioni di trascrizione sono quelle dell’app, identiche: language_code
oppure il rilevamento automatico, speaker_detection, medical_mode
(richiede language_code in en, es, fr o de, fatturata al +100%),
translation_targets (+25% per lingua), multichannel, keyterms_prompt,
un prompt in testo libero, e i dictionary_ids e il prompt_preset_id
salvati che GET /v1/transcription-context elenca.
Una parte dell’account resta ancora solo per MCP. Importare da un link,
modificare o eliminare trascrizioni, gli Insights, le esportazioni, salvare
dizionari e preset dei prompt, e le impostazioni dell’account non hanno
ancora una rotta /v1/; il server MCP copre tutto questo con lo
stesso token.
Autenticazione
Ogni chiamata /v1/ porta un token bearer nell’intestazione
Authorization, verificato rispetto agli stessi scope che usa il server
MCP:
| Scope | Cosa consente |
|---|---|
transcripts:read |
Leggere ed esportare le trascrizioni, i loro metadati e l’elenco degli elementi eliminati |
transcripts:write |
Modificare, taggare, tradurre, ripristinare ed eliminare le trascrizioni |
transcribe |
Caricare registrazioni, importare da un link e avviare trascrizioni |
insights |
Leggere, generare ed eliminare gli Insights |
context |
Gestire i dizionari salvati e i preset dei prompt |
account:read |
Leggere saldo, utilizzo, transazioni e trattenute |
settings:write |
Modificare le impostazioni dell’account |
org:read |
Leggere i membri dello spazio di lavoro, l’attività del pool, le fatture e il registro di audit |
org:write |
Modificare i diritti dei membri, programmare il passaggio alla custodia aziendale (permanente), e applicare o revocare blocchi legali |
export |
Richiedere un’esportazione completa dell’account, verificarne lo stato e scaricarla |
billing |
Salvare una carta e acquistare pacchetti di minuti |
Una chiamata al di fuori degli scope del token fallisce con pat_scope_missing, con
stato 403. Lo scope billing resta inerte a meno che la fatturazione non sia attivata
sia sul token sia sull’account. Una chiamata di fatturazione con uno dei due
interruttori spento fallisce con lo stesso pat_scope_missing; rigenerare il token
non attiva l’interruttore dell’account. Un token non può creare, elencare o revocare
token, e un account ne può avere al massimo 25 attivi.
Questi 11 scope sono selezionabili da chi chiama. pat:rotate è uno scope separato,
concesso al primo token di un account agente e ai suoi successori ruotati; permette a
quel token di sostituire se stesso, non di gestire altri token. Non puoi selezionarlo
quando crei un token nell’app.
Endpoint
Il documento OpenAPI di produzione elenca 38 operazioni metodo/percorso su 37 percorsi. Ogni operazione qui sotto è vincolata allo scope indicato:
| Metodo | Percorso | Scope |
|---|---|---|
POST |
/v1/agent/accounts |
none |
POST |
/v1/agent/accounts/{signup_id}/claim |
none |
POST |
/v1/agent/credentials/rotate |
pat:rotate |
GET |
/v1/account |
account:read |
POST |
/v1/billing/setup-session |
billing |
GET |
/v1/billing/cards |
billing |
POST |
/v1/billing/cards/default |
billing |
GET |
/v1/billing/packs |
billing |
POST |
/v1/billing/purchase |
billing |
GET |
/v1/billing/transactions |
account:read |
GET |
/v1/billing/ledger |
account:read |
GET |
/v1/billing/holds |
account:read |
POST |
/v1/uploads |
transcribe |
GET |
/v1/uploads/{job}/part-urls |
transcribe |
PUT |
/v1/uploads/{job}/parts/{n} |
transcribe |
POST |
/v1/uploads/{job}/heartbeat |
transcribe |
POST |
/v1/uploads/{job}/complete |
transcribe |
GET |
/v1/jobs |
transcribe |
GET |
/v1/jobs/{id} |
transcribe |
GET |
/v1/transcripts |
transcripts:read |
GET |
/v1/transcripts/deleted |
transcripts:read |
GET |
/v1/transcripts/{id} |
transcripts:read |
GET |
/v1/transcription-context |
context |
GET |
/v1/org |
org:read |
GET |
/v1/org/members |
org:read |
PATCH |
/v1/org/members/{user_id} |
org:write |
GET |
/v1/org/matters |
org:read |
GET |
/v1/org/transcripts |
org:read |
POST |
/v1/org/transcripts/{id}/hold |
org:write |
DELETE |
/v1/org/transcripts/{id}/hold |
org:write |
POST |
/v1/org/custody |
org:write |
GET |
/v1/org/invoices |
org:read |
GET |
/v1/org/ledger |
org:read |
GET |
/v1/org/ledger.csv |
org:read |
GET |
/v1/org/usage |
org:read |
GET |
/v1/org/usage.csv |
org:read |
GET |
/v1/org/audit |
org:read |
GET |
/v1/org/audit.csv |
org:read |
/v1/agent/accounts avvia una registrazione headless senza ancora un
token, /v1/agent/accounts/{signup_id}/claim trasforma una registrazione a
pagamento in un account vero e nel suo primo token, e
/v1/agent/credentials/rotate genera un successore per il token chiamante
e lo ritira al primo uso del successore, senza toccare nessun’altra
credenziale sull’account. La guida
Uso automatizzato copre tutti e tre per intero.
Ogni elenco accetta un limit e un cursor opaco, e risponde con un
next_cursor che è null sull’ultima pagina. Restituisci il cursore
invariato; codifica la posizione, così una pagina non viene mai saltata o
ripetuta quando arrivano nuove righe tra una chiamata e l’altra.
La definizione completa e aggiornata, con parametri e schemi di risposta per ogni operazione, è il documento OpenAPI: trattalo come fonte di verità rispetto a questa tabella. Viene servito a qualsiasi token bearer indipendentemente dallo scope, così un client può recuperarlo con le credenziali che già possiede.
Interfaccia MCP
Preferisci gli strumenti alle chiamate HTTP dirette? Il server MCP espone lo stesso account tramite 56 strumenti anziché questi endpoint, per un client che usa già MCP invece di REST. Pubblica solo gli strumenti consentiti dagli scope del token connesso.
Limiti
Le richieste effettuate con il token di un account umano sono limitate a 1.200 al minuto per token. I token ruotati di un account agente condividono quel budget a livello di account. Le rotte di fatturazione che chiamano Stripe condividono un budget più stretto di 60 al minuto per account per i chiamanti PAT: sessione di configurazione, acquisto, cambio della carta predefinita, rimozione della carta e richieste dell’elenco carte non presenti nella cache. La limitazione ordinaria risponde 429 rate_limited con Retry-After in secondi; attendi quel tempo prima di riprovare. Gli acquisti di un account agente o effettuati con il PAT di un account umano condividono un tetto di 3 tentativi per ogni intervallo mobile di 24 ore per account. L’acquisto di registrazione dell’agente conta; contano anche i rifiuti o gli errori dopo che un tentativo è stato riservato. Un acquisto da una sessione browser umana è escluso. Un rifiuto per il tetto risponde con HTTP 429, 4038 agent_purchase_capped e Retry-After. Le registrazioni possono durare da 15 secondi a 10 ore. GET /v1/account riporta gli attuali limiti di ammissione dell’account (max_active_jobs, max_daily_seconds).
Sandbox
Non esiste una sandbox generale per la trascrizione: le normali chiamate /v1/ vengono eseguite su account reali e gli acquisti spendono denaro vero. L’eccezione è la convalida della registrazione: POST /v1/agent/accounts accetta dry_run: true, restituisce un id di registrazione dry_ non utilizzabile per attivare un account e non apre alcuna sessione Stripe né alcun account.
Errori
Un errore è un corpo JSON che contiene un code numerico stabile e uno slug
error, allo stato HTTP mostrato sotto. I corpi di errore /v1/ sono una
proiezione congelata: error, code e un insieme fisso di chiavi di
dettaglio. La struttura degli errori di /api non è congelata e può contenere
altri campi. I codici che un chiamante automatizzato deve gestire:
| Stato | Codice | Slug | Significato |
|---|---|---|---|
| 401 | 2000 | unauthorized |
Token bearer mancante o non valido |
| 403 | 2022 | pat_forbidden |
La rotta non accetta alcun token |
| 403 | 2023 | pat_scope_missing |
Al token manca lo scope richiesto da questa chiamata, oppure la fatturazione è disattivata per l’account |
| 403 | 4021 | pat_purchase_requires_app |
Non è stata indicata nessuna carta salvata, oppure l’addebito è stato rifiutato; nessun importo è stato addebitato |
| 403 | 4023 | pat_purchase_requires_authentication |
L’emittente della carta richiede una verifica che chi chiama non può completare; la carta in sé è valida |
| 402 | 3001 | insufficient_balance |
Saldo insufficiente per ammettere il job |
| 402 | 3002 | card_declined |
La carta salvata è stata rifiutata |
| 402 | 3003 | org_insufficient_balance |
Il pool dello spazio di lavoro che finanzia questo caricamento è insufficiente |
| 404 | 4000 | not_found |
Nessun job, caricamento o risorsa di questo tipo |
| 409 | 4001 | wrong_state |
La risorsa non si trova in uno stato che consente questa operazione |
| 422 | 1021 | duration_out_of_range |
La durata dichiarata è inferiore a 15 secondi o superiore a 10 ore |
| 429 | 4038 | agent_purchase_capped |
L’account ha esaurito i tentativi di acquisto consentiti tramite token; attendi il tempo indicato da Retry-After |
| 429 | 5000 | rate_limited |
Troppe richieste; attendi il valore di Retry-After |
| 502 | 6001 | provider_error |
Un servizio a monte è fallito |
| 500 | 9000 | internal_error |
Un errore inatteso del server |
Il documento OpenAPI indica il codice esatto che ogni operazione può
restituire, e il server MCP pubblica il catalogo completo come risorsa
hushscript://error-codes.