Subscribers only
The API is included with a paid Hear2Text subscription, and is not available on the free plan. There is no separate API product, no API-only price and no trial key. If you are not subscribed, you can read every one of these pages, but every request answers:
{
"error": "subscription_required",
"message": "The Hear2Text API is included with a paid subscription. Your keys are kept; they will work again as soon as the subscription is active.",
"docs": "https://heartotext.com/api/docs"
}Two accounts can never hold a key, whatever their subscription says:
- Guest accounts. A guest has no recoverable identity, so a long-lived credential on one is unsupportable —
guest_account_not_supported. - Restricted accounts. An account we have restricted answers
account_restrictedeverywhere.
Creating a key
Keys are created in the web app under Profile → API, signed in with your own session. There is deliberately no endpoint that mints a key: a credential that can create more credentials turns one leak into a permanent one.
You may hold 5 active keys at a time. Revoked keys do not count, so rotating is never blocked by the ceiling.
The key is shown once. We store a hash, not the key, so there is no screen anywhere — including ours — that can show it to you again. If you lose it, revoke it and create another.
Using a key
Put it in an Authorization header. Nothing else is accepted: not a query parameter, not a cookie, not a custom header. A key in a URL ends up in access logs, browser history and referrer headers.
curl https://heartotext.com/api/public/v1/me \
-H "Authorization: Bearer h2t_live_a1b2c3d4_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"GET /me is the request to make from a health check: it tells you the plan, the limits that currently bind, and which key is calling.
{
"plan": "monthly",
"subscription_status": "active",
"limits": { "max_recording_seconds": 21600, "daily_seconds": 72000, "concurrent_transcriptions": 5 },
"usage": { "daily_seconds_used": 3480, "running_transcriptions": 1 },
"rate_limits": { "requests_per_minute": 120, "creates_per_hour": 60, "creates_per_day": 500, "exports_per_minute": 30 },
"key": { "name": "Podcast pipeline", "prefix": "h2t_live_a1b2c3d4", "scopes": ["transcriptions:read","transcriptions:write","exports:read"], "workspace": null }
}Scopes
Each key carries the scopes you gave it when you created it.
| Scope | Allows |
|---|---|
transcriptions:read | Listing recordings, reading one, reading its segments. |
transcriptions:write | Creating a recording and deleting one. |
exports:read | Downloading a transcript as a file. |
A request outside a key’s scopes answers 403 insufficient_scope, with the scope it wanted named in the body. /me and /languages need no particular scope.
Workspace-scoped keys
A key can be pinned to one workspace when you create it. Recordings it creates file into that workspace, and it can only see recordings that live there — the pin is re-checked against your membership on every request, so a key stops working the moment you leave the workspace. An unpinned key works in your personal space.
Revoking, rotating, lapsing
- Revoking takes effect on the next request: a key is looked up afresh every time and never from a cache. A revoked key answers
401 invalid_api_keyforever after. - Rotating means creating the new key, deploying it, then revoking the old one. Both work at once, so there is no gap.
- A lapsed subscription keeps your keys. They answer
subscription_requireduntil the subscription is active again, then carry on. - Changing your password keeps your keys; recovering the account revokes them. A key is not a session, and breaking a production integration on a routine password change would be its own kind of outage. A reset through the emailed code is different: it is what you reach for when you think somebody else got in, so it revokes every key along with every session. Deleting the account deletes them.
Keeping a key safe
- Server-side only. CORS is off here deliberately; browser calls are not supported, and a key shipped to a browser is a public key.
- Keep it in your secret store or environment, never in the repository.
- A mobile app token is not an API key, and an API key is not a session — neither works on the other’s surface. That is a property of where they are stored, not a rule a middleware could be talked out of.
- We never log the
Authorizationheader or the key. If you think one has leaked, revoke it; that is the whole remedy.
