Documentation Index
Fetch the complete documentation index at: https://documentation.lettucestream.com/llms.txt
Use this file to discover all available pages before exploring further.
Use these endpoints to manage API keys for a user account. These endpoints require a valid Firebase ID token (not an API key) because they create or revoke keys.
Authentication
Provide an ID token using one of these methods:
Authorization: Bearer <ID_TOKEN>
x-id-token: <ID_TOKEN>
- JSON body field
idToken
Base URL
https://www.lettucestream.com
Endpoints
List API keys
GET /api/api-keys
Response
{
"keys": [
{
"id": "string",
"label": "string",
"prefix": "ls_live_AbCd...",
"createdAt": "2026-02-06T18:02:12.123Z",
"lastUsedAt": "2026-02-06T18:10:55.000Z",
"revokedAt": null
}
]
}
Example requests
curl "https://www.lettucestream.com/api/api-keys" \
-H "Authorization: Bearer <ID_TOKEN>"
import fetch from "node-fetch";
const response = await fetch("https://www.lettucestream.com/api/api-keys", {
headers: {
Authorization: "Bearer <ID_TOKEN>",
},
});
const data = await response.json();
console.log(data.keys);
import requests
response = requests.get(
"https://www.lettucestream.com/api/api-keys",
headers={"Authorization": "Bearer <ID_TOKEN>"},
timeout=10,
)
print(response.json()["keys"])
Create API key
POST /api/api-keys
Body
{
"label": "Production key"
}
Response
{
"key": "ls_live_...",
"keyId": "string",
"keys": [
{
"id": "string",
"label": "string",
"prefix": "ls_live_AbCd...",
"createdAt": "2026-02-06T18:02:12.123Z",
"lastUsedAt": null,
"revokedAt": null
}
]
}
Example requests
curl -X POST "https://www.lettucestream.com/api/api-keys" \
-H "Authorization: Bearer <ID_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"label":"Production key"}'
import fetch from "node-fetch";
const response = await fetch("https://www.lettucestream.com/api/api-keys", {
method: "POST",
headers: {
Authorization: "Bearer <ID_TOKEN>",
"Content-Type": "application/json",
},
body: JSON.stringify({ label: "Production key" }),
});
const data = await response.json();
console.log(data.key);
import requests
response = requests.post(
"https://www.lettucestream.com/api/api-keys",
headers={
"Authorization": "Bearer <ID_TOKEN>",
"Content-Type": "application/json",
},
json={"label": "Production key"},
timeout=10,
)
print(response.json()["key"])
Notes
- The full
key value is returned only once. Store it securely.
- The UI and API store only a SHA-256 hash of the key.
Revoke API key
DELETE /api/api-keys
Body
Response
{
"keys": [
{
"id": "string",
"label": "string",
"prefix": "ls_live_AbCd...",
"createdAt": "2026-02-06T18:02:12.123Z",
"lastUsedAt": "2026-02-06T18:10:55.000Z",
"revokedAt": "2026-02-06T18:12:01.000Z"
}
]
}
Example requests
curl -X DELETE "https://www.lettucestream.com/api/api-keys" \
-H "Authorization: Bearer <ID_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"keyId":"key_123"}'
import fetch from "node-fetch";
const response = await fetch("https://www.lettucestream.com/api/api-keys", {
method: "DELETE",
headers: {
Authorization: "Bearer <ID_TOKEN>",
"Content-Type": "application/json",
},
body: JSON.stringify({ keyId: "key_123" }),
});
const data = await response.json();
console.log(data.keys);
import requests
response = requests.delete(
"https://www.lettucestream.com/api/api-keys",
headers={
"Authorization": "Bearer <ID_TOKEN>",
"Content-Type": "application/json",
},
json={"keyId": "key_123"},
timeout=10,
)
print(response.json()["keys"])
Example UI
Use a lightweight UI library like shadcn/ui with a free placeholder API to prototype your API-key dashboard layout before wiring it to the Lettuce Stream endpoints.
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
const placeholderUrl = "https://jsonplaceholder.typicode.com/users";
export default function ApiKeysTable() {
const [rows, setRows] = useState([]);
useEffect(() => {
const loadRows = async () => {
const response = await fetch(placeholderUrl);
const users = await response.json();
setRows(
users.slice(0, 5).map((user) => ({
id: `key_${user.id}`,
label: `${user.company.name} key`,
prefix: "ls_live_AbCd...",
createdAt: new Date().toISOString(),
lastUsedAt: "-",
}))
);
};
loadRows();
}, []);
return (
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-muted-foreground">
Replace the placeholder API with your Lettuce Stream requests once
your auth flow is ready.
</p>
</div>
<Button>Create key</Button>
</div>
<Table>
<TableHeader>
<TableRow>
<TableHead>Label</TableHead>
<TableHead>Prefix</TableHead>
<TableHead>Created</TableHead>
<TableHead>Last used</TableHead>
<TableHead className="text-right">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{rows.map((row) => (
<TableRow key={row.id}>
<TableCell className="font-medium">{row.label}</TableCell>
<TableCell>{row.prefix}</TableCell>
<TableCell>{row.createdAt}</TableCell>
<TableCell>{row.lastUsedAt}</TableCell>
<TableCell className="text-right">
<Button variant="ghost">Revoke</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
Limits
- Maximum active keys per user:
API_KEYS_MAX_ACTIVE (default 10).
- Key prefix format:
API_KEY_PREFIX (default ls_live_).
- Prefix preview length:
API_KEY_PREFIX_LENGTH (default 12).
Errors
400 — Missing label or key id, or maximum active keys reached.
401 — Missing or invalid authentication token.
403 — Attempted to revoke a key not owned by the user.
404 — API key not found.
405 — Method not allowed (allowed: GET, POST, DELETE).
500 — Server error.
Example (curl)
curl -X POST "https://www.lettucestream.com/api/api-keys" \
-H "Authorization: Bearer <ID_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"label":"Prod key"}'
Using API keys on other endpoints
Other protected endpoints accept API keys via:
x-api-key: <API_KEY>
Authorization: Bearer <API_KEY>