Complete reference for all tRPC endpoints in the AI Filmmaking Studio. All endpoints are accessed through the tRPC client and are fully type-safe.
- Authentication
- Projects
- Characters
- Scenes & Shots
- Prompts
- Prompt Templates
- Assets
- Tags & Organization
- Generation
- Error Handling
Get the current authenticated user.
Type: Query (Public)
Response:
{
id: number;
openId: string;
name: string | null;
email: string | null;
role: "user" | "admin";
createdAt: Date;
updatedAt: Date;
lastSignedIn: Date;
}Example:
const user = await trpc.auth.me.useQuery();Log out the current user and clear session.
Type: Mutation (Public)
Response:
{ success: true }Example:
const logout = trpc.auth.logout.useMutation();
logout.mutate();Projects are the main container for all filmmaking work. Each project contains characters, scenes, shots, and generated assets.
Get all projects for the current user.
Type: Query (Protected)
Response:
Project[]Example:
const projects = await trpc.projects.list.useQuery();Get a specific project by ID.
Type: Query (Protected)
Input:
{ id: number }Response:
Project | undefinedExample:
const project = await trpc.projects.get.useQuery({ id: 1 });Create a new project.
Type: Mutation (Protected)
Input:
{
title: string;
description?: string;
genre?: string;
status?: "planning" | "pre_production" | "production" | "post_production" | "completed";
}Response:
ProjectExample:
const project = await trpc.projects.create.useMutation();
project.mutate({
title: "My Sci-Fi Film",
genre: "Science Fiction",
description: "A futuristic story about AI",
});Update an existing project.
Type: Mutation (Protected)
Input:
{
id: number;
title?: string;
description?: string;
genre?: string;
status?: "planning" | "pre_production" | "production" | "post_production" | "completed";
coverImageUrl?: string;
}Response:
Project | undefinedDelete a project and all associated data.
Type: Mutation (Protected)
Input:
{ id: number }Response:
booleanCharacters represent people or entities in your story. Each character has visual identity details and personality traits.
Get all characters in a project.
Type: Query (Protected)
Input:
{ projectId: number }Response:
Character[]Get a specific character.
Type: Query (Protected)
Input:
{ id: number; projectId: number }Response:
Character | undefinedCreate a new character.
Type: Mutation (Protected)
Input:
{
projectId: number;
name: string;
description?: string;
age?: string;
skinTone?: string;
hairStyle?: string;
hairColor?: string;
eyeColor?: string;
bodyType?: string;
clothing?: string;
accessories?: string;
personality?: string;
background?: string;
motivations?: string;
referenceImageUrl?: string;
}Response:
CharacterUpdate character details.
Type: Mutation (Protected)
Input:
{
id: number;
projectId: number;
// ... same fields as create, all optional
}Response:
Character | undefinedDelete a character.
Type: Mutation (Protected)
Input:
{ id: number; projectId: number }Response:
booleanScenes organize your story into major sections. Shots are individual camera angles or sequences within a scene.
Get all scenes in a project.
Type: Query (Protected)
Input:
{ projectId: number }Response:
Scene[]Create a new scene.
Type: Mutation (Protected)
Input:
{
projectId: number;
title: string;
description?: string;
sceneNumber?: number;
location?: string;
timeOfDay?: string;
mood?: string;
characters?: number[]; // Character IDs
duration?: number; // in seconds
}Response:
SceneGet all shots in a scene.
Type: Query (Protected)
Input:
{ sceneId: number }Response:
Shot[]Create a new shot.
Type: Mutation (Protected)
Input:
{
sceneId: number;
projectId: number;
title: string;
description?: string;
shotNumber?: number;
cameraAngle?: string;
cameraMovement?: string;
duration?: number;
characters?: number[];
props?: string;
lighting?: string;
referenceImageUrl?: string;
}Response:
ShotPrompts are the core of content generation. They can be created manually or enhanced with AI.
Get all prompts in a project.
Type: Query (Protected)
Input:
{ projectId: number }Response:
Prompt[]Create a new prompt.
Type: Mutation (Protected)
Input:
{
projectId: number;
title: string;
content: string;
type?: "video" | "image" | "audio" | "general";
style?: string;
mood?: string;
characters?: number[];
scenes?: number[];
shots?: number[];
tags?: string[];
}Response:
PromptEnhance a prompt using AI with project context.
Type: Mutation (Protected)
Input:
{
projectId: number;
promptId?: number;
content: string;
context?: "character" | "scene" | "shot" | "general";
contextId?: number;
}Response:
{
original: string;
enhanced: string;
suggestions: string[];
}Example:
const enhance = trpc.prompts.enhance.useMutation();
enhance.mutate({
projectId: 1,
content: "A character walking in a city",
context: "character",
contextId: 5,
});Reusable templates with placeholder support for efficient prompt creation.
Get all prompt templates.
Type: Query (Protected)
Input:
{ projectId?: number }Response:
PromptTemplate[]Create a new template.
Type: Mutation (Protected)
Input:
{
name: string;
description?: string;
category?: string;
templateText: string; // Text with {placeholders}
examplePrompt?: string;
tags?: string[];
isPublic?: "private" | "shared" | "public";
projectId?: number;
}Response:
PromptTemplateExample:
const create = trpc.prompts.templates.create.useMutation();
create.mutate({
name: "Cinematic Hero Shot",
templateText: "Create a cinematic shot of {character} in {location}, {mood} lighting, {style}",
category: "cinematic",
tags: ["hero", "cinematic", "character-focused"],
});Get templates filtered by category.
Type: Query (Protected)
Input:
{ category: string; projectId?: number }Response:
PromptTemplate[]Apply a template by filling in placeholders.
Type: Mutation (Protected)
Input:
{
templateId: number;
values: Record<string, string>; // { "character": "Hero", "location": "City" }
}Response:
{
template: PromptTemplate;
filledPrompt: string;
}Generated videos, images, and audio files with metadata and organization.
Get all assets for the current user.
Type: Query (Protected)
Response:
Asset[]Get all assets in a project.
Type: Query (Protected)
Input:
{ projectId: number }Response:
Asset[]Get a specific asset.
Type: Query (Protected)
Input:
{ id: number }Response:
Asset | undefinedCreate an asset record (typically after generation).
Type: Mutation (Protected)
Input:
{
projectId: number;
assetType: "video" | "image" | "audio";
title?: string;
prompt: string;
url: string;
fileKey: string;
duration?: number;
width?: number;
height?: number;
characterIds?: number[];
sceneIds?: number[];
shotIds?: number[];
generationModel?: string;
generationParameters?: Record<string, any>;
status?: "pending" | "completed" | "failed";
}Response:
AssetDelete an asset.
Type: Mutation (Protected)
Input:
{ id: number }Response:
booleanFlexible tagging system and intelligent folders for asset organization.
Get all tags in a project.
Type: Query (Protected)
Input:
{ projectId?: number }Response:
Tag[]Create a new tag.
Type: Mutation (Protected)
Input:
{
name: string;
color?: string; // Hex color, e.g., "#3b82f6"
description?: string;
projectId?: number;
}Response:
TagAdd a tag to an asset.
Type: Mutation (Protected)
Input:
{ assetId: number; tagId: number }Response:
booleanRemove a tag from an asset.
Type: Mutation (Protected)
Input:
{ assetId: number; tagId: number }Response:
booleanGet all tags for an asset.
Type: Query (Protected)
Input:
{ assetId: number }Response:
Tag[]Get all folders in a project.
Type: Query (Protected)
Input:
{ projectId?: number }Response:
IntelligentFolder[]Create a new folder.
Type: Mutation (Protected)
Input:
{
name: string;
description?: string;
folderType: "manual" | "by_type" | "by_character" | "by_scene" | "by_date" | "by_tag" | "by_status" | "smart";
filterRules?: Record<string, any>;
icon?: string;
color?: string;
projectId?: number;
}Response:
IntelligentFolderAdd an asset to a folder.
Type: Mutation (Protected)
Input:
{ folderId: number; assetId: number; position?: number }Response:
booleanGet all assets in a folder.
Type: Query (Protected)
Input:
{ folderId: number }Response:
Asset[]AI-powered content generation endpoints.
Generate a video using fal.ai.
Type: Mutation (Protected)
Input:
{
projectId: number;
prompt: string;
model: "veo" | "kling" | "wan" | "ltx";
duration?: number;
width?: number;
height?: number;
characterIds?: number[];
sceneIds?: number[];
referenceImageUrl?: string;
negativePrompt?: string;
}Response:
{
assetId: number;
url: string;
duration: number;
status: "completed" | "failed";
error?: string;
}Generate an image using fal.ai.
Type: Mutation (Protected)
Input:
{
projectId: number;
prompt: string;
model: "flux" | "nano-banana";
width?: number;
height?: number;
characterIds?: number[];
sceneIds?: number[];
referenceImageUrl?: string;
negativePrompt?: string;
}Response:
{
assetId: number;
url: string;
width: number;
height: number;
status: "completed" | "failed";
error?: string;
}Generate audio using fal.ai.
Type: Mutation (Protected)
Input:
{
projectId: number;
prompt: string;
duration?: number;
voiceId?: string;
}Response:
{
assetId: number;
url: string;
duration: number;
status: "completed" | "failed";
error?: string;
}Extract frames from a generated video.
Type: Mutation (Protected)
Input:
{
assetId: number;
frameIndices?: number[]; // Specific frames, or all if not provided
}Response:
{
frameAssets: Asset[];
totalFrames: number;
}All endpoints follow consistent error handling patterns.
{
code: "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "BAD_REQUEST" | "INTERNAL_SERVER_ERROR";
message: string;
data?: {
code: string;
httpStatus: number;
};
}| Code | Status | Meaning |
|---|---|---|
| UNAUTHORIZED | 401 | User not authenticated |
| FORBIDDEN | 403 | User lacks permission |
| NOT_FOUND | 404 | Resource not found |
| BAD_REQUEST | 400 | Invalid input |
| INTERNAL_SERVER_ERROR | 500 | Server error |
| PARSE_ERROR | 400 | Invalid JSON |
| CONFLICT | 409 | Resource already exists |
const mutation = trpc.projects.create.useMutation({
onError: (error) => {
if (error.data?.code === "UNAUTHORIZED") {
// Redirect to login
} else if (error.data?.code === "BAD_REQUEST") {
// Show validation error
toast.error(error.message);
} else {
// Show generic error
toast.error("Something went wrong");
}
},
});// 1. Create a project
const projectMutation = trpc.projects.create.useMutation();
const project = await projectMutation.mutateAsync({
title: "My Film",
genre: "Drama",
});
// 2. Create characters
const charMutation = trpc.characters.create.useMutation();
const hero = await charMutation.mutateAsync({
projectId: project.id,
name: "Alex",
description: "The protagonist",
age: "30s",
});
// 3. Create a scene
const sceneMutation = trpc.scenes.create.useMutation();
const scene = await sceneMutation.mutateAsync({
projectId: project.id,
title: "Opening Scene",
location: "City Street",
});
// 4. Create a prompt
const promptMutation = trpc.prompts.create.useMutation();
const prompt = await promptMutation.mutateAsync({
projectId: project.id,
content: "Alex walking down a busy city street at sunset",
type: "video",
characters: [hero.id],
scenes: [scene.id],
});
// 5. Generate video
const genMutation = trpc.generation.generateVideo.useMutation();
const video = await genMutation.mutateAsync({
projectId: project.id,
prompt: prompt.content,
model: "veo",
duration: 10,
});
// 6. Tag the asset
const tagMutation = trpc.tags.addToAsset.useMutation();
await tagMutation.mutateAsync({
assetId: video.assetId,
tagId: heroShotsTagId,
});Last Updated: March 2026 API Version: 1.0