{"openapi":"3.1.0","info":{"title":"Lamina v1 API","version":"1.0.0","description":"Lamina is a visual AI workflow builder. The v1 API lets agents discover apps, execute content creation workflows, access brand intelligence, publish to social channels, and manage content at scale.\n\nAuthentication: Include your API key in the `x-api-key` header or as a Bearer token."},"servers":[{"url":"/v1","description":"Lamina API v1"}],"security":[{"apiKey":[]},{"bearerAuth":[]}],"tags":[{"name":"Apps","description":"Discover and inspect available content creation apps"},{"name":"Runs","description":"Run workflows and track run progress"},{"name":"Assets","description":"Browse generated assets from past runs"},{"name":"Intelligence","description":"Brand context, performance prediction, recommendations, and trends"},{"name":"Publishing","description":"Publish content to connected social channels"},{"name":"Compound","description":"High-level content operations: create, score, brief, batch"},{"name":"Account","description":"Credit balance and rate limit visibility"},{"name":"Templates","description":"Content creation templates and strategies"},{"name":"Webhooks","description":"Webhook signature verification"}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"Workspace API key (starts with lma_)"},"bearerAuth":{"type":"http","scheme":"bearer","description":"API key as Bearer token"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"details":{"type":"array","items":{"type":"string"}}},"required":["error"]},"Pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["total","limit","offset"]},"AppCapabilities":{"type":"object","description":"Semantic capabilities derived from workflow composition — helps agents understand what this app does and produces.","properties":{"produces":{"type":"array","items":{"type":"string"},"description":"What this app produces (e.g. \"photo\", \"video-clip\", \"voiceover\")"},"strengths":{"type":"array","items":{"type":"string"},"description":"What this app is good at"},"bestFor":{"type":"array","items":{"type":"string"},"description":"Best use cases for this app"},"limitations":{"type":"array","items":{"type":"string"},"description":"Known limitations"},"outputFormats":{"type":"array","items":{"type":"string"},"description":"Output MIME types (e.g. \"image/png\", \"video/mp4\")"},"hasQualityControl":{"type":"boolean","description":"Whether the workflow includes automated quality control"},"hasHumanApproval":{"type":"boolean","description":"Whether the workflow requires human approval"},"generationStepCount":{"type":"integer","description":"Number of AI generation steps"},"nodeTypes":{"type":"array","items":{"type":"string"},"description":"Node types used in the workflow"}},"required":["produces","strengths","bestFor","limitations","outputFormats","hasQualityControl","hasHumanApproval","generationStepCount","nodeTypes"]},"AppDiscoveryFrontmatter":{"type":"object","description":"Author-managed discovery metadata. Arrays are normalized, de-duplicated tags used by UI, REST, and MCP search.","properties":{"schemaVersion":{"type":"integer","enum":[1]},"summary":{"type":"string","maxLength":600},"categories":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"useCases":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"keywords":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"aliases":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"formats":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"platforms":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"audiences":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20},"excludedIntents":{"type":"array","items":{"type":"string","maxLength":80},"maxItems":20}},"required":["schemaVersion","summary","categories","useCases","keywords","aliases","formats","platforms","audiences","excludedIntents"]},"AppDiscoveryMatchReason":{"type":"object","properties":{"source":{"type":"string","enum":["name","description","frontmatter","capability","semantic"]},"field":{"type":"string"},"terms":{"type":"array","items":{"type":"string"}},"explanation":{"type":"string"}},"required":["source","explanation"]},"AppSummary":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"isPublic":{"type":"boolean"},"capabilities":{"type":"object","description":"Semantic capabilities derived from workflow composition — helps agents understand what this app does and produces.","properties":{"produces":{"type":"array","items":{"type":"string"},"description":"What this app produces (e.g. \"photo\", \"video-clip\", \"voiceover\")"},"strengths":{"type":"array","items":{"type":"string"},"description":"What this app is good at"},"bestFor":{"type":"array","items":{"type":"string"},"description":"Best use cases for this app"},"limitations":{"type":"array","items":{"type":"string"},"description":"Known limitations"},"outputFormats":{"type":"array","items":{"type":"string"},"description":"Output MIME types (e.g. \"image/png\", \"video/mp4\")"},"hasQualityControl":{"type":"boolean","description":"Whether the workflow includes automated quality control"},"hasHumanApproval":{"type":"boolean","description":"Whether the workflow requires human approval"},"generationStepCount":{"type":"integer","description":"Number of AI generation steps"},"nodeTypes":{"type":"array","items":{"type":"string"},"description":"Node types used in the workflow"}},"required":["produces","strengths","bestFor","limitations","outputFormats","hasQualityControl","hasHumanApproval","generationStepCount","nodeTypes"],"nullable":true}},"required":["appId","name","isPublic"]},"AppParameter":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["text","url","options"]},"required":{"type":"boolean"},"description":{"type":"string"},"options":{"type":"array","items":{"type":"string"}},"default":{},"accept":{"type":"array","items":{"type":"string"}},"multiple":{"type":"boolean"}},"required":["id","name","type","required"]},"AppDetail":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"parameters":{"type":"array","items":{"$ref":"#/components/schemas/AppParameter"}},"outputs":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"label":{"type":"string"},"type":{"type":"string","enum":["image","video","audio","text"]}},"required":["index","label","type"]}},"frontmatter":{"$ref":"#/components/schemas/AppDiscoveryFrontmatter"},"capabilities":{"$ref":"#/components/schemas/AppCapabilities"}},"required":["appId","name","parameters","outputs","frontmatter","capabilities"]},"WorkflowNode":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"label":{"type":"string"}},"required":["id","type","label"]},"WorkflowEdge":{"type":"object","properties":{"source":{"type":"string"},"target":{"type":"string"}},"required":["source","target"]},"AppWorkflow":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"nodes":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowNode"}},"edges":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowEdge"}}},"required":["appId","name","nodes","edges"]},"SuggestedNextStep":{"type":"object","properties":{"description":{"type":"string","description":"Human-readable next step description"},"toolHint":{"type":"string","nullable":true,"description":"Lamina tool name to invoke (e.g. \"run_app\", \"lamina_create\", \"publish_content\")"}},"required":["description","toolHint"]},"OutputDimensions":{"type":"object","properties":{"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"}},"required":["width","height"]},"ExecutionOutput":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"},"value":{"nullable":true},"status":{"type":"string"},"error":{"type":"string","nullable":true},"mimeType":{"type":"string","description":"Canonical MIME type (e.g. \"image/png\", \"video/mp4\"). Present on completed outputs."},"contentDescription":{"type":"string","nullable":true,"description":"What was produced (e.g. \"AI-generated photograph\"). Present on completed outputs."},"compatibleInputTypes":{"type":"array","items":{"type":"string"},"description":"Downstream tool categories this output can feed into. Present on completed outputs."},"suggestedNextSteps":{"type":"array","items":{"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/SuggestedNextStep"}]},"description":"Actionable hints for chaining. Each item is either a plain string or an object with description and toolHint. Present on completed outputs."},"canChainAs":{"type":"array","items":{"type":"string"},"description":"Semantic roles this output can play in a pipeline (e.g. \"hero_image\", \"social_clip\"). Present on completed outputs."},"platformsOptimized":{"type":"array","items":{"type":"string"},"description":"Platforms the output is likely formatted for (e.g. \"instagram\", \"tiktok\"). Present on completed outputs."},"dimensions":{"type":"object","properties":{"width":{"type":"integer","description":"Width in pixels"},"height":{"type":"integer","description":"Height in pixels"}},"required":["width","height"],"nullable":true,"description":"Output dimensions in pixels. Present on completed outputs when metadata is available."},"durationSeconds":{"type":"number","nullable":true,"description":"Duration in seconds. Present on completed video/audio outputs when metadata is available."}},"required":["id","label","type","status"]},"ExecutionResponse":{"type":"object","properties":{"runId":{"type":"string","format":"uuid"},"workflowId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","completed","failed","cancelled"]},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/ExecutionOutput"}},"errorMessage":{"type":"string","nullable":true},"cost":{"type":"object","description":"What the run cost, when the orchestrator recorded it.","properties":{"credits":{"type":"number"}}},"startedAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["runId","workflowId","status","createdAt"]},"ExecutionSummary":{"type":"object","properties":{"runId":{"type":"string","format":"uuid"},"workflowId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","completed","failed","cancelled"]},"source":{"type":"string"},"errorMessage":{"type":"string","nullable":true},"startedAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["runId","workflowId","status","createdAt"]},"AssetRecord":{"type":"object","properties":{"id":{"type":"string"},"runId":{"type":"string","format":"uuid"},"nodeLabel":{"type":"string"},"outputType":{"type":"string"},"sourceUrl":{"type":"string","nullable":true},"cdnUrl":{"type":"string","nullable":true},"textContent":{"type":"string","nullable":true},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","runId","outputType","status","createdAt"]},"ToneSpectrum":{"type":"object","nullable":true,"properties":{"primary":{"type":"string","nullable":true},"secondary":{"type":"string","nullable":true},"avoid":{"type":"array","items":{"type":"string"}}}},"PerformanceProfile":{"type":"object","nullable":true,"properties":{"topPatterns":{"type":"array","items":{"type":"string"}},"weakPatterns":{"type":"array","items":{"type":"string"}},"avgEngagementTier":{"type":"string","nullable":true}}},"BrandDna":{"type":"object","nullable":true,"properties":{"voiceAttributes":{"type":"array","items":{"type":"string"}},"visualIdentity":{"type":"array","items":{"type":"string"}},"contentPillars":{"type":"array","items":{"type":"string"}},"audienceSignals":{"type":"array","items":{"type":"string"}},"guardrails":{"type":"array","items":{"type":"string"}},"toneSpectrum":{"$ref":"#/components/schemas/ToneSpectrum"},"performanceProfile":{"$ref":"#/components/schemas/PerformanceProfile"}}},"BrandIdentity":{"type":"object","nullable":true,"properties":{"category.primary":{"type":"string","nullable":true},"category.sub":{"type":"string","nullable":true},"offering":{"type":"array","items":{"type":"string"}},"business_model":{"type":"string","nullable":true},"price_tier":{"type":"string","nullable":true},"value_proposition":{"type":"string","nullable":true},"proof_point":{"type":"array","items":{"type":"string"}},"audience.segment":{"type":"array","items":{"type":"string"}},"market.geography":{"type":"array","items":{"type":"string"}},"market.language":{"type":"array","items":{"type":"string"}},"market.currency":{"type":"string","nullable":true},"seasonality.moment":{"type":"array","items":{"type":"string"}}}},"BrandStrategy":{"type":"object","nullable":true,"description":"Accepted evidence-backed public brand strategy for the selected scope.","properties":{"tagline":{"type":"string","nullable":true},"mission":{"type":"string","nullable":true},"goals":{"type":"array","items":{"type":"string"}},"values":{"type":"array","items":{"type":"string"}},"differentiators":{"type":"array","items":{"type":"string"}},"messagingPillars":{"type":"array","items":{"type":"string"}},"audienceNeeds":{"type":"array","items":{"type":"string"}},"voiceDirectives":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"kind":{"type":"string","enum":["use","avoid"]}},"required":["text","kind"]}}}},"BrandObjective":{"type":"object","description":"A currently applicable objective authored by the workspace team.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"statement":{"type":"string"},"successMeasure":{"type":"string","nullable":true},"priority":{"type":"integer","minimum":1,"maximum":5},"claimScope":{"type":"string","enum":["global","market","product"]},"scopeKey":{"type":"string"},"scopeLabel":{"type":"string","nullable":true},"startsAt":{"type":"string","format":"date-time","nullable":true},"endsAt":{"type":"string","format":"date-time","nullable":true},"currentlyApplicable":{"type":"boolean","enum":[true]},"revision":{"type":"integer"}},"required":["id","type","statement","priority","claimScope","scopeKey","currentlyApplicable","revision"]},"BrandKitElement":{"type":"object","description":"A reusable brand identity asset — a named, versioned pointer to a primitive (cloned_voice / persona / asset) plus a type-specific spec.","properties":{"id":{"type":"string"},"element_type":{"type":"string","enum":["voice","avatar","character","motion_graphic"]},"name":{"type":"string"},"ref_kind":{"type":"string","enum":["cloned_voice","persona","asset"],"nullable":true},"ref_id":{"type":"string","nullable":true},"spec":{"type":"object"},"version":{"type":"integer"},"is_active":{"type":"boolean"}},"required":["id","element_type","name"]},"GuidancePackage":{"type":"object","nullable":true,"properties":{"promptDirectives":{"type":"array","items":{"type":"string"}},"negativePrompts":{"type":"array","items":{"type":"string"}},"recommendedMoves":{"type":"array","items":{"type":"string"}},"testIdeas":{"type":"array","items":{"type":"string"}},"winningPatterns":{"type":"array","items":{"type":"string"}},"weakPatterns":{"type":"array","items":{"type":"string"}},"supportingMetrics":{"type":"array","items":{"type":"string"}},"creativeStructure":{"nullable":true}}},"TopPatternItem":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string","nullable":true},"modality":{"type":"string","nullable":true},"platform":{"type":"string","nullable":true},"performanceScore":{"type":"number"},"winningPatterns":{"type":"array","items":{"type":"string"}}}},"PatternSummary":{"type":"object","properties":{"pattern":{"type":"string"},"occurrences":{"type":"integer"},"avgPerformance":{"type":"number"}}},"TopPatterns":{"type":"object","nullable":true,"properties":{"topItems":{"type":"array","items":{"$ref":"#/components/schemas/TopPatternItem"}},"topPatterns":{"type":"array","items":{"$ref":"#/components/schemas/PatternSummary"}},"weakPatterns":{"type":"array","items":{"$ref":"#/components/schemas/PatternSummary"}}}},"BrandContext":{"type":"object","properties":{"brandDna":{"$ref":"#/components/schemas/BrandDna"},"brandIdentity":{"$ref":"#/components/schemas/BrandIdentity"},"brandStrategy":{"$ref":"#/components/schemas/BrandStrategy"},"brandObjectives":{"type":"array","items":{"$ref":"#/components/schemas/BrandObjective"}},"guidance":{"$ref":"#/components/schemas/GuidancePackage"},"topPatterns":{"$ref":"#/components/schemas/TopPatterns"}}},"Recommendation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string"},"status":{"type":"string"},"priority":{"type":"integer"},"title":{"type":"string"},"summary":{"type":"string","nullable":true},"data":{"type":"object"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","type","status","priority","title","createdAt"]},"Channel":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"platform":{"type":"string"},"accountName":{"type":"string","nullable":true},"accountType":{"type":"string","nullable":true},"username":{"type":"string","nullable":true},"hasInstagram":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","platform","createdAt"]},"PublishHistoryItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"platform":{"type":"string","nullable":true},"contentType":{"type":"string"},"contentUrl":{"type":"string","nullable":true},"caption":{"type":"string","nullable":true},"postUrl":{"type":"string","nullable":true},"status":{"type":"string"},"error":{"type":"string","nullable":true},"publishedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}},"required":["id","status","createdAt"]},"CreditBalance":{"type":"object","properties":{"balance":{"type":"number"},"totalEarned":{"type":"number"},"totalSpent":{"type":"number"}},"required":["balance","totalEarned","totalSpent"]},"UsageResponse":{"type":"object","properties":{"credits":{"$ref":"#/components/schemas/CreditBalance"},"rateLimit":{"type":"object","properties":{"limit":{"type":"integer","description":"Requests per window"},"windowMs":{"type":"integer","description":"Window size in milliseconds"}}}},"required":["credits"]},"ContentTemplate":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string","enum":["launch","trend","campaign","optimization","testing","library"]},"suggestedModalities":{"type":"array","items":{"type":"string"}},"suggestedPlatforms":{"type":"array","items":{"type":"string"}},"isBuiltIn":{"type":"boolean"}},"required":["id","name","description","category","isBuiltIn"]},"ContentTemplateDetail":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"suggestedModalities":{"type":"array","items":{"type":"string"}},"suggestedPlatforms":{"type":"array","items":{"type":"string"}},"guidanceData":{"type":"object","properties":{"promptDirectives":{"type":"array","items":{"type":"string"}},"negativePrompts":{"type":"array","items":{"type":"string"}},"winningPatterns":{"type":"array","items":{"type":"string"}},"testIdeas":{"type":"array","items":{"type":"string"}},"creativeStructure":{"nullable":true}}},"multiAssetComposition":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"modality":{"type":"string"},"description":{"type":"string"}}}},"isBuiltIn":{"type":"boolean"}},"required":["id","name","description","category","isBuiltIn"]},"BatchCreateItem":{"type":"object","properties":{"brief":{"type":"string","description":"Content creation brief"},"platform":{"type":"string","nullable":true},"modality":{"type":"string","nullable":true},"appId":{"type":"string","format":"uuid","nullable":true},"brandProfileId":{"type":"string","format":"uuid","nullable":true},"campaignId":{"type":"string","format":"uuid","nullable":true},"inputs":{"type":"object","nullable":true}},"required":["brief"]},"BatchResultItem":{"type":"object","properties":{"index":{"type":"integer"},"status":{"type":"string","enum":["queued","failed"]},"runId":{"type":"string","format":"uuid"},"workflowId":{"type":"string","format":"uuid"},"workflowName":{"type":"string"},"error":{"type":"string"}},"required":["index","status"]}}},"paths":{"/health":{"get":{"summary":"Health check","description":"Lightweight health probe. No authentication required.","operationId":"healthCheck","tags":["Account"],"security":[],"responses":{"200":{"description":"Server is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}},"required":["status","version","timestamp"]}}}}}}},"/apps":{"get":{"summary":"List apps","description":"List all apps accessible to the authenticated workspace, including public apps.","operationId":"listApps","tags":["Apps"],"parameters":[{"name":"search","in":"query","schema":{"type":"string"},"description":"Filter by name or description"},{"name":"limit","in":"query","schema":{"type":"integer","default":10},"description":"Max public apps returned"}],"responses":{"200":{"description":"List of apps","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AppSummary"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}":{"get":{"summary":"Get app details","description":"Get an app's metadata and parameter definitions.","operationId":"getApp","tags":["Apps"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"App details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AppDetail"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"App not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}/workflow":{"get":{"summary":"Get app workflow graph","description":"Get the DAG (nodes and edges) of the app's workflow.","operationId":"getAppWorkflow","tags":["Apps"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Workflow graph","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AppWorkflow"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"App not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/discover":{"post":{"summary":"Discover apps by intent","description":"Hybrid discovery: describe what you want to create and get ranked app matches from lexical metadata, workflow capabilities, and semantic retrieval.","operationId":"discoverApps","tags":["Apps"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["intent"],"properties":{"intent":{"type":"string","description":"Describe what you want to create"},"constraints":{"type":"object","properties":{"maxCredits":{"type":"number","description":"Maximum credit budget"},"outputFormat":{"type":"string","description":"Required output MIME type"}}},"limit":{"type":"integer","default":5,"maximum":10,"description":"Max results to return"}}}}}},"responses":{"200":{"description":"Ranked app matches","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"matches":{"type":"array","items":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"relevanceScore":{"type":"number"},"capabilities":{"$ref":"#/components/schemas/AppCapabilities"},"formats":{"type":"array","items":{"type":"string"}},"platforms":{"type":"array","items":{"type":"string"}},"matchReasons":{"type":"array","items":{"$ref":"#/components/schemas/AppDiscoveryMatchReason"}},"matchedTerms":{"type":"array","items":{"type":"string"}},"estimatedCredits":{"type":"number","nullable":true},"whyMatch":{"type":"string"}},"required":["appId","name","relevanceScore","capabilities","formats","platforms","matchReasons","matchedTerms","whyMatch"]}},"intent":{"type":"object","properties":{"medium":{"type":"string"},"summary":{"type":"string"}}}},"required":["matches","intent"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}/estimate":{"post":{"summary":"Estimate run cost","description":"Estimate the credit cost and duration for running an app before committing to execution. Returns a cost breakdown by node, the expected total, and the current credit balance so agents can make informed cost/quality tradeoff decisions.","operationId":"estimateRunCost","tags":["Apps"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Cost estimate for running this app","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"estimatedCredits":{"type":"object","properties":{"expected":{"type":"number","description":"Expected credit cost for a single run"},"min":{"type":"number","description":"Minimum cost (no retries)"},"max":{"type":"number","description":"Maximum cost (with quality check retries)"}},"required":["expected","min","max"]},"breakdown":{"type":"array","items":{"type":"object","properties":{"nodeId":{"type":"string"},"nodeType":{"type":"string"},"credits":{"type":"number"}}}},"currentBalance":{"type":"number","description":"Current workspace credit balance"},"affordable":{"type":"boolean","description":"Whether the workspace can afford this run"}},"required":["appId","name","estimatedCredits","breakdown","currentBalance","affordable"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}/runs":{"post":{"summary":"Run an app","description":"Start a new run of an app with the given inputs. Returns immediately with run ID; poll GET /runs/{id} or use SSE streaming for results.","operationId":"runApp","tags":["Runs"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"webhook","in":"query","schema":{"type":"string","format":"uri"},"description":"Webhook URL for completion callback"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"inputs":{"type":"object","description":"Input values keyed by parameter name or ID"},"inputOverrides":{"type":"object","description":"Per-node input overrides"},"applyBrand":{"type":"boolean","default":false,"description":"Fold the workspace's brand (negatives + visual style) onto the app's visual generation nodes so output is on-brand, without hand-writing brand into `inputs`. Layered below your `inputs`, which always win."},"brandProfileId":{"type":"string","description":"Target a specific brand profile when `applyBrand` is set. Omit to use the workspace active brand."},"test":{"type":"boolean","default":false,"description":"Sandbox mode (or send header `X-Lamina-Test: true`): validate inputs and return a deterministic stub run — no execution is dispatched and no credits are charged."}}}}}},"responses":{"202":{"description":"Execution started","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"runId":{"type":"string","format":"uuid"},"workflowId":{"type":"string","format":"uuid"},"workflowName":{"type":"string"},"status":{"type":"string"},"webhookUrl":{"type":"string","nullable":true},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/ExecutionOutput"}}},"required":["runId","workflowId","status"]}},"required":["data"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workflows/generate":{"post":{"summary":"Generate or edit an app from a text instruction","description":"Analyze a plain-language instruction with the configured workflow planner, assemble a validated workflow graph from the node catalog, and auto-publish it as a private, immediately-runnable app. Returns the app schema; run it via POST /apps/{appId}/runs. Pass baseAppId to EDIT an existing generated app in place instead of building a new one.","operationId":"generateWorkflow","tags":["Apps"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"instruction":{"type":"string","description":"What the app should create — or, with baseAppId, the change to apply (e.g. \"add a 9:16 crop output\")."},"baseAppId":{"type":"string","description":"Edit mode. The appId of a generated app to modify in place (same appId, run history preserved). The planner starts from its current graph and applies the instruction as a targeted edit. Requires creator or workspace owner/admin. Omit to build a new app."},"ops":{"type":"array","description":"Edit mode cheap path: explicit edit operations applied deterministically (no planner LLM call, no credit charge). Requires baseAppId; instruction becomes optional. Each item is one of setNodeData / addNode / removeNode / addEdge / removeEdge / addParameter / removeParameter / setParameter.","items":{"type":"object"}},"name":{"type":"string","description":"Optional preferred app name."},"visibility":{"type":"string","enum":["private","shared","public"],"default":"private"},"provider":{"type":"string","enum":["claude","openai"],"description":"Planner LLM provider override. Defaults to WFGEN_PROVIDER, then OpenAI."},"brandProfileId":{"type":"string","description":"Bake a specific brand profile's voice, visual anchors, and guardrails into the generated app so it produces on-brand output. Omit to use the workspace's active brand."},"run":{"type":"boolean","default":false,"description":"One-shot: after generating the app, immediately start a run using `inputs`. Returns a `run` object with the runId — poll GET /runs/{runId}."},"inputs":{"type":"object","description":"Input values keyed by the generated app's parameter `key` (media as URLs, options as labels). Used only when `run` is true."},"test":{"type":"boolean","default":false,"description":"Sandbox mode (or send header `X-Lamina-Test: true`): validate the request and return a stub app — no planner LLM call, nothing persisted, no credits charged."}},"required":["instruction"]}}}},"responses":{"200":{"description":"App generated and published","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"visibility":{"type":"string","enum":["private","shared","public"]},"runUrl":{"type":"string"},"parameters":{"type":"array","items":{"type":"object"}},"outputs":{"type":"array","items":{"type":"object"}},"tier":{"type":"string","enum":["deterministic","fast_edit","recipe","planner"],"description":"Which path produced this: `deterministic` (explicit ops, no LLM, free) or `planner` (LLM generation)."},"creditsSpent":{"type":"number","description":"Credits this generation charged (0 for the deterministic ops path)."},"editability":{"type":"object","nullable":true,"description":"Deterministic measure of how tweakable the generated app is — param clarity, grouping, node granularity, output-steerability (planner tier only). A low `score` plus its `notes` is a cue to offer the user a refinement.","properties":{"score":{"type":"number","description":"0–1; higher = more editable."},"subscores":{"type":"object"},"notes":{"type":"array","items":{"type":"string"}}}},"run":{"type":"object","nullable":true,"description":"Present only when `run` was requested.","properties":{"started":{"type":"boolean"},"runId":{"type":"string","format":"uuid"},"status":{"type":"string"},"errors":{"type":"array","items":{"type":"object"}}},"required":["started"]}},"required":["appId","name","runUrl"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/cancel":{"post":{"summary":"Cancel a run","description":"Cancel a queued or running execution. Idempotent on terminal runs.","operationId":"cancelRun","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Run cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"runId":{"type":"string","format":"uuid"},"status":{"type":"string"}},"required":["runId","status"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/freestyle/{runId}":{"get":{"summary":"Get freestyle run status","description":"Poll the status and outputs of a freestyle (recipe) run.","operationId":"getFreestyleRun","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Freestyle run status","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExecutionResponse"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/match":{"post":{"summary":"Match apps to an intent","description":"Rank the workspace apps that best fit an intent, document, or a specific field — useful when embedding Lamina into a document/form workflow. Provide at least one of intent, document, or fieldName.","operationId":"matchApps","tags":["Apps"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"intent":{"type":"string","description":"Free-text description of the goal."},"document":{"type":"object","description":"Document context to match against."},"fieldName":{"type":"string"},"fieldDescription":{"type":"string"},"modality":{"type":"string","enum":["image","video","audio"]},"limit":{"type":"integer","default":5}}}}}},"responses":{"200":{"description":"Matched apps","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Ranked app matches with reasoning."}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/account":{"get":{"summary":"Get account identity","description":"The API key's user identity and the workspaces it can access. For credit balance and rate limits use GET /account/usage.","operationId":"getAccount","tags":["Account"],"responses":{"200":{"description":"Account identity","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"userId":{"type":"string"},"email":{"type":"string","nullable":true},"workspaces":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","nullable":true},"role":{"type":"string"}}}}}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}/visibility":{"post":{"summary":"Set app visibility","description":"Promote or demote an app between private, shared (workspace-wide), and public. Only the app creator or a workspace owner may change visibility.","operationId":"setAppVisibility","tags":["Apps"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"visibility":{"type":"string","enum":["private","shared","public"]}},"required":["visibility"]}}}},"responses":{"200":{"description":"Visibility updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"appId":{"type":"string","format":"uuid"},"name":{"type":"string"},"visibility":{"type":"string","enum":["private","shared","public"]}},"required":["appId","visibility"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}/versions":{"get":{"summary":"List app versions","description":"Every edit via POST /workflows/generate (with baseAppId) snapshots the app's prior graph as a restorable version. This lists them, newest first.","operationId":"listAppVersions","tags":["Apps"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"App version list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"appId":{"type":"string"},"versions":{"type":"array","items":{"type":"object","properties":{"version":{"type":"integer"},"createdAt":{"type":"string","nullable":true},"createdBy":{"type":"string","nullable":true},"changeSummary":{"type":"string","nullable":true}}}}},"required":["appId","versions"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/apps/{appId}/versions/{version}/restore":{"post":{"summary":"Restore an app version","description":"Restore an app to a prior version's graph and parameters. The current graph is snapshotted first, so the restore is itself undoable. Requires the app creator or a workspace owner/admin.","operationId":"restoreAppVersion","tags":["Apps"],"parameters":[{"name":"appId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"version","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"App restored","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"appId":{"type":"string"},"restoredFrom":{"type":"integer"},"newVersion":{"type":"integer"}},"required":["appId","restoredFrom","newVersion"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs":{"get":{"summary":"List runs","description":"List past runs for the workspace with optional filters.","operationId":"listRuns","tags":["Runs"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["queued","running","completed","failed","cancelled"]}},{"name":"appId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filter by app/workflow ID"},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Only runs created after this ISO date"}],"responses":{"200":{"description":"Paginated run list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExecutionSummary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}":{"get":{"summary":"Get run status","description":"Get the current status and outputs of a run.","operationId":"getRun","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Run status with outputs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExecutionResponse"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/stream":{"get":{"summary":"Stream run progress (SSE)","description":"Server-Sent Events stream for real-time run progress. Events: progress, node_complete, complete, error, timeout.","operationId":"streamRun","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"SSE event stream","content":{"text/event-stream":{"schema":{"type":"string"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/wait":{"get":{"summary":"Wait for run (long-poll)","description":"Block until the run reaches a terminal state or the timeout expires. Simpler alternative to SSE for agents that cannot consume event streams. Returns `timeout: true` in the response if the deadline was reached.","operationId":"waitForRun","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"timeout","in":"query","schema":{"type":"integer","default":60,"minimum":1,"maximum":120},"description":"Max seconds to wait (default 60, max 120)"}],"responses":{"200":{"description":"Run status (may include timeout: true)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ExecutionResponse"},"timeout":{"type":"boolean"}},"required":["data"]}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/feedback":{"post":{"summary":"Refine run with feedback","description":"Iterative refinement: provide natural-language feedback on a completed run. An LLM identifies which workflow nodes need prompt changes, re-executes them, and returns updated outputs. Only works on completed runs.","operationId":"refineRun","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The run ID to refine."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"feedback":{"type":"string","description":"Natural-language feedback describing what to change."}},"required":["feedback"]}}}},"responses":{"200":{"description":"Refinement result with updated outputs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"runId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["completed","failed"]},"summary":{"type":"string","description":"LLM-generated description of changes"},"refinedNodes":{"type":"array","items":{"type":"object","properties":{"nodeId":{"type":"string"},"reason":{"type":"string"}}}},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/Output"}},"errorMessage":{"type":"string","nullable":true}}}}}}}},"400":{"description":"Run is not in completed state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/brand-compliance":{"get":{"summary":"Get run brand compliance","description":"Read the Brand Guard result for a run's workflow — the per-node compliance status and score against the workspace brand. Returns { enabled: false } when Brand Guard is off for the workflow.","operationId":"getRunBrandCompliance","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Brand compliance result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean"},"brandProfileId":{"type":"string","nullable":true},"nodes":{"type":"array","items":{"type":"object","properties":{"nodeId":{"type":"string"},"status":{"type":"string"},"overallScore":{"type":"number"},"brandDeviations":{"type":"array","items":{"type":"string"}},"checkedAt":{"type":"string","nullable":true}}}}},"required":["enabled","nodes"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/brand-feedback":{"post":{"summary":"Give brand feedback on a run","description":"Close the loop: an on/off-brand verdict on a run's output. A `reject` with a `note` becomes a brand guardrail, so the next generation and `applyBrand` run avoid it. `approve` is acknowledged without mutating the brand. Requires an owner/admin API key.","operationId":"runBrandFeedback","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"verdict":{"type":"string","enum":["approve","reject"]},"note":{"type":"string","description":"Why it is off-brand — becomes a guardrail when verdict is reject."},"brandProfileId":{"type":"string","description":"Target brand. Defaults to the run's workflow brand."}},"required":["verdict"]}}}},"responses":{"200":{"description":"Feedback recorded","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"runId":{"type":"string"},"brandProfileId":{"type":"string"},"verdict":{"type":"string","enum":["approve","reject"]},"applied":{"type":"boolean"},"guardrails":{"type":"array","items":{"type":"string"}}},"required":["brandProfileId","verdict","applied","guardrails"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/brand-score":{"post":{"summary":"Score a run against a brand","description":"On-demand brand-fit score for a completed run's image output, with the specific deviations. Unlike GET /runs/{runId}/brand-compliance (which reads the score Brand Guard stored during the run, only when it was enabled), this scores any completed run on request — the check to run in a generate → score → refine loop. Defaults to the run's app brand; pass brandProfileId to score against a different one.","operationId":"runBrandScore","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"brandProfileId":{"type":"string","description":"Brand to score against. Defaults to the run's workflow brand."}}}}}},"responses":{"200":{"description":"Brand-fit score","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"runId":{"type":"string"},"brandProfileId":{"type":"string"},"brandFit":{"type":"number","nullable":true,"description":"Weighted 0–100 brand-fit score."},"dimensions":{"type":"object","description":"Per-dimension breakdown (e.g. color_match, tone_match).","additionalProperties":{"type":"object","properties":{"score":{"type":"number"},"details":{"type":"string"}}}},"deviations":{"type":"array","items":{"type":"string"}},"suggestions":{"type":"string"},"checkedAt":{"type":"string"}},"required":["runId","brandProfileId","brandFit","deviations"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/runs/{runId}/refine-to-brand":{"post":{"summary":"Refine a run until on-brand, within budget","description":"Bounded generate → score → refine loop. Repeats score → refine (re-rolling with the specific deviations fed back in) on a completed run and stops the instant brandFit >= minScore, iterations >= maxIterations, or the credit budget would be exceeded — whichever first. Returns the best result and exactly how many iterations and credits it took. The credit cap is never exceeded.","operationId":"refineRunToBrand","tags":["Runs"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"minScore":{"type":"number","minimum":0,"maximum":100,"description":"Target brand-fit score to stop at (default 80)."},"maxIterations":{"type":"integer","minimum":1,"maximum":10,"description":"Most refine passes to try (default 3)."},"maxCredits":{"type":"number","minimum":1,"maximum":100000,"description":"Hard credit ceiling — never exceeded (default 200)."},"brandProfileId":{"type":"string","description":"Brand to score against. Defaults to the run's workflow brand."}}}}}},"responses":{"200":{"description":"Refine loop result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"runId":{"type":"string"},"brandProfileId":{"type":"string"},"minScore":{"type":"number"},"maxCredits":{"type":"number"},"iterations":{"type":"integer","description":"Refine passes performed."},"creditsSpent":{"type":"number"},"stoppedBecause":{"type":"string","enum":["met_score","max_iterations","budget","no_output"]},"summary":{"type":"string","description":"Human-readable spend-vs-budget, attempts, and best-score line."},"best":{"type":"object","properties":{"iteration":{"type":"integer"},"brandFit":{"type":"number","nullable":true},"imageUrl":{"type":"string"}}},"attempts":{"type":"array","items":{"type":"object","properties":{"iteration":{"type":"integer"},"brandFit":{"type":"number","nullable":true},"imageUrl":{"type":"string"},"creditsSpent":{"type":"number"},"cumulativeCredits":{"type":"number"},"deviations":{"type":"array","items":{"type":"string"}}}}}},"required":["runId","iterations","creditsSpent","stoppedBecause","best"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/assets":{"get":{"summary":"List generated assets","description":"List generated assets (images, videos, audio) from past runs.","operationId":"listAssets","tags":["Assets"],"parameters":[{"name":"runId","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filter by run"},{"name":"outputType","in":"query","schema":{"type":"string"},"description":"Filter by output type (image, video, audio)"},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Paginated asset list","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AssetRecord"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"description":"Missing or invalid API key"}}}},"/brand/profiles":{"get":{"summary":"List brand profiles","description":"List the workspace's brand profiles with a `hasDna` flag, so you can discover which brandProfileId values exist before targeting one in generation or runs.","operationId":"listBrandProfiles","tags":["Intelligence"],"responses":{"200":{"description":"Brand profiles","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"brandProfileId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"hasDna":{"type":"boolean"},"updatedAt":{"type":"string","nullable":true}},"required":["brandProfileId","name","hasDna"]}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create or update a brand","description":"Create a brand profile (or update one when brandProfileId is given) and ground it with a starter Brand DNA, so generated apps and applyBrand runs produce on-brand output. Requires an owner/admin API key.","operationId":"saveBrandProfile","tags":["Intelligence"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brandName":{"type":"string","description":"Brand to create, or display name on update."},"brandProfileId":{"type":"string","description":"Update this existing profile. Omit to create a new one."},"guardrails":{"type":"array","items":{"type":"string"},"description":"Things to avoid — become the brand's visual negatives."},"brandVoice":{"type":"string"},"visualStyle":{"type":"string"},"targetAudience":{"type":"string"},"description":{"type":"string"},"industry":{"type":"string"}},"required":["brandName"]}}}},"responses":{"200":{"description":"Brand saved","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"brandProfileId":{"type":"string"},"reused":{"type":"boolean"}},"required":["brandProfileId","reused"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brand/profiles/{brandProfileId}/synthesize":{"post":{"summary":"Synthesize Brand DNA","description":"Force an LLM re-synthesis of a brand's DNA from its profile and any accumulated performance data. Requires an owner/admin API key.","operationId":"synthesizeBrandDna","tags":["Intelligence"],"parameters":[{"name":"brandProfileId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Brand DNA synthesized","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"brandProfileId":{"type":"string"},"synthesized":{"type":"boolean"}},"required":["brandProfileId","synthesized"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brand/profiles/{brandProfileId}/kit":{"get":{"summary":"Get a brand kit","description":"Resolve a brand's reusable identity assets — voices, avatars, characters, and motion graphics — registered once and referenced across reels. Returns both the hydrated `resolved` kit (voice ids, reference-image URLs ready for generation) and the raw `elements`.","operationId":"getBrandKit","tags":["Intelligence"],"parameters":[{"name":"brandProfileId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Brand kit","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"resolved":{"type":"object"},"elements":{"type":"array","items":{"$ref":"#/components/schemas/BrandKitElement"}}}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Register a brand kit element","description":"Register (or supersede, by name) a reusable brand asset that points at an existing primitive — a cloned voice, a persona, or an asset. Requires an owner/admin API key.","operationId":"registerBrandKitElement","tags":["Intelligence"],"parameters":[{"name":"brandProfileId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"elementType":{"type":"string","enum":["voice","avatar","character","motion_graphic"]},"name":{"type":"string","description":"Stable reference handle, unique per type."},"refKind":{"type":"string","enum":["cloned_voice","persona","asset"],"nullable":true},"refId":{"type":"string","nullable":true},"spec":{"type":"object","description":"Type-specific detail (tone, presenter image, refs…)."}},"required":["elementType","name"]}}}},"responses":{"200":{"description":"Brand kit element registered","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BrandKitElement"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brand/profiles/{brandProfileId}/kit/from-run":{"post":{"summary":"Save a generated output into the brand kit","description":"Promote a generated output (from a completed run, or a direct outputUrl) into a reusable brand asset. The output is persisted to a durable CDN URL first, then registered. Images → avatar/character, video → motion_graphic. Requires an owner/admin API key.","operationId":"saveOutputToBrandKit","tags":["Intelligence"],"parameters":[{"name":"brandProfileId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"elementType":{"type":"string","enum":["avatar","character","motion_graphic"]},"name":{"type":"string"},"runId":{"type":"string","description":"Resolve the output from this completed run."},"outputUrl":{"type":"string","description":"Or pass the output URL directly."},"mediaType":{"type":"string","enum":["image","video"],"description":"Required with outputUrl."},"spec":{"type":"object"}},"required":["elementType","name"]}}}},"responses":{"200":{"description":"Output saved to brand kit","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BrandKitElement"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/intelligence/brand-context":{"get":{"summary":"Get brand context","description":"Retrieve workspace brand DNA, workflow guidance, and top-performing content patterns. Used to inform content creation.","operationId":"getBrandContext","tags":["Intelligence"],"parameters":[{"name":"brandProfileId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"workflowId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"objective","in":"query","schema":{"type":"string"}},{"name":"marketCode","in":"query","schema":{"type":"string","pattern":"^[A-Za-z]{2}$"}},{"name":"productKey","in":"query","schema":{"type":"string","pattern":"^[0-9a-fA-F]{16}$"}},{"name":"modality","in":"query","schema":{"type":"string","enum":["image","video","text","audio","mixed"]}},{"name":"topK","in":"query","schema":{"type":"integer","default":10}}],"responses":{"200":{"description":"Brand context package","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BrandContext"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/intelligence/predict":{"post":{"summary":"Predict content performance","description":"Predict how a content concept would perform on a given platform.","operationId":"predictPerformance","tags":["Intelligence"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"concept":{"type":"string","description":"Content concept or brief"},"platform":{"type":"string","description":"Target platform (instagram, tiktok, etc.)"},"modality":{"type":"string","enum":["image","video","text","audio","mixed"]},"brandProfileId":{"type":"string","format":"uuid","nullable":true},"campaignId":{"type":"string","format":"uuid","nullable":true}},"required":["concept","platform","modality"]}}}},"responses":{"200":{"description":"Performance prediction","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/intelligence/recommendations":{"get":{"summary":"Get content recommendations","description":"List open content recommendations for the workspace.","operationId":"getRecommendations","tags":["Intelligence"],"parameters":[{"name":"campaignId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"workflowId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"brandProfileId","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"objective","in":"query","schema":{"type":"string"}},{"name":"modality","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"Content recommendations","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Recommendation"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/intelligence/trends":{"get":{"summary":"Get trend signals","description":"Aggregate trending content signals for the workspace.","operationId":"getTrends","tags":["Intelligence"],"parameters":[{"name":"category","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}},{"name":"windowDays","in":"query","schema":{"type":"integer","default":7}},{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Trend signal aggregation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/publishing/channels":{"get":{"summary":"List connected channels","description":"List social accounts connected to the workspace.","operationId":"listChannels","tags":["Publishing"],"responses":{"200":{"description":"Connected channels","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Channel"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/publishing/publish":{"post":{"summary":"Publish content","description":"Publish content (image, video, or caption) to one or more connected social accounts.","operationId":"publishContent","tags":["Publishing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Channel IDs to publish to"},"imageUrl":{"type":"string","format":"uri","nullable":true},"videoUrl":{"type":"string","format":"uri","nullable":true},"caption":{"type":"string","nullable":true}},"required":["accountIds"]}}}},"responses":{"200":{"description":"Publish result","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/publishing/transfer-asset":{"post":{"summary":"Transfer asset to CDN","description":"Transfer an asset from an external URL to the Lamina CDN for reliable access.","operationId":"transferAsset","tags":["Publishing"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sourceUrl":{"type":"string","format":"uri"},"mediaType":{"type":"string","enum":["image","video","audio"]},"filename":{"type":"string"}},"required":["sourceUrl","mediaType"]}}}},"responses":{"200":{"description":"CDN URL","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string"}}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/publishing/history":{"get":{"summary":"Get publish history","description":"List past publish operations.","operationId":"getPublishHistory","tags":["Publishing"],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Publish history","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublishHistoryItem"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/create":{"post":{"summary":"Create content (short alias)","description":"Alias for /content/create. Freezes the same high-level AgentPlan used by the browser and MCP. Interactive calls return the plan for review; explicitly headless calls may execute with an idempotency key and hard credit ceiling.","operationId":"create","tags":["Content"],"requestBody":{"$ref":"#/paths/~1content~1create/post/requestBody"},"responses":{"$ref":"#/paths/~1content~1create/post/responses"}}},"/content/create":{"post":{"summary":"Create content","description":"Compatibility high-level endpoint over the frozen AgentPlan lifecycle. Interactive calls return questions, route choices, or an approval-ready plan without spending generation credits. Set headless=true only with an Idempotency-Key header and positive maxCredits to execute an approval-ready plan.","operationId":"createContent","tags":["Content"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brief":{"type":"string","description":"What content to create"},"platform":{"type":"string","nullable":true,"description":"Target platform"},"modality":{"type":"string","enum":["image","video","audio"],"nullable":true,"description":"Content modality (image, video, or audio)"},"brandProfileId":{"type":"string","format":"uuid","nullable":true},"campaignId":{"type":"string","format":"uuid","nullable":true},"appId":{"type":"string","format":"uuid","nullable":true,"description":"Force a specific app"},"scenarioId":{"type":"string","maxLength":64,"nullable":true,"description":"Pin a known creative scenario for deterministic planning."},"feedback":{"type":"string","maxLength":2000,"nullable":true,"description":"Free-text feedback to fold into a revised plan."},"preferredPath":{"type":"string","enum":["auto","atomic","compose","app"],"nullable":true,"description":"Optional route-family preference; the planner still freezes the route."},"maxEstimatedCredits":{"type":"integer","minimum":1,"nullable":true,"description":"Planning constraint; do not return a plan estimated above this amount."},"headless":{"type":"boolean","nullable":true,"default":false,"description":"Unattended mode. The server still freezes a plan first and dispatches only when it is awaiting approval, within maxCredits, and protected by Idempotency-Key. Questions and route choices are returned without dispatch."},"maxCredits":{"type":"integer","minimum":1,"description":"Required hard credit ceiling for headless execution."},"allowUnknownCost":{"type":"boolean","default":false,"description":"Explicitly permit an unknown-cost plan while retaining maxCredits as the hard ceiling."},"inputs":{"type":"object","nullable":true,"description":"Override inputs for the selected app"},"templateId":{"type":"string","nullable":true,"description":"Apply a content template"},"autoQuality":{"type":"object","nullable":true,"description":"Auto-quality guarantee: score output after completion and retry if below threshold. Credits refunded if quality cannot be met.","properties":{"enabled":{"type":"boolean","default":true,"description":"Enable auto-quality (default true when object is present)"},"minScore":{"type":"number","default":70,"minimum":0,"maximum":100,"description":"Minimum quality score (0-100)"},"maxRetries":{"type":"integer","default":1,"minimum":0,"maximum":3,"description":"Max retry attempts (capped at 3)"}}},"aspectRatio":{"type":"string","nullable":true,"description":"Output aspect ratio (e.g. 1:1, 16:9, 9:16, 4:3, 4:5, auto). Auto-mapped to the matching workflow parameter."},"metadata":{"type":"object","nullable":true,"description":"Deprecated compatibility metadata. Put planner-known values under inputs; metadata.webhookUrl returns a warning and is not attached to pipeline runs."},"webhookUrl":{"type":"string","format":"uri","nullable":true,"description":"Deprecated compatibility field. Canonical pipeline runs do not attach this callback; poll GET /content/runs/{runId}. A warning is returned when supplied."}},"required":["brief"]}}}},"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Required when headless=true or terminalMode=auto."}],"responses":{"200":{"description":"Frozen plan or started pipeline run","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/plan":{"post":{"summary":"Freeze a creative execution plan","description":"Runs the canonical Director planner without dispatching generation. The compatibility envelope includes the exact immutable plan under `data.plan`, plus planId, planFingerprint, canonicalStatus, questions, route alternatives, credit/time estimates, and legacy app fields where derivable.","operationId":"planContent","tags":["Content"],"requestBody":{"$ref":"#/paths/~1content~1create/post/requestBody"},"responses":{"200":{"description":"Frozen AgentPlan","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/plans/{planId}/choose":{"post":{"summary":"Choose and freeze a plan route","operationId":"chooseContentPlanRoute","tags":["Content"],"parameters":[{"name":"planId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["routeId"],"properties":{"routeId":{"type":"string"}}}}}},"responses":{"200":{"description":"Re-frozen AgentPlan","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/plans/{planId}/execute":{"post":{"summary":"Execute an approved frozen plan","operationId":"executeContentPlan","tags":["Content"],"parameters":[{"name":"planId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["planFingerprint","maxCredits"],"properties":{"planFingerprint":{"type":"string"},"inputs":{"type":"object"},"maxCredits":{"type":"integer","minimum":1},"allowUnknownCost":{"type":"boolean","default":false}}}}}},"responses":{"202":{"description":"Pipeline run queued","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/runs/{runId}":{"get":{"summary":"Get canonical pipeline run status","operationId":"getContentPipelineRun","tags":["Content"],"parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pipeline run snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/score":{"post":{"summary":"Score content","description":"Evaluate workspace content across multiple quality dimensions.","operationId":"scoreContent","tags":["Content"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"contentItemIds":{"type":"array","items":{"type":"string","format":"uuid"},"nullable":true},"platform":{"type":"string","nullable":true},"modality":{"type":"string","nullable":true},"limit":{"type":"integer","default":25}}}}}},"responses":{"200":{"description":"Content scores","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/brief":{"post":{"summary":"Generate content brief","description":"Generate content briefs based on a goal, enriched with brand context and trend signals.","operationId":"createBrief","tags":["Content"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"goal":{"type":"string","description":"What you want to achieve"},"platform":{"type":"string","nullable":true},"modality":{"type":"string","nullable":true},"count":{"type":"integer","default":3,"maximum":10},"brandProfileId":{"type":"string","format":"uuid","nullable":true}},"required":["goal"]}}}},"responses":{"200":{"description":"Generated content briefs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/content/batch":{"post":{"summary":"Batch content creation","description":"Create multiple content pieces in a single request. Brand context is resolved once and shared across all items.","operationId":"batchCreate","tags":["Content"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/BatchCreateItem"},"minItems":1,"maxItems":10},"brandProfileId":{"type":"string","format":"uuid","nullable":true},"campaignId":{"type":"string","format":"uuid","nullable":true}},"required":["items"]}}}},"responses":{"202":{"description":"Batch creation started","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"batchId":{"type":"string","format":"uuid"},"total":{"type":"integer"},"queued":{"type":"integer"},"failed":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/BatchResultItem"}}},"required":["batchId","total","items"]}},"required":["data"]}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/billing/packages":{"get":{"summary":"List credit packages","description":"List the active credit packages a caller can buy. Pair with POST /billing/checkout to start a purchase. Balance is on GET /account/usage.","operationId":"listCreditPackages","tags":["Account"],"responses":{"200":{"description":"Credit packages","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"packageId":{"type":"string"},"name":{"type":"string"},"credits":{"type":"integer","description":"Total credits granted (base + bonus)."},"priceCents":{"type":"integer"},"currency":{"type":"string"},"description":{"type":"string","nullable":true}},"required":["packageId","name","credits","priceCents","currency"]}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/billing/checkout":{"post":{"summary":"Start a credit top-up","description":"Start a one-time credit purchase and get back a Stripe-hosted Checkout URL to hand to the user. No card details are handled by the API — payment happens on Stripe's page, and the workspace is credited on completion. Lets an agent recover from 'insufficient credits' without a dashboard detour.","operationId":"startCreditCheckout","tags":["Account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"packageId":{"type":"string","description":"From GET /billing/packages."}},"required":["packageId"]}}}},"responses":{"200":{"description":"Checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"checkoutUrl":{"type":"string","description":"Stripe-hosted Checkout URL for the user."},"sessionId":{"type":"string"},"credits":{"type":"integer"},"amountCents":{"type":"integer"},"currency":{"type":"string"}},"required":["checkoutUrl","credits"]}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/account/usage":{"get":{"summary":"Get credit balance and usage","description":"Check remaining credits and rate limit status for the workspace.","operationId":"getUsage","tags":["Account"],"responses":{"200":{"description":"Credit balance and rate limits","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/UsageResponse"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates":{"get":{"summary":"List content templates","description":"List available content templates (built-in and custom).","operationId":"listTemplates","tags":["Templates"],"parameters":[{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter by category"}],"responses":{"200":{"description":"Available templates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContentTemplate"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates/{id}":{"get":{"summary":"Get template details","description":"Get full template details including guidance data and multi-asset composition.","operationId":"getTemplate","tags":["Templates"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ContentTemplateDetail"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/signing-key":{"get":{"summary":"Get webhook signing public key","description":"JWKS endpoint for verifying webhook callback signatures. No authentication required.","operationId":"getWebhookSigningKey","tags":["Webhooks"],"security":[],"responses":{"200":{"description":"JWKS key set","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array"}}}}}}}}}}}