Get Twins API
List AI twins for a Firebase user or API client with getTwins — try it live, then copy the request into your backend.
Overview
getTwins returns the AI twins owned by the authenticated account. Use a Firebase ID token for dashboard users, or a client_* JWT from getAiTwinAuthToken for API / embed clients.
Browser calls must send an Origin on the allowlist (localhost:3000, aitwin.me, www.aitwin.me, avatars.streamoji.com). Server-to-server callers should send a valid allowlisted Origin or proxy through your backend. This interactive demo works on aitwin.me and local docs because those origins are already allowed.
Interactive Demo
Generate a token with your API Keys, then fetch twins for that client. Client JWTs are automatically scoped to the token’s userId.
curl -X POST "https://us-central1-streamoji-265f4.cloudfunctions.net/getAiTwinAuthToken" \
-H "Content-Type: application/json" \
-H "Client-Id: YOUR_CLIENT_ID" \
-H "Client-Secret: YOUR_64_CHAR_API_KEY" \
-d '{"userId":"end-user-123","userName":"Jane Doe"}'For testing only. In production, call getAiTwinAuthToken from your backend and pass the token to your iframe URL.
Request reference
Methods: GET or POST
URL: https://us-central1-streamoji-265f4.cloudfunctions.net/getTwins
Header: Authorization: Bearer <token>
curl -X GET "https://us-central1-streamoji-265f4.cloudfunctions.net/getTwins" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Origin: https://aitwin.me"Response shape
Success responses are wrapped as { data: { success: true, twins: [...] } }. Each twin is a serialized Firestore document.
| Field | Description |
|---|---|
| id | Firestore document id (public slug or private twin id). |
| faceId | Face asset id. Use it to build the public thumbnail URL (see Face thumbnails). |
| voiceId | Voice id used for TTS. |
| ttsEngineId | TTS engine id (default eng_c9b1e6d4 when unset upstream). |
| isPrivate | Whether the twin is private. |
| name | Optional display name. |
| createdBy | Firebase uid or API clientId that owns the twin. |
| createdBySubUserId | Optional end-user id for twins created via client JWT / embed. |
| createdAt | Creation time (ISO string from the API). |
| updatedAt | Last update time (ISO string from the API). |
| token | Optional twin token when present. |
| knowledgeContextId | Optional brain / knowledge base id. |
Face thumbnails
Every twin in the getTwins response includes a faceId. Use it to show a portrait thumbnail in your app — for example an avatar grid like the interactive demo above.
Thumbnails are served from the public CDN at https://aitwin.bubu.social/custom-faces/{faceId}/thumbnail.webp. Replace {faceId} with the value from the API response. No auth token is required to load thumbnail images.
If you already use @streamoji/aitwin, prefer getAiTwinThumbnailUrl(faceId) — it builds the same URL for you.
import { getAiTwinThumbnailUrl } from "@streamoji/aitwin";
function TwinAvatar({ faceId, name }: { faceId: string; name: string }) {
return (
<img
src={getAiTwinThumbnailUrl(faceId)}
alt={name}
className="aspect-[3/4] w-24 rounded-lg object-cover"
/>
);
}
// After getTwins:
twins.forEach((twin) => {
if (!twin.faceId) return;
const thumbnailUrl = getAiTwinThumbnailUrl(twin.faceId);
// render TwinAvatar or push into your UI list
});// Public CDN URL pattern (no auth required):
https://aitwin.bubu.social/custom-faces/{faceId}/thumbnail.webp
// Example with a faceId from getTwins:
const thumbnailUrl =
"https://aitwin.bubu.social/custom-faces/" + twin.faceId + "/thumbnail.webp";Errors
| Status | When | Example |
|---|---|---|
| 401 | Missing, malformed, or invalid Bearer token | Authorization header is required / Invalid or expired Firebase Auth token |
| 403 | Browser Origin not on the allowlist | Access forbidden: Invalid origin |
| 405 | Method other than GET, POST, or OPTIONS | Method not allowed. Use GET or POST. |
| 500 | Unexpected server error | Internal server error (or the thrown message) |
Error bodies typically look like { success: false, error: "…" }.