{"openapi":"3.0.3","info":{"title":"EzUGC Public API","version":"1.0.0","description":"Programmatic access to EzUGC for generating UGC-style video ads, any-model\nvideo generation, subtitle rendering, brand ingestion, and the agent workflow.\n\n## Authentication\nEvery endpoint requires an EzUGC API key. Send it as either:\n- `Authorization: Bearer ezk_live_...` (bearerAuth), or\n- `x-api-key: ezk_live_...` (apiKeyAuth).\n\nAPI keys are prefixed `ezk_live_` and are issued **only** to accounts with an\nactive paid subscription, exclusively through the EzUGC dashboard. There is no\nendpoint that issues a key without authentication. Without a valid key, no\nfunctional or data endpoint is reachable.\n\n## Scopes\nEach key carries scopes that gate access per operation: `ugc:write`,\n`video:write`, `image:write`, `jobs:read`, `account:read`, `account:write`,\n`agent:read`, `agent:write`, `agent:approve`, `brand:read`, `brand:write`,\n`skills:read`, `skills:write`. The required scope is noted in each operation\ndescription.\n\n## Headers\nClients may send `X-EzUGC-Agent-Channel: cli|mcp` to identify the integration\nchannel.\n\n## Jobs\nGeneration endpoints are asynchronous by default and return `202` with a job\nrecord (poll `GET /api/public/jobs/{jobId}`). Pass `sync: true` (with optional\n`waitTimeoutMs`) to wait for completion inline; completed jobs expose the result\nin `result_payload` (e.g. `result_payload.videoUrl`).","contact":{"name":"EzUGC Support","email":"support@ezugc.ai","url":"https://www.ezugc.ai"}},"servers":[{"url":"https://api.ezugc.ai","description":"EzUGC production API"}],"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"tags":[{"name":"Account","description":"Account, usage and scope information."},{"name":"Jobs","description":"Asynchronous generation job status."},{"name":"UGC","description":"Full UGC ad generation."},{"name":"Video","description":"Any-model video generation and discovery."},{"name":"Image","description":"Static image-ad generation and discovery."},{"name":"Subtitle","description":"Subtitle / caption rendering."},{"name":"Brand","description":"Saved brand workspaces and ingestion."},{"name":"Agent","description":"Conversational agent threads and runs."},{"name":"Skills","description":"Agent capability catalog and saved user skills."},{"name":"Keys","description":"API key management."}],"paths":{"/api/public/me":{"get":{"tags":["Account"],"summary":"Get account identity and scopes","description":"Returns the authenticated account id, key prefix, granted scopes and subscription/payment status. Scope: `account:read`.","operationId":"getMe","responses":{"200":{"description":"Account identity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/usage":{"get":{"tags":["Account"],"summary":"Get video usage and limits","description":"Returns current billing-cycle video usage, plan limit, remaining quota and subscription status. Scope: `account:read`.","operationId":"getUsage","responses":{"200":{"description":"Usage and subscription summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/jobs":{"get":{"tags":["Jobs"],"summary":"List recent jobs","description":"Lists the most recent jobs for the account. Scope: `jobs:read`.","operationId":"listJobs","parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum number of jobs to return.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"A list of jobs.","content":{"application/json":{"schema":{"type":"object","properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/Job"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/jobs/{jobId}":{"get":{"tags":["Jobs"],"summary":"Get a job by id","description":"Returns the status of a single job. When completed, `result_payload.videoUrl` contains the output video. Scope: `jobs:read`.","operationId":"getJob","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The job record.","content":{"application/json":{"schema":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/Job"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/public/ugc/jobs":{"post":{"tags":["UGC"],"summary":"Create a full UGC ad job","description":"Generates a complete UGC-style video ad (script, actor, voice, video). Scope: `ugc:write`.","operationId":"createUgcJob","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UgcJobCreate"}}}},"responses":{"200":{"$ref":"#/components/responses/JobCompleted"},"202":{"$ref":"#/components/responses/JobAccepted"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/video/models":{"get":{"tags":["Video"],"summary":"List available video models","description":"Returns the catalog of video models available to the public API (an array of model objects with id, name, capabilities and supported durations) plus the default model id. Scope: `account:read`.","operationId":"listVideoModels","responses":{"200":{"description":"Available video models.","content":{"application/json":{"schema":{"type":"object","properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/VideoModel"}},"defaultModel":{"type":"string","description":"Id of the model used when a request omits `model`."}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/video/jobs":{"post":{"tags":["Video"],"summary":"Create an any-model video job","description":"Generates a video with any supported catalog model. At least one of `prompt`, `imageUrls` or `frameImages` is required. Scope: `video:write`.","operationId":"createVideoJob","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VideoJobCreate"}}}},"responses":{"200":{"$ref":"#/components/responses/JobCompleted"},"202":{"$ref":"#/components/responses/JobAccepted"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/image-ads/models":{"get":{"tags":["Image"],"summary":"List available image models","description":"Returns the catalog of image-ad models available to the public API (an array of model objects with id, name, capabilities and aspect ratios) plus the default model id. Scope: `account:read`.","operationId":"listImageModels","responses":{"200":{"description":"Available image models.","content":{"application/json":{"schema":{"type":"object","properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/ImageModel"}},"defaultModel":{"type":"string","description":"Id of the model used when a request omits `model`."}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/image-ads/jobs":{"post":{"tags":["Image"],"summary":"Create a static image-ad job","description":"Generates 1-4 static image ads with premium AI image models. Pass `referenceImageUrls` to ground the output on real product/brand assets. Charges `staticAdGenerations` usage (one per image). Scope: `image:write`.","operationId":"createImageAdJob","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageAdJobCreate"}}}},"responses":{"200":{"$ref":"#/components/responses/JobCompleted"},"202":{"$ref":"#/components/responses/JobAccepted"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/subtitle/jobs":{"post":{"tags":["Subtitle"],"summary":"Create a subtitle render job","description":"Renders subtitles onto a video. Provide either `sourceJobId` (a prior video job) or `videoUrl` (+ optional `script`). Scope: `ugc:write`.","operationId":"createSubtitleJob","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubtitleJobCreate"}}}},"responses":{"200":{"$ref":"#/components/responses/JobCompleted"},"202":{"$ref":"#/components/responses/JobAccepted"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/brands":{"get":{"tags":["Brand"],"summary":"List saved brands","description":"Lists the account's saved brand workspaces. Scope: `brand:read`.","operationId":"listBrands","responses":{"200":{"description":"Saved brands.","content":{"application/json":{"schema":{"type":"object","properties":{"brands":{"type":"array","items":{"$ref":"#/components/schemas/Brand"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Brand"],"summary":"Ingest a brand from a website","description":"Starts brand DNA ingestion from a website URL. Scope: `brand:write`.","operationId":"createBrand","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["websiteUrl"],"properties":{"websiteUrl":{"type":"string","format":"uri","example":"https://example.com"}}}}}},"responses":{"202":{"description":"Brand ingestion started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Brand"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/brands/{brandId}":{"get":{"tags":["Brand"],"summary":"Get brand status and profile","description":"Returns the ingestion status and resolved brand profile. Scope: `brand:read`.","operationId":"getBrand","parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Brand status and profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Brand"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Brand"],"summary":"Update a saved brand's profile","description":"Updates editable brand identity fields. Supports `brandMd` (the brand's Markdown brand book / brand DNA) and `toneOfVoice`. Editing `brandMd` bumps its version. Asset URLs and extraction internals are not editable here. Scope: `brand:write`.","operationId":"updateBrand","parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandUpdate"}}}},"responses":{"200":{"description":"Updated brand and profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Brand"}}}},"400":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/public/brands/{brandId}/assets":{"get":{"tags":["Brand"],"summary":"List a brand's assets","description":"Returns the brand's uploaded assets and previously generated brand creatives, each with a temporary signed URL. Use these URLs as reference images for on-brand image/video generation. Scope: `brand:read`.","operationId":"listBrandAssets","parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Brand assets.","content":{"application/json":{"schema":{"type":"object","properties":{"assets":{"type":"array","items":{"$ref":"#/components/schemas/BrandAsset"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/public/agent/threads":{"post":{"tags":["Agent"],"summary":"Create an agent thread","description":"Starts a new conversational agent thread, optionally with an initial message. Scope: `agent:write`.","operationId":"createAgentThread","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"message":{"type":"string"},"clientMessageId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Thread created.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/agent/threads/{threadId}/messages":{"post":{"tags":["Agent"],"summary":"Post a message to a thread","description":"Sends a user message to an existing thread and starts an agent run. Scope: `agent:write`.","operationId":"createAgentMessage","parameters":[{"name":"threadId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"text":{"type":"string"},"clientMessageId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"202":{"description":"Message accepted; agent run started.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/agent/threads/{threadId}":{"get":{"tags":["Agent"],"summary":"Get a thread","description":"Returns the thread with its messages and current run state. Scope: `agent:read`.","operationId":"getAgentThread","parameters":[{"name":"threadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Thread state.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/public/agent/runs/{runId}/events":{"get":{"tags":["Agent"],"summary":"Stream agent run events","description":"Streams events (SSE) for an agent run. Scope: `agent:read`.","operationId":"getAgentRunEvents","parameters":[{"name":"runId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"An event stream of run progress.","content":{"text/event-stream":{}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/agent/pending-inputs/{pendingInputId}/reply":{"post":{"tags":["Agent"],"summary":"Reply to a pending agent input","description":"Approves, rejects or supplies input the agent is waiting on (human-in-the-loop). Scope: `agent:approve`.","operationId":"replyAgentPendingInput","parameters":[{"name":"pendingInputId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"response":{},"skipped":{"type":"boolean"},"uploadedFiles":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"name":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"Reply accepted.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/agent/skills":{"get":{"tags":["Skills"],"summary":"List agent capability catalog","description":"Returns the read-only catalog of agent tool capabilities (name, description, JSON-Schema parameters) the conversational agent can use. Scope: `agent:read`.","operationId":"listAgentSkills","responses":{"200":{"description":"Agent capability catalog.","content":{"application/json":{"schema":{"type":"object","properties":{"skills":{"type":"array","items":{"$ref":"#/components/schemas/AgentSkill"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/skills":{"get":{"tags":["Skills"],"summary":"List saved skills","description":"Lists the account's saved skills (reusable parameterized prompt templates). Scope: `skills:read`.","operationId":"listSkills","responses":{"200":{"description":"Saved skills.","content":{"application/json":{"schema":{"type":"object","properties":{"skills":{"type":"array","items":{"$ref":"#/components/schemas/UserSkill"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Skills"],"summary":"Create a saved skill","description":"Creates a reusable saved skill (a parameterized prompt template with default params). Scope: `skills:write`.","operationId":"createSkill","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSkillCreate"}}}},"responses":{"201":{"description":"Skill created.","content":{"application/json":{"schema":{"type":"object","properties":{"skill":{"$ref":"#/components/schemas/UserSkill"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/skills/{skillId}":{"get":{"tags":["Skills"],"summary":"Get a saved skill","description":"Returns a single saved skill. Scope: `skills:read`.","operationId":"getSkill","parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The saved skill.","content":{"application/json":{"schema":{"type":"object","properties":{"skill":{"$ref":"#/components/schemas/UserSkill"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Skills"],"summary":"Update a saved skill","description":"Updates a saved skill. Scope: `skills:write`.","operationId":"updateSkill","parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSkillUpdate"}}}},"responses":{"200":{"description":"Skill updated.","content":{"application/json":{"schema":{"type":"object","properties":{"skill":{"$ref":"#/components/schemas/UserSkill"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Skills"],"summary":"Delete a saved skill","description":"Deletes a saved skill. Scope: `skills:write`.","operationId":"deleteSkill","parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Skill deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/public/skills/{skillId}/run":{"post":{"tags":["Skills"],"summary":"Run a saved skill","description":"Renders the skill's prompt template with `variables`, merges `default_params` with `overrides`, and dispatches a generation job of the skill's kind (`video`/`ugc`/`image`). `agent`-kind skills are not runnable here. Charges `videos` usage for video/ugc skills and `staticAdGenerations` for image skills. Scope: `skills:write`.","operationId":"runSkill","parameters":[{"name":"skillId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSkillRun"}}}},"responses":{"200":{"$ref":"#/components/responses/JobCompleted"},"202":{"$ref":"#/components/responses/JobAccepted"},"400":{"$ref":"#/components/responses/NotFound"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/public/keys":{"get":{"tags":["Keys"],"summary":"List API keys","description":"Lists the account's API keys (metadata only; never the secret). Scope: `account:read`.","operationId":"listKeys","responses":{"200":{"description":"API key records.","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Keys"],"summary":"Create an API key","description":"Creates a new API key. The plaintext secret is returned once. Scope: `account:write`.","operationId":"createKey","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"expiresAt":{"type":"string","format":"date-time","nullable":true}}}}}},"responses":{"201":{"description":"Key created (secret shown once).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/public/keys/{keyId}/revoke":{"post":{"tags":["Keys"],"summary":"Revoke an API key","description":"Revokes an API key by id. Scope: `account:write`.","operationId":"revokeKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Key revoked.","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"$ref":"#/components/schemas/ApiKey"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"EzUGC API key sent as `Authorization: Bearer ezk_live_...`. Issued only to paid subscribers via the dashboard."},"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"EzUGC API key sent in the `x-api-key` header (prefix `ezk_live_`). Issued only to paid subscribers via the dashboard."}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"JobAccepted":{"description":"Job queued (asynchronous).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJobResponse"}}}},"JobCompleted":{"description":"Job completed inline (when `sync: true`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateJobResponse"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}}},"Scope":{"type":"string","enum":["ugc:write","video:write","image:write","jobs:read","account:read","account:write","agent:read","agent:write","agent:approve","brand:read","brand:write","skills:read","skills:write"]},"MeResponse":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"keyPrefix":{"type":"string","example":"ezk_live_abcd"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"subscriptionStatus":{"type":"string","nullable":true},"paymentStatus":{"type":"string","nullable":true}}},"UsageResponse":{"type":"object","properties":{"subscription":{"type":"object","properties":{"status":{"type":"string","nullable":true},"paymentStatus":{"type":"string","nullable":true},"billingCycleStart":{"type":"string","nullable":true},"billingCycleEnd":{"type":"string","nullable":true}}},"usage":{"type":"object","properties":{"videos":{"type":"integer"},"limit":{"type":"integer"},"remaining":{"type":"integer"}}}}},"Job":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["ugc","subtitle","video","image"]},"status":{"type":"string","enum":["queued","running","completed","failed","cancelled"]},"progress":{"type":"number","minimum":0,"maximum":100},"step":{"type":"string","nullable":true},"result_payload":{"type":"object","nullable":true,"additionalProperties":true,"properties":{"videoUrl":{"type":"string","format":"uri"}}},"error_payload":{"type":"object","nullable":true,"additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"CreateJobResponse":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/Job"},"result":{"type":"object","nullable":true,"additionalProperties":true}}},"BrandReference":{"type":"object","description":"Optional reference to a saved brand workspace. When `useDefaultBrand` is true and no id/slug is given, the most recently ready brand is used.","properties":{"brandId":{"type":"string"},"brandSlug":{"type":"string"},"useDefaultBrand":{"type":"boolean"}}},"UgcJobCreate":{"allOf":[{"$ref":"#/components/schemas/BrandReference"},{"type":"object","required":["prompt"],"properties":{"prompt":{"type":"string","maxLength":2000},"script":{"type":"string","maxLength":3000},"productImageUrls":{"type":"array","maxItems":6,"items":{"type":"string","format":"uri"},"description":"HTTPS image URLs of the product."},"platform":{"type":"string"},"duration":{"type":"number","minimum":5,"maximum":120,"description":"Target duration in seconds."},"aspectRatio":{"type":"string","enum":["9:16","16:9","1:1"]},"voiceId":{"type":"string"},"sync":{"type":"boolean","description":"Wait for completion inline."},"waitTimeoutMs":{"type":"integer","description":"Max inline wait when sync (ms)."}}}]},"VideoFrameImage":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"frame":{"description":"\"first\" | \"last\" | frame index. Defaults to \"first\".","oneOf":[{"type":"string"},{"type":"integer"}]}}},"VideoJobCreate":{"allOf":[{"$ref":"#/components/schemas/BrandReference"},{"type":"object","description":"At least one of `prompt`, `imageUrls` or `frameImages` is required.","properties":{"prompt":{"type":"string","maxLength":2000},"model":{"type":"string","description":"Model identifier. Call the authenticated GET /api/public/video/models for the list of available models and ids. Omit to use the default model.","example":"<model-id>"},"imageUrls":{"type":"array","maxItems":6,"items":{"type":"string","format":"uri"},"description":"HTTPS image URLs for image-to-video."},"frameImages":{"type":"array","items":{"$ref":"#/components/schemas/VideoFrameImage"}},"duration":{"type":"number","minimum":1,"maximum":120,"description":"Target duration in seconds."},"aspectRatio":{"type":"string","enum":["9:16","16:9","1:1"]},"resolution":{"type":"string","example":"1280x720","description":"Explicit WxH resolution, e.g. `1280x720`."},"generateAudio":{"type":"boolean"},"negativePrompt":{"type":"string"},"sync":{"type":"boolean"},"waitTimeoutMs":{"type":"integer"}}}]},"SubtitleJobCreate":{"type":"object","description":"Provide either `sourceJobId` or `videoUrl` (with optional `script`).","properties":{"sourceJobId":{"type":"string","format":"uuid","description":"Id of a prior completed video job."},"videoUrl":{"type":"string","format":"uri","description":"HTTPS URL of the video to subtitle."},"script":{"type":"string","maxLength":3000,"description":"Optional transcript override."},"preset":{"type":"string","enum":["classic_subtitle","tiktok_bold","karaoke","minimal"]},"sync":{"type":"boolean"},"waitTimeoutMs":{"type":"integer"}}},"VideoModel":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"provider":{"type":"string"},"t2v":{"type":"boolean"},"i2v":{"type":"boolean"},"audio":{"type":"boolean"},"durations":{"type":"array","items":{"type":"number"}},"publicApiSupported":{"type":"boolean"},"note":{"type":"string"}}},"ImageModel":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"provider":{"type":"string"},"capabilities":{"type":"object","properties":{"references":{"type":"boolean"},"maxReferences":{"type":"integer"}}},"aspectRatios":{"type":"array","items":{"type":"string"}},"available":{"type":"boolean"},"note":{"type":"string","nullable":true}}},"ImageAdJobCreate":{"allOf":[{"$ref":"#/components/schemas/BrandReference"},{"type":"object","required":["prompt"],"properties":{"prompt":{"type":"string","maxLength":2000},"model":{"type":"string","description":"Model identifier. Call the authenticated GET /api/public/image-ads/models for the list of available models and ids. Omit to use the default model.","example":"<model-id>"},"referenceImageUrls":{"type":"array","maxItems":6,"items":{"type":"string","format":"uri"},"description":"HTTPS reference image URLs (product, logo, prior creatives). First = primary."},"aspectRatio":{"type":"string","enum":["9:16","16:9","1:1","4:5","3:4","2:3"]},"count":{"type":"integer","minimum":1,"maximum":4,"default":1,"description":"Number of images to generate (charges one staticAdGeneration each)."},"enhancePrompt":{"type":"boolean","description":"Run brand-aware prompt enhancement (only when a brand is referenced)."},"sync":{"type":"boolean"},"waitTimeoutMs":{"type":"integer"}}}]},"AgentSkill":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"parameters":{"type":"object","additionalProperties":true,"description":"JSON Schema for the tool's parameters."}}},"UserSkill":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"kind":{"type":"string","enum":["video","ugc","image","agent"]},"prompt_template":{"type":"string"},"default_params":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"UserSkillCreate":{"type":"object","required":["name","kind","promptTemplate"],"properties":{"name":{"type":"string","maxLength":120},"slug":{"type":"string","maxLength":80},"description":{"type":"string","maxLength":600},"kind":{"type":"string","enum":["video","ugc","image","agent"]},"promptTemplate":{"type":"string","maxLength":6000,"description":"Prompt template with `{{variable}}` tokens."},"defaultParams":{"type":"object","additionalProperties":true,"description":"Default request params merged at run time (e.g. model, aspectRatio, count, brandId)."}}},"UserSkillUpdate":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"slug":{"type":"string","maxLength":80},"description":{"type":"string","nullable":true,"maxLength":600},"kind":{"type":"string","enum":["video","ugc","image","agent"]},"promptTemplate":{"type":"string","maxLength":6000},"defaultParams":{"type":"object","additionalProperties":true}}},"UserSkillRun":{"type":"object","properties":{"variables":{"type":"object","additionalProperties":{"type":"string"},"description":"Values for `{{variable}}` tokens in the prompt template."},"overrides":{"type":"object","additionalProperties":true,"description":"Per-run overrides merged over the skill's default_params."},"sync":{"type":"boolean"},"waitTimeoutMs":{"type":"integer"}}},"Brand":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"websiteUrl":{"type":"string","format":"uri"},"status":{"type":"string"},"profile":{"type":"object","nullable":true,"additionalProperties":true},"created_at":{"type":"string","format":"date-time"}}},"BrandUpdate":{"type":"object","description":"Editable brand identity fields. Provide at least one. Only `brandMd` and `toneOfVoice` are editable; asset URLs and extraction internals are managed by ingestion.","properties":{"brandMd":{"type":"string","maxLength":20000,"description":"The brand's Markdown brand book / brand DNA used to ground generations."},"toneOfVoice":{"type":"string","maxLength":2000,"description":"Short description of the brand's tone of voice."}}},"BrandAsset":{"type":"object","properties":{"id":{"type":"string"},"source":{"type":"string","enum":["upload","generated"],"description":"`upload` = user-uploaded brand asset; `generated` = a previously generated brand creative."},"filename":{"type":"string"},"mimeType":{"type":"string","nullable":true},"url":{"type":"string","format":"uri","nullable":true,"description":"Temporary signed URL for the asset."},"prompt":{"type":"string","nullable":true,"description":"Generation prompt (generated assets only)."},"createdAt":{"type":"string","format":"date-time"}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"key_prefix":{"type":"string"},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"revoked_at":{"type":"string","format":"date-time","nullable":true},"expires_at":{"type":"string","format":"date-time","nullable":true},"last_used_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}}}}}