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
- 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.
- 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.
- 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.