Skip to main content

Automatic transcription for agents and scripts

Automatic transcription turns recorded audio into editable text. The app prepares video audio on your device; agents can submit prepared audio through REST or MCP.

Automatic transcription in Hushscript turns an existing audio recording into an editable transcript. In the browser app, you can also start with a local video: Hushscript prepares its audio on your device and sends only that audio for online recognition. You review and correct the result yourself: this isn’t a human-proofread or certified transcription service.

How automatic transcription works

  1. Prepare the recording. Use an audio file, import a supported audio link, or record your voice in the browser app. For video recordings, choose a local file so the app can prepare the audio on your device.
  2. Submit and wait for the transcript. The app handles upload and status. An agent can upload prepared audio in parts through the REST API or use the scoped MCP tools, then check the job until the transcript is ready.
  3. Review and export. Edit the transcript and speaker labels in the app, or retrieve the text through the API. An agent’s token can also export the transcript within its granted scopes.

Automatic transcription software for audio and video

Hushscript’s automatic transcription software turns recorded speech into text you can search, edit, and export. The app’s record entry also lets you capture a voice recording before transcription. For a standalone recording file without transcription, use the free voice recorder.

Automatic video transcription follows the same text workflow after the app extracts or converts the audio locally. The REST upload example below starts with prepared audio; to hand the app your local video file instead, use the browser workflow at video to text.

Can I try automatic transcription for free?

Yes. The public preview transcribes up to five minutes from one file, supported audio link, or browser recording before sign-in, and a local video works once the browser prepares its audio. Full transcription needs an account: an eligible personal account gets 30 free minutes after card verification (see pricing for how that works), while a machine account skips the welcome minutes and starts with the pack it buys at signup.

Run transcript automation with the API or MCP

The browser app is for working directly with recordings. For transcript automation, the REST API and MCP server let an agent upload prepared audio, check jobs, retrieve transcripts, and export results. An agent can open its own account with a payment-first flow, without a human account holder; hosted checkout still needs a browser, and a card issuer may require an authentication step. A person can instead create a scoped token from an existing account in the app. This walkthrough follows the machine account from signup through credential rotation.

Sign up

POST /v1/agent/accounts opens a headless signup. There is no account yet, no cookie, and no token: just a pending purchase.

curl -X POST https://api.hushscript.com/v1/agent/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "contact_email": "ops@example-agent.dev",
    "pack_id": "300min",
    "accept_terms_version": "2026-10-20",
    "agent": {
      "name": "research-crawler",
      "platform": "langgraph",
      "contact_url": "https://example-agent.dev/bots/research-crawler"
    }
  }'
{
  "signup_id": "hsr1:eu:4c3a1f9e7b2d4e6f8a0c1b2d3e4f5061",
  "claim_secret": "cs_9f3d2a1b7e6c4f5a8b9d0e1f2a3b4c5d",
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_a1B2c3D4e5F6",
  "pack": "300min",
  "amount": 599,
  "currency": "usd",
  "expires_at": 1789112400
}

contact_email is for receipts and notices only, never a login. pack_id is one of 45min, 300min, 900min, 1800min, 6000min; never send amount or currency yourselves, both are derived from the pack on the server. Only the two smallest packs, 45min and 300min, can be bought at signup. A larger pack_id is refused, and the refusal carries details.allowed_packs listing what this account may buy right now, so a caller can retry without guessing. The rest of the ladder unlocks with age, not with volume: see What a new account may buy below. accept_terms_version must match the server’s current policy version exactly, or the call fails with policy_version_stale, which names the current value in its body. An optional data_region hint is honored only when it agrees with the region your network location already implies. An optional dry_run: true validates everything with no Stripe session and no charge; its signup_id is prefixed dry_ and can never be claimed.

claim_secret is shown exactly once, in this response. Hushscript stores only its hash. Losing it before the claim call means losing the signup: there is no recovery route for a claim secret. A paid, unclaimed signup enters the refund process described below; it cannot be recovered through a lookup.

Complete the checkout in your own browser

checkout_url is a hosted Stripe Checkout page. Signup needs a browser for this step, and it does not need to be a person’s browser: an agent can drive it with its own automation (fill the card fields, submit, follow the redirect). Hushscript never sees the card details either way; Stripe does. The window to finish it and then claim is 30 minutes, the expires_at above.

An hourly sweep checks paid, unclaimed signups after the 30-minute claim window and a further one-hour grace. It attempts a full refund, because minutes are credited only at claim. Failed refund attempts are retried and may require manual handling; the refund is not guaranteed to arrive at a particular time.

Claim the account

POST /v1/agent/accounts/{signup_id}/claim turns a paid, unclaimed signup into a real account, in one call.

curl -X POST https://api.hushscript.com/v1/agent/accounts/hsr1:eu:4c3a1f9e7b2d4e6f8a0c1b2d3e4f5061/claim \
  -H "Content-Type: application/json" \
  -d '{"claim_secret": "cs_9f3d2a1b7e6c4f5a8b9d0e1f2a3b4c5d"}'
{
  "user_id": "usr_7d1a2b3c4d5e6f708192a3b4c5d6e7f8",
  "pat": "hsr1:eu:pat.k3n2j1.8f7e6d5c4b3a29180716253443526170",
  "scopes": [
    "transcripts:read",
    "transcripts:write",
    "transcribe",
    "account:read",
    "export",
    "billing",
    "pat:rotate"
  ],
  "balance_seconds": 18000
}

Claiming creates exactly one account, with a synthetic, unresolvable login identity behind it, and grants the paid pack exactly once, however many times the request is retried. It mints one PAT: the pat value above.

If the response is lost, repeat the call with the same claim_secret. Within one hour of the claim, and while the token it issued has never been used, the retry returns 201 for the same account with the same response shape and a fresh pat. The lost token stops working. After the token’s first use, or after that hour, a retry answers agent_claim_invalid. A retry that overlaps a claim still running may get 429 rate_limited with a Retry-After header; retry after that delay.

That first token can transcribe, read and edit transcripts, export, read the account balance, buy minutes, and rotate itself. It does not grant Insights, context, organization, or settings-write scopes. The MCP server only offers tools covered by the token’s scopes.

A wrong secret, an unknown signup_id, a refunded signup, an expired one, and a repeat claim whose token was already used or whose hour has passed all answer the identical agent_claim_invalid error. There is no way for a caller to tell those apart from the response, on purpose. Only once the secret itself checks out does payment state come into it: a Checkout Session that has not settled yet answers wrong_state instead.

The balance_seconds above is the whole starting balance. Agent accounts get no welcome bonus and no free minutes from card verification the way a person’s first account does; they start from nothing but the pack they paid for. That’s deliberate: the account was already paid for before it existed.

Buy more minutes

From here the account uses the /v1/ surface /developers documents in full.

curl -X POST https://api.hushscript.com/v1/billing/purchase \
  -H "Authorization: Bearer hsr1:eu:pat.k3n2j1.8f7e6d5c4b3a29180716253443526170" \
  -H "Content-Type: application/json" \
  -d '{
    "pack": "300min",
    "quick_payment_method_id": "pm_1PqR2sT3uV4wX5yZ",
    "idempotency_key": "purchase-2026-09-11-01"
  }'
{
  "balance_seconds": 36000
}

This needs the billing scope, which the claim response above already granted. The claim also enables billing on the token and account; a token created by a person needs the billing scope and both billing switches enabled. PAT billing calls share a tighter 60 requests a minute per account across the Stripe-calling billing routes, before their Stripe requests.

What a new account may buy

Pack size unlocks on the age of settled payments, not on how much an account spends. A purchase counts toward the next tier only once it is 7 days past its own payment date, so a brand new account cannot reach the large packs by buying quickly.

Settled payments aged past 7 days Packs it may buy
Nothing yet, including a fresh claim 45min, 300min
At least 45 minutes’ worth adds 900min, 1800min
At least 15 hours’ worth adds 6000min

A refused purchase names the current set in details.allowed_packs rather than failing blind. The signup call applies the first row of that table, which is why the walkthrough above buys 300min and not something larger. Separately from the ladder, a rolling 24 hour burn cap limits how fast balance that has not yet aged past the dispute window can be spent. The signup purchase counts toward the account’s three purchase attempts in a rolling 24 hours; declined attempts after reservation count too.

Transcribe

Uploading and transcribing is the same multipart flow as any other account. The API example submits prepared audio; it does not upload a local video’s source file.

curl -X POST https://api.hushscript.com/v1/uploads \
  -H "Authorization: Bearer hsr1:eu:pat.k3n2j1.8f7e6d5c4b3a29180716253443526170" \
  -H "Content-Type: application/json" \
  -d '{
    "size_bytes": 48213504,
    "duration_seconds": 1860,
    "title": "weekly-standup-2026-09-11",
    "idempotency_key": "upload-2026-09-11-01"
  }'
{
  "job_id": "job_3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d",
  "part_urls": [
    { "n": 1, "url": "https://r2.hushscript.com/uploads/job_3a2b1c0d.../part-1?X-Amz-Signature=..." }
  ]
}

PUT each part to its presigned URL, then POST the same job’s /complete with the n and etag of every part sent that way. Then poll the job:

curl https://api.hushscript.com/v1/jobs/job_3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d \
  -H "Authorization: Bearer hsr1:eu:pat.k3n2j1.8f7e6d5c4b3a29180716253443526170"
{
  "id": "job_3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d",
  "state": "done",
  "transcript_id": "trs_6f5e4d3c2b1a0908f7e6d5c4b3a29180"
}
curl https://api.hushscript.com/v1/transcripts/trs_6f5e4d3c2b1a0908f7e6d5c4b3a29180 \
  -H "Authorization: Bearer hsr1:eu:pat.k3n2j1.8f7e6d5c4b3a29180716253443526170"
{
  "id": "trs_6f5e4d3c2b1a0908f7e6d5c4b3a29180",
  "language": "en",
  "duration_seconds": 1860,
  "body": "..."
}

Rotate the credential

A machine account has no password and no usable mailbox, so there is no “forgot your password” path if a PAT leaks or simply needs replacing. Rotation is that path.

curl -X POST https://api.hushscript.com/v1/agent/credentials/rotate \
  -H "Authorization: Bearer hsr1:eu:pat.k3n2j1.8f7e6d5c4b3a29180716253443526170"
{
  "pat": "hsr1:eu:pat.p9q8r7.1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
  "pat_id": "p9q8r7",
  "scopes": [
    "transcripts:read",
    "transcripts:write",
    "transcribe",
    "account:read",
    "export",
    "billing",
    "pat:rotate"
  ],
  "expires_at": null
}

The call takes no body. It mints a successor for the token that authenticated the request. The successor keeps the predecessor’s scopes, billing permission, name, client label, and expiry policy. This route touches nothing but the caller’s own token: it cannot list, mint, or revoke any other credential on the account. It is the only credential-recovery path a machine account has, so rotate before the old token is discarded, not after.

The old token is not revoked at once. After rotating, it works for one thing only: calling rotate again. That lasts until the new token makes its first successful request or one hour passes, whichever comes first. On every other route the old token answers 401 right away.

If the response carrying the new token is lost, call rotate again with the old token while the new one is unused. You get a fresh secret for the same pat_id, and the earlier new secret stops working.

Keep the old token until the new one has worked once. Then make one call with the new token right away, such as GET /v1/account. That first successful request retires the old token for good.

Errors

Status Code Slug Meaning
401 2000 unauthorized Missing or invalid bearer token
403 2023 pat_scope_missing The token lacks the scope this call needs, or billing is off for the account
403 4021 pat_purchase_requires_app No saved card was named, or the charge was declined; nothing was charged
403 4023 pat_purchase_requires_authentication The card issuer wants a challenge the caller cannot complete; the card itself is fine
402 3001 insufficient_balance Not enough balance to admit the job
429 5000 rate_limited Too many requests; wait for Retry-After

These errors cover agent signup and purchase controls. The purchase cap also applies to PAT purchases on a human account; a human session purchase is exempt.

Status Code Slug Meaning
409 4035 agent_signup_pending A signup for this contact_email is still open. Wait for it to be claimed, refunded or expired, or use a different address
401 4036 agent_claim_invalid Wrong secret, unknown signup, refunded, expired, or already claimed with the token since used or the hour passed. Identical on purpose
403 4037 agent_pack_locked This account’s tier does not allow that pack yet. Carries details.allowed_packs; retry with one of those
429 4038 agent_purchase_capped 3 purchase attempts in the trailing 24 hours, including failures after reservation and an agent account’s signup purchase. Counted per account across credentials, so rotation does not reset it. Carries details.retry_after_seconds

Once the claim secret itself checks out, an unpaid Checkout Session answers wrong_state (4001) rather than agent_claim_invalid. The full catalog is the OpenAPI document.

Limits

Calls are limited to 1,200 a minute. For an agent account that budget belongs to the account, not to the individual token: every credential in the rotation lineage draws on the same one, so rotating a PAT does not hand the successor a fresh allowance. PAT billing calls that reach Stripe share a tighter 60 a minute per account. This includes setup and purchase, card-default changes and removal, and card-list cache misses; the check runs before the Stripe call. The 24 hour purchase cap above is counted the same way, per account rather than per credential.

Learn more

This page covers the account lifecycle: opening one, funding it, and keeping its credential alive. For everything the account can then do, see the REST API, including the full OpenAPI document, or the MCP server for the same account over tools instead of raw HTTP.

Transcribe in the app, or give your agent its own account

Eligible personal accounts can receive 30 free minutes once after successful card verification, or with their first purchase if not already granted. Agent accounts start with the minute pack they buy at signup.

Get 30 free minutes