L’API de transcription Hushscript accepte l’audio enregistré via /v1/, puis
permet à votre script de suivre la tâche et de lire la transcription. Ce
parcours de transcription en ligne ne propose ni diffusion en direct ni
accès direct à un modèle de reconnaissance vocale.
Le serveur MCP utilise le même compte, le même solde et le même jeton
porteur si votre client préfère des outils aux appels HTTP.
Transcription audio et vidéo via l’API
L’API de transcription audio accepte des fichiers audio préparés, y compris des enregistrements vocaux. Pour une intégration STT (speech-to-text), envoyez des fichiers enregistrés ; la diffusion en direct du microphone n’est pas prise en charge. Pour transcrire une vidéo, téléversez tel quel un fichier MP4 ou MOV avec une piste audio : le serveur lit la piste audio et ignore la vidéo. Extrayez d’abord l’audio de tout autre format vidéo ; l’API n’accepte pas d’URL de vidéo. Le parcours dans le navigateur est expliqué sur la page vidéo en texte.
Démarrage rapide
L’API nécessite un jeton d’accès personnel, et il existe deux façons d’en
détenir un. Une personne en crée un sous Tokens sur la
page MCP du compte, choisit ses
scopes, et décide s’il peut acheter des minutes. Ou un agent ouvre son propre
compte sans titulaire humain : POST /v1/agent/accounts démarre une
inscription payante, et POST /v1/agent/accounts/{signup_id}/claim échange
son secret à usage unique contre un compte réel et un premier jeton. Dans les deux cas, le jeton est affiché une seule fois et ressemble à
hsr1:<region>:pat.<id>.<secret>. Un jeton émis via la connexion OAuth du
serveur MCP fonctionne aussi ici ; voir Se connecter. Un jeton
ne peut jamais créer, lister ni révoquer d’autres jetons, et un compte
détient au maximum 25 jetons actifs ; le guide présente le parcours complet du compte d’agent,
y compris la rotation des identifiants :
Transcription automatique pour agents et scripts.
Une fois le jeton obtenu, appelez directement l’API. Cet exemple représente un nouveau compte personnel avant vérification de carte ou achat ; un compte créé par un agent commence avec le pack de minutes acheté :
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 réponse indique le solde en secondes, les secondes réservées par les tâches
en cours, credits_expire_at (toujours null, car les minutes n’expirent pas), la présence d’une carte enregistrée,
la région des données et les limites d’admission (max_active_jobs,
max_daily_seconds et les ressources déjà utilisées). La limite quotidienne
est la limite effective actuelle du compte ; ne la codez pas en dur.
POST /v1/uploads vérifie les minutes disponibles, pas la carte : si elles
sont insuffisantes, il renvoie 3001 insufficient_balance.
L’API de transcription est-elle gratuite ?
Il n’existe pas d’offre gratuite générale pour l’API, mais vous pouvez essayer le parcours avant d’écrire du code : l’aperçu public transcrit jusqu’à cinq minutes d’un enregistrement avant la connexion. Un compte personnel éligible reçoit ensuite 30 minutes gratuites après vérification de carte (voir les tarifs pour les conditions). Un compte créé par un agent ne reçoit pas de minutes de bienvenue et commence avec le pack acheté à l’inscription. Dans les deux cas, une transcription complète via l’API nécessite un compte et des minutes.
Automatiser de bout en bout
Les mêmes appels /v1/ fonctionnent avec un jeton créé par une personne dans
l’application ou obtenu par un agent après une inscription payante (voir
Transcription automatique pour agents et scripts). Enregistrer une carte nécessite une page
Checkout hébergée dans un navigateur ; un agent peut piloter ce navigateur.
Les achats ultérieurs hors session peuvent être refusés si l’émetteur de la
carte exige une authentification.
-
Lire le compte.
GET /v1/account. Si vous devez acheter des minutes et quecard_on_filevaut false, enregistrez d’abord une carte. -
Enregistrer une carte, une fois.
POST /v1/billing/setup-sessionrenvoie uncheckout_url, unsession_idet 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" }Ouvrez l’URL dans un navigateur que vous contrôlez et complétez la page Stripe hébergée ; rien n’est débité et Hushscript ne voit jamais la carte. Ensuite,
GET /v1/billing/cardsla liste avec son identifiant.POST /v1/billing/cards/defaultchange la carte par défaut si le compte en détient plusieurs. -
Acheter des minutes.
GET /v1/billing/packsliste les cinq packs avecid,seconds,amountetcurrency:curl https://api.hushscript.com/v1/billing/packs \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"POST /v1/billing/purchaseavecpack,quick_payment_method_id(l’identifiant de la carte enregistrée) et unidempotency_keydébite la carte hors session et répond avec le nouveaubalance_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 }Cela nécessite le scope
billing, la facturation activée sur le jeton et la facturation activée pour le compte. Un corps sans identifiant de carte, ou une carte refusée, est rejeté avec4021 pat_purchase_requires_app; une carte pour laquelle l’émetteur exige une authentification est rejetée avec4023 pat_purchase_requires_authentication. Ni l’un ni l’autre n’ouvre une page que personne ne peut terminer. -
Téléverser.
POST /v1/uploadsavecsize_bytes,duration_seconds(de 15 secondes à 10 heures), untitleoptionnel,transcription_options,matter_codeet 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_codeest un texte libre de 64 caractères au plus, et il n’a de sens que pour un jeton appartenant à un espace de travail : il apparaît en regard de la tâche dans le registre et les rapports d’usage de cet espace de travail. Un espace de travail dont la politique de dossiers est réglée sur obligatoire rejette un téléversement sans code, avecorg_matter_code_required.client_codeest accepté et ignoré, car le client est un attribut du dossier, défini par un administrateur de l’espace de travail.Cet appel réserve des crédits et renvoie un
job_idplus une première page d’URL de parties présignées :{ "job_id": "job_5e2a91cf4d7b6081a9f3c2e4b5d6a7c8", "part_urls": [ { "n": 1, "url": "https://r2.hushscript.com/uploads/job_5e2a91cf.../part-1?X-Amz-Signature=..." } ] }Faites un
PUTde chaque partie vers son URL (parties de 32 MiB par défaut, la dernière plus petite) :curl -X PUT "https://r2.hushscript.com/uploads/job_5e2a91cf.../part-1?X-Amz-Signature=..." \ --data-binary @part-01.binRécupérez les pages suivantes via
GET /v1/uploads/{job}/part-urls?start=<n>, et appelezPOST /v1/uploads/{job}/heartbeatbien avant le délai d’inactivité de 20 minutes lors d’un transfert long. Quand les URL présignées sont indisponibles, ou qu’une partie échoue,PUT /v1/uploads/{job}/parts/{n}envoie plutôt les octets de cette partie via l’API ; unPUTrépété remplace la partie, donc les nouvelles tentatives sont sûres. Formats acceptés : mp3, m4a, mp4 ou mov (la piste audio est utilisée, les pistes vidéo sont ignorées), wav, flac, ogg ou opus, vérifiés côté serveur ; extrayez l’audio de tout autre format vidéo avant de le téléverser. -
Démarrer et attendre.
POST /v1/uploads/{job}/completeavec lenet l’etagde chaque partie envoyée à une URL présignée (omettezpartssi toutes les parties sont passées par 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\"" } ] }'Ensuite, interrogez
GET /v1/jobs/{id}:statepasse paruploading,queuedetprocessingjusqu’àdoneoufailed, et une tâche terminée comprend 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" } -
Lire le résultat.
GET /v1/transcripts/{id}renvoie les métadonnées et le texte complet, avec les noms des locuteurs, la langue détectée, les étiquettes et la date de suppression automatique :curl https://api.hushscript.com/v1/transcripts/trs_2b6e1d4a9f7c3088a1b2c3d4e5f6a7b9 \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"GET /v1/transcriptspagine la liste.
Les options de transcription sont celles de l’application, à l’identique :
language_code ou détection automatique, speaker_detection, medical_mode
(nécessite language_code en en, es, fr ou de, facturé à +100 %),
translation_targets (+25 % par langue), multichannel, keyterms_prompt,
un prompt en texte libre, et les dictionary_ids et prompt_preset_id
enregistrés que liste GET /v1/transcription-context.
Certaines fonctions du compte restent accessibles uniquement via MCP :
importation depuis un lien, modification ou suppression de transcriptions,
Insights, exports, enregistrement de dictionnaires et de modèles d’invite,
et paramètres du compte. Elles n’ont pas encore de route /v1/ ; le
serveur MCP les couvre toutes avec le même jeton.
Authentification
Chaque appel /v1/ porte un jeton porteur dans l’en-tête Authorization,
vérifié selon les mêmes scopes que ceux qu’utilise le serveur MCP :
| Scope | Autorisations |
|---|---|
transcripts:read |
Lire et exporter les transcriptions, leurs métadonnées et la liste des éléments supprimés |
transcripts:write |
Modifier, étiqueter, traduire, restaurer et supprimer des transcriptions |
transcribe |
Téléverser des enregistrements, importer depuis un lien et lancer des transcriptions |
insights |
Lire, générer et supprimer des Insights |
context |
Gérer les dictionnaires enregistrés et les modèles d’invite |
account:read |
Lire le solde, l’utilisation, les transactions et les réservations |
settings:write |
Modifier les paramètres du compte |
org:read |
Lire les membres de l’espace de travail, le registre, les factures et le journal d’audit |
org:write |
Modifier les droits des membres, planifier le passage à la garde de l’organisation (permanente), et placer ou lever une conservation légale |
export |
Demander un export complet du compte, vérifier son statut et le télécharger |
billing |
Enregistrer une carte et acheter des packs de minutes |
Un appel en dehors des scopes du jeton échoue avec pat_scope_missing, en 403. Le
scope billing ne permet aucune action tant que la facturation n’est pas
activée à la fois sur le jeton et sur le compte. Un appel de facturation avec l’un des deux réglages
désactivé échoue avec le même pat_scope_missing ; réémettre le jeton n’active pas
le réglage du compte. Un jeton ne peut pas créer, lister ni révoquer de jetons,
et un compte détient au maximum 25 jetons actifs.
Ces 11 scopes sont sélectionnables par l’appelant. pat:rotate est un scope à part,
accordé au premier jeton d’un compte d’agent et à ses successeurs renouvelés ; il
permet à ce jeton de se remplacer lui-même, pas de gérer d’autres jetons. Vous ne
pouvez pas le sélectionner en créant un jeton dans l’application.
Points de terminaison
Le document OpenAPI de production liste 38 opérations méthode/chemin sur 37 chemins. Chaque opération ci-dessous est protégée par le scope indiqué :
| Méthode | Chemin | 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 ouvre une inscription sans interface et sans jeton pour
l’instant, /v1/agent/accounts/{signup_id}/claim transforme une inscription
payée en un compte réel et son premier jeton, et
/v1/agent/credentials/rotate génère un successeur pour le jeton appelant et
le retire dès que le successeur sert pour la première fois, sans toucher à aucun autre identifiant du compte. Le guide
Transcription automatique pour agents et scripts couvre les trois de bout en bout.
Chaque liste accepte un limit et un cursor opaque, et renvoie un
next_cursor qui vaut null sur la dernière page. Renvoyez le curseur
inchangé ; il encode la position, si bien qu’une page n’est jamais sautée ni
répétée quand des lignes arrivent entre deux appels.
La définition complète et à jour, avec les paramètres et les schémas de réponse de chaque opération, est le document OpenAPI : traitez-le comme la source de vérité plutôt que ce tableau. Il est accessible avec tout jeton porteur quel que soit son scope, si bien qu’un client peut le récupérer avec les identifiants qu’il détient déjà.
Interface MCP
Vous préférez des outils au HTTP brut ? Le serveur MCP place le même compte derrière 56 outils au lieu de ces points de terminaison, pour un client qui utilise déjà MCP plutôt que REST. Il annonce uniquement les outils autorisés par les scopes du jeton connecté.
Limites
Les requêtes effectuées avec le jeton d’un compte humain sont limitées à 1 200 par minute et par jeton. Les jetons renouvelés d’un compte d’agent partagent ce budget à l’échelle du compte. Les routes de facturation qui appellent Stripe partagent un budget plus strict de 60 par minute et par compte pour les appelants PAT : session de configuration, achat, changement de carte par défaut, suppression de carte et requêtes de liste des cartes non servies par le cache. La limitation ordinaire répond 429 rate_limited avec Retry-After en secondes ; attendez ce délai avant de réessayer. Les achats d’un compte d’agent ou effectués avec le PAT d’un compte humain partagent un plafond de 3 tentatives par période glissante de 24 heures et par compte. L’achat à l’inscription de l’agent compte ; les refus ou erreurs après réservation d’une tentative comptent aussi. Un achat depuis une session de navigateur humaine en est exempté. Un refus dû au plafond répond en HTTP 429 avec 4038 agent_purchase_capped et Retry-After. Les enregistrements peuvent durer de 15 secondes à 10 heures. GET /v1/account indique les limites d’admission actuelles du compte (max_active_jobs, max_daily_seconds).
Bac à sable
Il n’existe pas de bac à sable général pour la transcription : les appels /v1/ ordinaires utilisent des comptes réels, et les achats dépensent de l’argent réel. L’exception est la validation d’inscription : POST /v1/agent/accounts accepte dry_run: true, renvoie un identifiant d’inscription dry_ qui ne permet pas de récupérer un compte, et n’ouvre aucune session Stripe ni aucun compte.
Erreurs
Une erreur est un corps JSON qui porte un code numérique stable et un slug
error, au statut HTTP indiqué ci-dessous. Les corps d’erreur /v1/ sont
une projection figée : error, code, et un ensemble fixe de clés de
détail. La structure des erreurs de /api n’est pas figée et peut en porter
davantage. Les codes qu’un appelant automatisé doit gérer :
| Statut | Code | Slug | Signification |
|---|---|---|---|
| 401 | 2000 | unauthorized |
Jeton porteur manquant ou invalide |
| 403 | 2022 | pat_forbidden |
La route n’accepte aucun jeton |
| 403 | 2023 | pat_scope_missing |
Le jeton n’a pas le scope requis pour cet appel, ou la facturation est désactivée sur le compte |
| 403 | 4021 | pat_purchase_requires_app |
Aucune carte enregistrée n’a été nommée, ou le paiement a été refusé ; rien n’a été débité |
| 403 | 4023 | pat_purchase_requires_authentication |
L’émetteur de la carte demande une vérification que l’appelant ne peut pas effectuer ; la carte elle-même est valide |
| 402 | 3001 | insufficient_balance |
Solde insuffisant pour accepter la tâche |
| 402 | 3002 | card_declined |
La carte enregistrée a été refusée |
| 402 | 3003 | org_insufficient_balance |
La réserve de l’espace de travail qui finance ce téléversement est insuffisante |
| 404 | 4000 | not_found |
Tâche, téléversement ou ressource introuvable |
| 409 | 4001 | wrong_state |
La ressource n’est pas dans un état qui permette cela |
| 422 | 1021 | duration_out_of_range |
La durée déclarée est inférieure à 15 secondes ou supérieure à 10 heures |
| 429 | 4038 | agent_purchase_capped |
Le compte a atteint son plafond de tentatives d’achat avec un jeton ; attendez le délai Retry-After |
| 429 | 5000 | rate_limited |
Trop de requêtes ; attendez Retry-After |
| 502 | 6001 | provider_error |
Un service en amont a échoué |
| 500 | 9000 | internal_error |
Une erreur serveur inattendue |
Le document OpenAPI nomme le code exact que chaque opération peut renvoyer,
et le serveur MCP publie le catalogue complet sous forme de ressource
hushscript://error-codes.