Authentication
🔑 Authentication
Section titled “🔑 Authentication”The Uspeech API uses per-user API keys. Every key belongs to a single user account and inherits exactly the permissions that user has in the web app: the projects and teams they can see, the transcripts they can read, the files they can upload.
There is no shared “service” or “team” key today — pick the user the key should act on behalf of, and create a key for that user.
1. Create an API key
Section titled “1. Create an API key”API keys are managed from your Profile panel in the web app.
- Sign in at app.uspeech.io as the user the key should act on behalf of.
- Open Profile from the user menu.
- Find the API keys section and click Create API key.
- The plaintext key is shown once at this point. Copy it immediately. The key is given an auto-generated name you can use to identify it later in the list.
⚠️ Important: the plaintext key is only displayed at creation time. Uspeech only stores a hash, so a lost key cannot be recovered — you’ll need to create a new one and revoke the old.
2. Use it in requests
Section titled “2. Use it in requests”Send the key in the Authorization header, prefixed with Api-Key:
Authorization: Api-Key <prefix>.<secret>A complete request looks like this:
curl https://app.uspeech.io/api/transcripts/ \ -H "Authorization: Api-Key $USPEECH_KEY"import os
import requests
BASE_URL = "https://app.uspeech.io"HEADERS = {"Authorization": f"Api-Key {os.environ['USPEECH_KEY']}"}
response = requests.get(f"{BASE_URL}/api/transcripts/", headers=HEADERS, timeout=30)response.raise_for_status()print(response.json())const BASE_URL = 'https://app.uspeech.io';const HEADERS = { Authorization: `Api-Key ${process.env.USPEECH_KEY}` };
const response = await fetch(`${BASE_URL}/api/transcripts/`, { headers: HEADERS });if (!response.ok) throw new Error(await response.text());console.log(await response.json());That’s it — no separate login step, no token exchange.
💡 Tip: keep the key in an environment variable (USPEECH_KEY in these examples) rather than
pasting it into your source. Every example in this reference reads it the same way.
3. Scoping
Section titled “3. Scoping”A key inherits its user’s view of the system:
- Listing transcripts (
GET /api/transcripts/) returns only transcripts whose file belongs to a project the user can see. - Uploading a file (
POST /api/files/) requiresproject=<id>to point at a project the user owns, is a team admin on, or has been explicitly shared with. - An inactive user (
is_active = False) cannot use the key — requests are rejected even if the key itself is still valid.
Treat a key as having the same blast radius as the user’s password.
4. Revoke a compromised key
Section titled “4. Revoke a compromised key”If a key leaks, revoke it immediately:
- Open Profile and scroll to the API keys section.
- Find the key by its Name or Prefix (the part before the
.in the plaintext key). - Click Revoke.
Revoked keys return 403 Forbidden on every request. Issue a new key for the integration and update the deployment that uses it.
5. Security best practices
Section titled “5. Security best practices”- 🔒 Store keys in a secret manager or environment variable, never in source control.
- 🔁 Rotate keys on a schedule, and immediately on suspected exposure.
- 🧑🤝🧑 Use a dedicated user account for each integration so you can revoke independently. Don’t reuse a personal account’s key for a shared service.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Likely cause |
|---|---|
401 Unauthorized / 403 Forbidden with no header | Authorization header is missing or the prefix isn’t exactly Api-Key (note the trailing space) |
403 Forbidden with a valid-looking key | Key is revoked, the user is inactive, or the secret half doesn’t match |
404 Not Found on a known project ID | The project exists but isn’t visible to the key’s user |
See Status Codes & Errors for the full list of response codes.