Hushscript también responde a llamadas REST simples, para agentes y scripts que prefieren llamar a un endpoint HTTP antes que ejecutar un cliente MCP. Es la misma cuenta, el mismo saldo y los mismos tokens bearer en todo momento: nada aquí cambia cómo se cobra o se almacena la transcripción.
Inicio rápido
La API necesita un token de acceso personal, y hay dos formas de conseguir
uno. Una persona crea uno en Tokens, en la página de MCP de la
cuenta, elige sus scopes y decide si
puede comprar minutos. O un agente abre su propia cuenta sin ninguna persona
involucrada: POST /v1/agent/accounts inicia un registro pagado, y
POST /v1/agent/accounts/{signup_id}/claim cambia su secreto de reclamo de
un solo uso por una cuenta real y un primer token. De cualquier forma, el
token se muestra una sola vez y tiene la forma
hsr1:<region>:pat.<id>.<secret>. Un token generado mediante el inicio de
sesión OAuth del servidor MCP también funciona aquí; consulta
Conéctate. Un token nunca puede generar, listar ni revocar
otros tokens, y una cuenta tiene como máximo 25 activos; el flujo completo de
cuenta de agente, incluida la rotación de credenciales, está en la guía de
Uso automatizado.
Una vez que tienes un token, llama a la API directamente:
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": 3,
"max_daily_seconds": 36000,
"active_jobs": 0,
"daily_seconds_used": 0
}
}
Eso responde el saldo en segundos, los segundos retenidos por jobs en curso,
la fecha de vencimiento de los créditos, si hay una tarjeta guardada, la
región de datos y los límites de admisión (max_active_jobs,
max_daily_seconds, y lo que ya se usó). Una cuenta nueva empieza con saldo
cero. POST /v1/uploads verifica el saldo, no la tarjeta: sin minutos,
responde 3001 insufficient_balance. La tarjeta es cómo llega el saldo, ya
que la verificación única de tarjeta en la aplicación libera los 30 minutos
gratis, y los paquetes se compran con una tarjeta guardada.
Automatizar de principio a fin
Todo lo que ocurre después de que la cuenta existe funciona sin ninguna
persona, sin importar si una persona abrió esa cuenta en la aplicación o un
agente la abrió mediante /v1/agent/accounts (consulta Uso
automatizado). Queda un único paso de navegador, y un agente
puede manejarlo él mismo.
-
Lee la cuenta.
GET /v1/account. Sicard_on_filees false, guarda una tarjeta primero. -
Guarda una tarjeta, una sola vez.
POST /v1/billing/setup-sessiondevuelve uncheckout_url, unsession_idy 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" }Abre la URL en un navegador que controles y completa la página alojada de Stripe; no se cobra nada y Hushscript nunca ve la tarjeta. Luego
GET /v1/billing/cardsla lista con su id.POST /v1/billing/cards/defaultcambia la predeterminada si la cuenta tiene varias. -
Compra minutos.
GET /v1/billing/packslista los cinco paquetes conid,seconds,amountycurrency:curl https://api.hushscript.com/v1/billing/packs \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"POST /v1/billing/purchaseconpack,quick_payment_method_id(el id de la tarjeta guardada) y unidempotency_keycobra la tarjeta fuera de sesión y responde el nuevobalance_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 }Esto necesita el scope
billingen el token y la facturación activada para la cuenta. Un cuerpo sin id de tarjeta, o una tarjeta rechazada, se rechaza con4021 pat_purchase_requires_app; una tarjeta que el emisor quiere verificar se rechaza con4023 pat_purchase_requires_authentication. Ninguno de los dos abre una página que nadie pueda completar. -
Sube el archivo.
POST /v1/uploadsconsize_bytes,duration_seconds(de 15 segundos a 10 horas), untitleopcional,transcription_optionsy 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" }'Coloca una retención de crédito y responde un
job_idmás una primera página de URLs de parte prefirmadas:{ "job_id": "job_5e2a91cf4d7b6081a9f3c2e4b5d6a7c8", "part_urls": [ { "n": 1, "url": "https://r2.hushscript.com/uploads/job_5e2a91cf.../part-1?X-Amz-Signature=..." } ] }Haz
PUTde cada parte a su URL (partes de 32 MiB por defecto, la última más pequeña):curl -X PUT "https://r2.hushscript.com/uploads/job_5e2a91cf.../part-1?X-Amz-Signature=..." \ --data-binary @part-01.binObtén más páginas desde
GET /v1/uploads/{job}/part-urls?start=<n>, y llama aPOST /v1/uploads/{job}/heartbeatbien dentro de los 20 minutos de tiempo de espera por inactividad durante una transferencia larga. Cuando las URLs prefirmadas no están disponibles, o una parte falla,PUT /v1/uploads/{job}/parts/{n}envía los bytes de esa parte a través de la API en su lugar; unPUTrepetido reemplaza la parte, así que los reintentos son seguros. Solo audio: mp3, m4a, wav, flac, ogg u opus, como máximo 5 GB, verificado en el servidor; extrae la pista de audio de un video antes de subirlo. -
Inicia y espera.
POST /v1/uploads/{job}/completecon elny eletagde cada parte que enviaste a una URL prefirmada (omitepartscuando todas las partes se enviaron por la 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\"" } ] }'Luego consulta
GET /v1/jobs/{id}:statepasa poruploading,queuedyprocessinghastadoneofailed, y un job terminado trae 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" } -
Lee el resultado.
GET /v1/transcripts/{id}devuelve los metadatos y el cuerpo completo, con los nombres de los hablantes, el idioma detectado, las etiquetas y la fecha de eliminación automática:curl https://api.hushscript.com/v1/transcripts/trs_2b6e1d4a9f7c3088a1b2c3d4e5f6a7b9 \ -H "Authorization: Bearer hsr1:eu:pat.7f3a9c.2b6e1d4a9f2c88b1a3d4e5f60718293"GET /v1/transcriptspagina la lista.
Las opciones de transcripción son las mismas que en la aplicación,
textualmente: language_code o detección automática, speaker_detection,
medical_mode (necesita language_code en en, es, fr o de; suma un
100 %), translation_targets (suma un 25 % por idioma), multichannel,
keyterms_prompt, un prompt de texto libre, y los dictionary_ids y
prompt_preset_id guardados que lista GET /v1/transcription-context.
Parte de la cuenta sigue siendo solo para MCP. Importar desde un enlace,
editar o eliminar transcripciones, Insights, exportaciones, guardar
diccionarios y ajustes preestablecidos de mensajes, y la configuración de la
cuenta todavía no tienen ruta /v1/; el servidor MCP cubre todo eso
con el mismo token.
Autenticación
Cada llamada /v1/ lleva un token bearer en el encabezado Authorization,
verificado contra los mismos scopes que usa el servidor MCP:
| Scope | Qué permite |
|---|---|
transcripts:read |
Lee y exporta las transcripciones, sus metadatos y la lista de eliminadas |
transcripts:write |
Edita, etiqueta, traduce, restaura y elimina transcripciones |
transcribe |
Sube grabaciones, importa desde un enlace e inicia transcripciones |
insights |
Lee, genera y elimina Insights |
context |
Administra diccionarios guardados y ajustes preestablecidos de mensajes |
account:read |
Lee el saldo, el uso, las transacciones y las retenciones |
settings:write |
Cambia la configuración de la cuenta |
org:read |
Lee los miembros, el historial de movimientos, las facturas y el registro de auditoría del espacio de trabajo |
export |
Solicita una exportación completa de la cuenta, consulta su estado y descárgala |
billing |
Guarda una tarjeta y compra paquetes de minutos |
Una llamada fuera de los scopes del token falla con pat_scope_missing,
en 403. El scope billing también está inerte hasta que el propietario de la
cuenta activa la facturación para la cuenta en la aplicación; una llamada de
facturación en una cuenta donde ese interruptor está apagado falla con el
mismo pat_scope_missing, y volver a generar el token no lo soluciona. Un
token no puede crear, listar ni revocar tokens, y una cuenta tiene como
máximo 25 activos.
Endpoints
Disponibles hoy, cada uno protegido por el scope indicado:
| Method | Path | Scope |
|---|---|---|
POST |
/v1/agent/accounts |
none |
POST |
/v1/agent/accounts/{signup_id}/claim |
none |
POST |
/v1/agent/credentials/rotate |
none |
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/members |
org:read |
GET |
/v1/org/invoices |
org:read |
GET |
/v1/org/ledger |
org:read |
GET |
/v1/org/audit |
org:read |
/v1/agent/accounts abre un registro sin interfaz y sin token todavía,
/v1/agent/accounts/{signup_id}/claim convierte un registro pagado en una
cuenta real y su primer token, y /v1/agent/credentials/rotate genera un
sucesor para el token que hace la llamada y lo revoca, sin tocar ninguna otra
credencial de la cuenta. La guía de Uso automatizado cubre los
tres de principio a fin.
Todo listado toma un limit y un cursor opaco, y responde un
next_cursor que es null en la última página. Devuelve el cursor sin
cambios; codifica la posición, así que nunca se salta ni se repite una
página cuando llegan filas entre llamadas.
La definición completa y actual, con parámetros y esquemas de respuesta para cada operación, está en el documento OpenAPI: trátalo como la fuente de verdad por encima de esta tabla. Se sirve a cualquier token bearer sin importar el scope, así que un cliente puede obtenerlo con las credenciales que ya tiene.
Interfaz MCP
¿Prefieres herramientas antes que HTTP puro? El servidor MCP pone la misma cuenta detrás de 51 herramientas en lugar de estos endpoints, para un cliente que ya habla MCP en vez de REST.
Límites
Las solicitudes hechas con un token están limitadas a 1.200 por minuto por
token. POST /v1/billing/setup-session y POST /v1/billing/purchase
comparten un presupuesto más estricto de 60 por minuto por cuenta, antes de
la llamada a Stripe que harían. Una solicitud rechazada responde
429 rate_limited con un encabezado Retry-After que indica la espera en
segundos; espera ese tiempo antes de reintentar. Las subidas están
limitadas a 5 GB y 10 horas, con un mínimo de 15 segundos, y los límites de
admisión propios de la cuenta (max_active_jobs, max_daily_seconds) se
reportan en GET /v1/account.
Entorno de pruebas
No existe un modo de simulación: toda llamada /v1/ se ejecuta contra una
cuenta real, y comprar minutos gasta dinero real.
Errores
Un error es un cuerpo JSON con un code numérico estable y un slug error,
en el estado HTTP que se muestra abajo. Los cuerpos de error de /v1/ son
una proyección congelada: error, code y un conjunto fijo de claves de
detalle. La forma de error de /api no está congelada y puede traer más.
Los códigos que quien llama de forma automatizada debe manejar:
| Status | Code | Slug | Significado |
|---|---|---|---|
| 401 | 2000 | unauthorized |
Token bearer ausente o inválido |
| 403 | 2022 | pat_forbidden |
La ruta no acepta ningún token |
| 403 | 2023 | pat_scope_missing |
Al token le falta el scope que esta llamada necesita, o la facturación está desactivada para la cuenta |
| 403 | 4021 | pat_purchase_requires_app |
No se indicó ninguna tarjeta guardada, o el cargo fue rechazado; no se cobró nada |
| 403 | 4023 | pat_purchase_requires_authentication |
El emisor de la tarjeta pide una verificación que quien llama no puede completar; la tarjeta en sí está bien |
| 402 | 3001 | insufficient_balance |
Saldo insuficiente para admitir el job |
| 402 | 3002 | card_declined |
Se rechazó la tarjeta guardada |
| 402 | 3003 | org_insufficient_balance |
Al fondo compartido del espacio de trabajo que financia esta subida le falta saldo |
| 404 | 4000 | not_found |
No existe ese job, subida o recurso |
| 409 | 4001 | wrong_state |
El recurso no está en un estado que permita esto |
| 422 | 1021 | duration_out_of_range |
La duración declarada es menor a 15 segundos o mayor a 10 horas |
| 429 | 5000 | rate_limited |
Demasiadas solicitudes; espera el Retry-After |
| 502 | 6001 | provider_error |
Falló un servicio externo |
| 500 | 9000 | internal_error |
Un error inesperado del servidor |
El documento OpenAPI indica el código exacto que puede devolver cada
operación, y el servidor MCP publica el catálogo completo como el recurso
hushscript://error-codes.