Skip to main content

Cloud Functions API

All Cloud Functions are deployed at us-central1 in Firebase project yugmastudio-addcd. Callable functions require Firebase Authentication.

Invocation

import { getFunctions, httpsCallable } from 'firebase/functions'

const functions = getFunctions()
const fn = httpsCallable(functions, 'functionName')
const result = await fn({ ...params })

AI Functions

aiCompose

The AI brain. Delegates to composeCore and runs an agentic tool-use loop (default 3 iterations, configurable 0–5 via AI_MAX_ITERATIONS). After each iteration a pure-math scene audit appends a SCENE AUDIT: line to the tool results (heavy overlaps, floating/sunken/oversized objects) so the model self-corrects on its next turn. aiComposeStream is the SSE variant — same composeCore, timeoutSeconds: 300.

Timeout: 180s | Secrets: ANTHROPIC_API_KEY, CEREBRAS_API_KEY, GEMINI_API_KEY

FieldTypeRequiredDescription
messages{role, content}[]YesConversation history
sceneContextobjectNoYSL scene text, objects, environment, styleHint
mode'creative' | 'precise'NoTemperature toggle (0.7 / 0.2)
sessionIdstringNoSession ID for cross-session persistence

Returns:

{
"text": "I've created a sci-fi hangar with...",
"toolCalls": [{ "name": "add_object", "input": {...} }, ...],
"iterations": 3,
"totalToolCalls": 7
}

generateMaterial

Generate PBR material values from a text description.

FieldTypeRequiredDescription
descriptionstringYese.g. "weathered copper with patina"

Returns: { color, roughness, metalness, emissive, emissiveIntensity }

inspectMaterial

Analyze a material and suggest improvements.

FieldTypeRequiredDescription
materialobjectYesCurrent material properties

Returns: { analysis, suggestions[] }

rankAssetCandidates

Vision-ranks Sketchfab search candidates for the client-side import_from_sketchfab flow. The client sends candidate thumbnail URLs (Sketchfab hosts only); the server fetches the images and asks Gemini which candidate is the single clean object matching the intent — keeping GEMINI_API_KEY server-side. Kill-switch: ASSET_VISION_RANK=off.

Secrets: GEMINI_API_KEY

FieldTypeRequiredDescription
querystringYesThe import search query, e.g. "office chair"
candidates{ thumbnailUrl, name?, license? }[]Yes2–6 candidates; thumbnails must be https URLs on sketchfab.com

Returns: { ok: true, verdict } when a verdict was reached; { ok: false } on any soft failure (feature disabled, no key, vision error, nothing parseable). The client treats ok: false as "use the first result" — this call never blocks an import.


Generation Functions

generateAsset

Start a Meshy.ai text-to-3D generation job.

FieldTypeRequiredDescription
promptstringYesDescription of the 3D model

Returns: { jobId, status: 'pending' }

sweepGenerationJobs (scheduled)

Replaces the deleted checkGenerationStatus callable. Runs every minute, polls Meshy for all processing jobs, and updates each generationJobs/{jobId} document. Clients observe progress via a Firestore onSnapshot listener on their job document (owner-readable) instead of polling a callable.


Project Functions

deleteProject

Delete a project and cascade-remove associated assets.

FieldTypeRequiredDescription
projectIdstringYesProject to delete

Authorization: Owner only.

exportScene

Convert a Yugma scene to glTF 2.0 JSON.

FieldTypeRequiredDescription
sceneobjectYesScene JSON

Storage Functions

generateSignedUploadUrl

FieldTypeRequired
filenamestringYes

Returns: { url, path } — PUT to the URL with appropriate Content-Type.

generateSignedDownloadUrl

FieldTypeRequired
pathstringYes

Returns: { url } — expires after 1 hour.


Billing

stripeWebhook

HTTP endpoint (not a callable). Stripe posts subscription events here. It verifies the Stripe-Signature header using Stripe's v1 scheme (HMAC-SHA256 over <timestamp>.<rawBody>, constant-time compare, 5-minute tolerance, keyed by STRIPE_WEBHOOK_SECRET) and handles three events: checkout.session.completed, customer.subscription.updated, and customer.subscription.deleted.

Processing is level-triggered, not edge-triggered: every subscription is mirrored into users/{uid}.billingSubs, and on each event the effective tier (premium / ultimate) is recomputed as the highest tier among still-active subscriptions — so out-of-order or duplicate deliveries converge to the customer's true entitlement. Idempotency is enforced via stripeEvents/{event.id}; test-mode (livemode !== true) events never grant a tier. The buyer's UID arrives as client_reference_id on the Payment Link checkout, and the tier is read from metadata.tier on the session / price.

The retired lemonsqueezyWebhook endpoint is still exported but dormantstripeWebhook is the live billing path.

The former Phase 12/14/16 stub functions (startVideoReconstruction, octopartProxy, renderStoryboard) were removed from the codebase in the 2026-07 cleanup and are not deployed. See the feature docs for their planned designs.


Auth Triggers

onUserCreate (v1)

Seeds a user profile document in Firestore on signup.

onUserDelete (v1)

Cascade-deletes user profile and projects on account deletion.


Error Codes

CodeMeaning
unauthenticatedNo valid auth token
invalid-argumentMissing or invalid parameters
not-foundResource doesn't exist
permission-deniedUser lacks access
resource-exhaustedRate limit exceeded (30/hr for AI)

Secrets

SecretUsed byStatus
GEMINI_API_KEYaiCompose, aiComposeStream, rankAssetCandidatesSet via firebase secrets
ANTHROPIC_API_KEYaiCompose, aiComposeStream, generateMaterial, inspectMaterialSet via firebase secrets
CEREBRAS_API_KEYaiCompose, aiComposeStreamSet via firebase secrets
MESHY_API_KEYgenerateAsset, sweepGenerationJobsSet via firebase secrets
STRIPE_WEBHOOK_SECRETstripeWebhookSet via firebase secrets