{"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 (payment_status=paid on Startup, Growth, or Pro),\nexclusively through the EzUGC dashboard. There is no endpoint that issues a\nkey without authentication, and there is no free or trial API access.\nIf the account later cancels or lapses, every subsequent call with that key\nreturns 402 PUBLIC_API_SUBSCRIPTION_REQUIRED — leftover keys cannot generate.\nWithout a valid key from a currently-paid account, no functional or data\nendpoint is reachable. `GET /openapi.json` is the only unauthenticated route\nand it documents the API; it performs no generation.\n\n## Versioning\nThis is public API **v1**. Canonical base URL:\n`https://api.ezugc.ai/api/public/v1` (paths in this document are relative to it,\nso `GET /me` is `GET https://api.ezugc.ai/api/public/v1/me`).\nUnversioned `https://api.ezugc.ai/api/public` is an alias of the same v1 contract.\nBreaking changes will ship as `/api/public/v2` with a new `servers` entry and a\n`Deprecation` / `Sunset` header on the old prefix. There is no `/v2` today.\nv1 stays until that header is published.\n\n## Scopes\nEach key stores scopes that are **enforced per operation** (HTTP 403\n`PUBLIC_API_SCOPE_DENIED` when missing). Named scopes live on the `apiKeyScopes`\nsecurity scheme and match RFC 9728 `scopes_supported` on\n`https://api.ezugc.ai/.well-known/oauth-protected-resource`.\nEzUGC authenticates with dashboard API keys, not an OAuth authorization server.\nThe oauth2 scheme exists so OpenAPI can name those labels; do not POST its\n`tokenUrl`. Create a key at https://app.ezugc.ai/dashboard/apps/mcp.\nScopes: `ugc:write`, `video:write`, `image:write`, `jobs:read`, `account:read`,\n`account:write`, `agent:read`, `agent:write`, `agent:approve`, `brand:read`,\n`brand:write`, `skills:read`, `skills:write`.\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 /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`).\n\n## Errors\nEvery failure returns `application/json` with `{ error, code, message, hint }`.\n`error` and `message` carry the same human-readable summary. `code` is stable\nfor programmatic handling. `hint` tells the caller how to fix the request\n(missing key, wrong path, missing scope). 4xx/5xx in this document `$ref`\n`#/components/schemas/Error`. Docs: https://www.ezugc.ai/docs","contact":{"name":"EzUGC Support","email":"support@ezugc.ai","url":"https://www.ezugc.ai/developers"},"termsOfService":"https://www.ezugc.ai/terms","x-documentation":"https://www.ezugc.ai/docs","x-developer-portal":"https://www.ezugc.ai/developers","x-auth-docs":"https://www.ezugc.ai/docs/auth","x-api-version":"1"},"servers":[{"url":"https://api.ezugc.ai/api/public/v1","description":"Public API v1. Paths in this spec are relative to this base (GET /me)."},{"url":"https://api.ezugc.ai/api/public","description":"Unversioned alias of v1. Same contract as /api/public/v1. Not deprecated."}],"security":[{"bearerAuth":[],"apiKeyScopes":[]},{"apiKeyAuth":[],"apiKeyScopes":[]}],"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":{"/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"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:read"]},{"apiKeyAuth":[],"apiKeyScopes":["account:read"]}]}},"/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"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:read"]},{"apiKeyAuth":[],"apiKeyScopes":["account:read"]}]}},"/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"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["jobs:read"]},{"apiKeyAuth":[],"apiKeyScopes":["jobs:read"]}]}},"/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"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["jobs:read"]},{"apiKeyAuth":[],"apiKeyScopes":["jobs:read"]}]}},"/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"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["ugc:write"]},{"apiKeyAuth":[],"apiKeyScopes":["ugc:write"]}]}},"/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`."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:read"]},{"apiKeyAuth":[],"apiKeyScopes":["account:read"]}]}},"/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"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["video:write"]},{"apiKeyAuth":[],"apiKeyScopes":["video:write"]}]}},"/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`."}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:read"]},{"apiKeyAuth":[],"apiKeyScopes":["account:read"]}]}},"/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"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["image:write"]},{"apiKeyAuth":[],"apiKeyScopes":["image:write"]}]}},"/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"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["ugc:write"]},{"apiKeyAuth":[],"apiKeyScopes":["ugc:write"]}]}},"/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"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["brand:read"]},{"apiKeyAuth":[],"apiKeyScopes":["brand:read"]}]},"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"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["brand:write"]},{"apiKeyAuth":[],"apiKeyScopes":["brand:write"]}]}},"/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"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["brand:read"]},{"apiKeyAuth":[],"apiKeyScopes":["brand:read"]}]},"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/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["brand:write"]},{"apiKeyAuth":[],"apiKeyScopes":["brand:write"]}]}},"/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"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["brand:read"]},{"apiKeyAuth":[],"apiKeyScopes":["brand:read"]}]}},"/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}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["agent:write"]},{"apiKeyAuth":[],"apiKeyScopes":["agent:write"]}]}},"/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}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["agent:write"]},{"apiKeyAuth":[],"apiKeyScopes":["agent:write"]}]}},"/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}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["agent:read"]},{"apiKeyAuth":[],"apiKeyScopes":["agent:read"]}]}},"/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":{}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["agent:read"]},{"apiKeyAuth":[],"apiKeyScopes":["agent:read"]}]}},"/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}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["agent:approve"]},{"apiKeyAuth":[],"apiKeyScopes":["agent:approve"]}]}},"/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"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["agent:read"]},{"apiKeyAuth":[],"apiKeyScopes":["agent:read"]}]}},"/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"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["skills:read"]},{"apiKeyAuth":[],"apiKeyScopes":["skills:read"]}]},"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"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["skills:write"]},{"apiKeyAuth":[],"apiKeyScopes":["skills:write"]}]}},"/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"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["skills:read"]},{"apiKeyAuth":[],"apiKeyScopes":["skills:read"]}]},"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"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["skills:write"]},{"apiKeyAuth":[],"apiKeyScopes":["skills:write"]}]},"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"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["skills:write"]},{"apiKeyAuth":[],"apiKeyScopes":["skills:write"]}]}},"/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/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["skills:write"]},{"apiKeyAuth":[],"apiKeyScopes":["skills:write"]}]}},"/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"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:read"]},{"apiKeyAuth":[],"apiKeyScopes":["account:read"]}]},"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}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:write"]},{"apiKeyAuth":[],"apiKeyScopes":["account:write"]}]}},"/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"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[{"bearerAuth":[],"apiKeyScopes":["account:write"]},{"apiKeyAuth":[],"apiKeyScopes":["account:write"]}]}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API-Key","description":"EzUGC API key sent as `Authorization: Bearer ezk_live_...`. Issued only to paid subscribers via the dashboard. Pair with apiKeyScopes for the required capability label."},"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. Pair with apiKeyScopes for the required capability label."},"apiKeyScopes":{"type":"oauth2","description":"Named capability labels stored on each EzUGC API key and enforced per operation (403 PUBLIC_API_SCOPE_DENIED). Authentication is the dashboard API key, not an OAuth authorization server. tokenUrl is the auth walkthrough (HTML), not a token issuer — do not POST it. Aligns with RFC 9728 scopes_supported on https://api.ezugc.ai/.well-known/oauth-protected-resource.","flows":{"clientCredentials":{"tokenUrl":"https://www.ezugc.ai/docs/auth","scopes":{"ugc:write":"Create UGC video jobs and subtitle render jobs.","video:write":"Create any-model video generation jobs.","image:write":"Create static image-ad jobs.","jobs:read":"List and poll generation jobs.","account:read":"Read account identity, usage, model catalogs, and API key metadata.","agent:read":"Read agent threads, run events, and the agent capability catalog.","agent:write":"Create agent threads, post messages, and manage schedules and channels.","agent:approve":"Reply to pending human-in-the-loop agent inputs.","brand:read":"List saved brands and brand assets.","brand:write":"Ingest a brand from a website and update brand DNA.","skills:read":"List and read saved skills.","skills:write":"Create, update, delete, and run saved skills.","account:write":"Create and revoke API keys."}}}}},"responses":{"BadRequest":{"description":"Malformed request body or query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRequired":{"description":"The API key is valid but the account is not on an active paid Startup, Growth, or Pro subscription (HTTP 402 PUBLIC_API_SUBSCRIPTION_REQUIRED).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The API key is missing a required scope (HTTP 403 PUBLIC_API_SCOPE_DENIED).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooManyRequests":{"description":"Rate limit exceeded. Wait for Retry-After, then retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ServerError":{"description":"Unexpected server error.","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","required":["error","code","message","hint"],"properties":{"error":{"type":"string","description":"Human-readable error summary. Same value as `message`."},"code":{"type":"string","description":"Machine-readable error code (for example PUBLIC_API_KEY_REQUIRED, NOT_FOUND)."},"message":{"type":"string","description":"Human-readable error summary for agent parsers that look for `message`."},"hint":{"type":"string","description":"How to resolve the error: missing auth, bad path, or a link to EzUGC API docs."}}},"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"}}}}}}