{"openapi":"3.1.0","info":{"title":"AdGreetz Creative API","version":"1.0.0","description":"# Creative API v1\n\nGenerate production-ready video, static, carousel, and rich-media ads with a conventional JSON REST API. Use polling, or supply a webhook URL for durable terminal callbacks.\n\n## Quickstart\n\n1. Create an API key in **Settings → API Keys** and send it as `Authorization: Bearer agz_live_…`.\n2. Call `POST /api/v1/videos` with the creative options plus **one** brand reference: an existing `brand_id`, or `brand_name` + `website` together. With the website form, an existing brand is reused when its website matches; otherwise the brand is created and scraped automatically.\n3. Video requests auto-render by default. Poll `GET /api/v1/generations/video/{id}` using each status response's `poll_after_seconds` hint (60s for static/carousel/rich media, 300s for video), or supply `webhook_url` on creation.\n4. For video, stop polling on `rendered` — that is the status carrying `video_url` on status and result payloads. Also stop on `completed` (the composition is authored but no MP4 was requested or the render failed — check `error_message`) and on `failed`. Set `auto_render: false` only for an edit-first flow that calls the render endpoint later; such a video settles at `completed` until you do.\n\nAll responses use `{ \"ok\": true, \"data\": ... }` or `{ \"ok\": false, \"error\": { \"code\", \"message\", \"details\"? } }`. Create endpoints return HTTP 202; reads return HTTP 200.\n\n## Operational behavior\n\n- Scopes: `creative:generate` for creates/renders, `creative:read` for generation reads, `brand:read` for brand reads, and `credits:read` for balances.\n- Rate limit: 60 requests per minute per authenticated connection (API key, or OAuth client+user). HTTP 429 includes `Retry-After`.\n- Idempotency: send a unique `Idempotency-Key` header on create requests. The JSON `idempotency_key` field is also accepted; the header wins. Successful responses are replayable for about 24 hours.\n- Credits: create endpoints enforce the live balance. No speculative pre-check is needed; HTTP 402 includes `required_credits` and the live balance in error details.\n- Status lifecycle: `queued → scraping → generating → completed | partial | failed`. Video adds a render leg: `completed → rendering → rendered`, where `completed` means the composition is authored, `rendering` means an MP4 render is genuinely in flight, and `rendered` is the only status that carries `video_url`. `rendering` never appears for image, carousel, or rich-media generations.\n- Video terminal states: `rendered` (MP4 ready), `completed` (authored, no MP4 — either `auto_render: false`, or a render that failed, in which case `error_message` explains it), and `failed` (authoring itself failed). A `completed` video can be moved to `rendered` at any time by calling the render endpoint.\n- Attribution: `external_actor_id` is an opaque identifier for your end user. It is echoed on generation reads and never changes authorization or billing tenancy.\n- Webhooks: all create endpoints accept `webhook_url` and optional `webhook_secret`. Deliveries are retried, signed with HMAC-SHA256 when a secret is supplied, and may arrive more than once; deduplicate on `delivery_id`. Use `occurred_at` to order lifecycle events when delivery retries or delays make arrival order differ from occurrence order.\n- Pagination: list endpoints return an opaque `next_cursor`. Pass it back unchanged; it carries the original filters."},"paths":{"/api/v1/brands":{"get":{"operationId":"list_brands","summary":"List brands","description":"List the brands available to this account (or another team via team_id, from list_teams). Use the returned brand id with get_brand and the create tools. Supports optional name search (query) and cursor pagination. When paginating, pass cursor alone; it carries the original query and team scope. Items carry team_id/team_name for grouping.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string","minLength":1}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/ListBrandsData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/brands/{id}":{"get":{"operationId":"get_brand","summary":"Get a brand","description":"Get bounded context for one brand: name, website, description, colors, logo, and up to 10 products (title + image) sourced from the scraped website. Use it to write smarter creative briefs before calling a create tool.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/BrandData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/credits":{"get":{"operationId":"get_credit_balance","summary":"Get credit balance","description":"Get the current credit balance for the connected account, plus a coarse cost reference per generation type. Call this ONLY when the user explicitly asks about credits/affordability, or to explain an INSUFFICIENT_CREDITS error a create tool returned. Do NOT call it as a routine pre-check before creating: the create tools enforce the credit gate themselves and, on failure, return an INSUFFICIENT_CREDITS error carrying both required_credits and the live balance — a speculative balance check before every generation only adds latency.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/CreditBalanceData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/videos":{"post":{"operationId":"create_video_ad","summary":"Create a video ad","description":"Create an AI video ad generation for a brand (default agent mode; defaults to voiceover and auto-render). Cost scales with length (~6000 credits for ≤15s, ~12000 for 30s). reference_images supplies labeled image context to the video agent. Supply webhook_url for terminal callbacks, or poll get_generation_status. Video has two terminal states: rendered (the MP4 is ready and video_url is present) and completed (the composition is authored but no MP4 exists). Stop polling on either, and on failed. Set auto_render=false only for an edit-first flow that will call render_generation manually; such a video settles at completed — it will NOT progress on its own — and fires the generation.completed callback then, with generation.rendered following only after you render it.","tags":["Generation creation"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key for replay-safe create retries. Overrides body idempotency_key.","schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"Existing brand","description":"Reference a brand you already have by `brand_id` (from `GET /api/v1/brands`). Do not send `brand_name` or `website`.","type":"object","properties":{"brand_id":{"description":"Existing brand id (from list_brands). Mutually exclusive with brand_name/website.","type":"string","minLength":1},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"video_length":{"type":"string","enum":["6","10","15","30"],"description":"Video length in seconds."},"aspect_ratio":{"default":"16:9","type":"string","enum":["16:9","9:16","1:1","3:4","4:5","120:31"]},"video_objective":{"default":"store_traffic","type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"video_style":{"default":"autodetect","description":"Visual style, e.g. 'cinematic', 'photorealistic'; 'autodetect' lets the agent pick.","type":"string"},"video_tone":{"default":"autodetect","description":"Tone, e.g. 'dramatic', 'humorous'; 'autodetect' lets the agent pick.","type":"string"},"language":{"default":"ENG_US","type":"string"},"audio_option":{"default":"voiceover","type":"string","enum":["voiceover","music","dialogue"]},"video_model":{"description":"Video generation model; omit for 'auto'.","type":"string","enum":["auto","seedance-lite","seedance-pro","seedance-1-pro-uncensored","seedance-1-fast-uncensored","seedance-fast","seedance-fast-reference","seedance-mini","seedance-mini-reference","seedance-pro-reference","seedance-pro-reference-1080p","seedance-1.5-pro","runway-gen4-turbo","runway-gen-4.5","veo3-fast","veo3","veo3.1","veo3.1-fast","veo3.1-preview","veo3.1-fast-preview","veo3.1-lite","gemini-omni-flash","kling-v2-1","kling-v2-1-master","kling-v2-5-turbo-pro","kling-v2-6-pro","kling-v3-standard","kling-v3-pro","kling-v3-omni-standard","kling-v3-omni-pro","hailuo-02","hailuo-2.3","hailuo-2.3-fast","pixverse-v5","pixverse-v5-6","pixverse-v6","pixverse-c1-transition","sora-2","sora-2-pro","ltx-2.3-pro","ltx-2.3-fast","ltx-2-pro","ltx-2-distilled","kling-o1","kling-o3-standard","kling-o3-reference","grok-imagine-video","grok-imagine-r2v","grok-imagine-video-1.5","happy-horse","happy-horse-reference","happy-horse-1.1","happy-horse-1.1-reference","wan-2.6-i2v-flash","wan-2.6-i2v","wan-2.7-r2v","p-video"]},"additional_direction":{"description":"Extra creative direction for the video agent.","type":"string","maxLength":2000},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"auto_render":{"default":true,"description":"Render the authored composition to an MP4 automatically.","type":"boolean"},"reference_images":{"description":"Labeled images the video agent can use as creative context.","minItems":1,"maxItems":10,"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":64},"url":{"type":"string","format":"uri"}},"required":["label","url"]}},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_id","video_length"],"additionalProperties":false},{"title":"New or matched brand from website","description":"Send `brand_name` and `website` together. An existing brand with the same website is reused; otherwise the brand is created and scraped automatically. Do not send `brand_id`.","type":"object","properties":{"brand_name":{"description":"Brand name for find-or-create. Requires website.","type":"string","minLength":1},"website":{"description":"Brand website URL. Required with brand_name.","type":"string","format":"uri"},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"video_length":{"type":"string","enum":["6","10","15","30"],"description":"Video length in seconds."},"aspect_ratio":{"default":"16:9","type":"string","enum":["16:9","9:16","1:1","3:4","4:5","120:31"]},"video_objective":{"default":"store_traffic","type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"video_style":{"default":"autodetect","description":"Visual style, e.g. 'cinematic', 'photorealistic'; 'autodetect' lets the agent pick.","type":"string"},"video_tone":{"default":"autodetect","description":"Tone, e.g. 'dramatic', 'humorous'; 'autodetect' lets the agent pick.","type":"string"},"language":{"default":"ENG_US","type":"string"},"audio_option":{"default":"voiceover","type":"string","enum":["voiceover","music","dialogue"]},"video_model":{"description":"Video generation model; omit for 'auto'.","type":"string","enum":["auto","seedance-lite","seedance-pro","seedance-1-pro-uncensored","seedance-1-fast-uncensored","seedance-fast","seedance-fast-reference","seedance-mini","seedance-mini-reference","seedance-pro-reference","seedance-pro-reference-1080p","seedance-1.5-pro","runway-gen4-turbo","runway-gen-4.5","veo3-fast","veo3","veo3.1","veo3.1-fast","veo3.1-preview","veo3.1-fast-preview","veo3.1-lite","gemini-omni-flash","kling-v2-1","kling-v2-1-master","kling-v2-5-turbo-pro","kling-v2-6-pro","kling-v3-standard","kling-v3-pro","kling-v3-omni-standard","kling-v3-omni-pro","hailuo-02","hailuo-2.3","hailuo-2.3-fast","pixverse-v5","pixverse-v5-6","pixverse-v6","pixverse-c1-transition","sora-2","sora-2-pro","ltx-2.3-pro","ltx-2.3-fast","ltx-2-pro","ltx-2-distilled","kling-o1","kling-o3-standard","kling-o3-reference","grok-imagine-video","grok-imagine-r2v","grok-imagine-video-1.5","happy-horse","happy-horse-reference","happy-horse-1.1","happy-horse-1.1-reference","wan-2.6-i2v-flash","wan-2.6-i2v","wan-2.7-r2v","p-video"]},"additional_direction":{"description":"Extra creative direction for the video agent.","type":"string","maxLength":2000},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"auto_render":{"default":true,"description":"Render the authored composition to an MP4 automatically.","type":"boolean"},"reference_images":{"description":"Labeled images the video agent can use as creative context.","minItems":1,"maxItems":10,"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":64},"url":{"type":"string","format":"uri"}},"required":["label","url"]}},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_name","website","video_length"],"additionalProperties":false}]}}}},"responses":{"202":{"description":"Generation queued.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/CreateVideoAdData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/static-ads":{"post":{"operationId":"create_static_ad","summary":"Create a static ad","description":"Create a static ad generation for a brand. Cost: 100 credits per image (quantity × aspect_ratios) plus an LLM base fee. Returns immediately with a generation ref. Supply webhook_url for terminal callbacks, or poll get_generation_status until completed.","tags":["Generation creation"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key for replay-safe create retries. Overrides body idempotency_key.","schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"Existing brand","description":"Reference a brand you already have by `brand_id` (from `GET /api/v1/brands`). Do not send `brand_name` or `website`.","type":"object","properties":{"brand_id":{"description":"Existing brand id (from list_brands). Mutually exclusive with brand_name/website.","type":"string","minLength":1},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"quantity":{"default":1,"description":"Images per aspect ratio (1-3).","type":"integer","minimum":1,"maximum":3},"aspect_ratios":{"default":["4:5"],"description":"Aspect ratios / IAB sizes to generate (max 6, no duplicates).","minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["1:1","16:9","9:16","4:5","4:3","3:4","3:2","2:3","5:4","21:9","4:1","1:4","8:1","1:8","iab-300x250","iab-336x280","iab-728x90","iab-970x90","iab-970x250","iab-468x60","iab-160x600","iab-120x600","iab-300x600","iab-300x1050","iab-250x250","iab-320x50","iab-320x100","iab-640x100","iab-320x480","iab-580x400","tv-1920x495"]}},"ad_objective":{"type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"visual_style":{"default":"autodetect","type":"string","enum":["autodetect","benefit","bold_typography","candid","comparison","conceptual","doodle_overlay","dynamic_handoff","essentials","hypermotion","influencer_ugc","ingredient","material_typography","miniature_diorama","narrative_still_life","pas_grid","problem_solution","problem_striker","receipt","shelfie","stickerbomb","testimonial","text_thread","tone_on_tone","ugly","web_search","zine_style"]},"language":{"default":"English","type":"string"},"additional_direction":{"type":"string","maxLength":2000},"image_model":{"default":"bytedance-seedream-5-pro","type":"string","enum":["bytedance-seedream-5-lite","bytedance-seedream-5-pro","bytedance-seedream-4-5","gemini","gemini-pro","gemini-3-1-flash-image","gemini-3-1-flash-image-512","gemini-3-1-flash-image-1k","gemini-3-1-flash-image-4k","gemini-3-1-flash-lite-image","gpt-image-2","flux-2-max","wan-2.7-image","wan-2.7-image-pro","reve-remix"]},"llm_model":{"type":"string"},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_id","ad_objective"],"additionalProperties":false},{"title":"New or matched brand from website","description":"Send `brand_name` and `website` together. An existing brand with the same website is reused; otherwise the brand is created and scraped automatically. Do not send `brand_id`.","type":"object","properties":{"brand_name":{"description":"Brand name for find-or-create. Requires website.","type":"string","minLength":1},"website":{"description":"Brand website URL. Required with brand_name.","type":"string","format":"uri"},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"quantity":{"default":1,"description":"Images per aspect ratio (1-3).","type":"integer","minimum":1,"maximum":3},"aspect_ratios":{"default":["4:5"],"description":"Aspect ratios / IAB sizes to generate (max 6, no duplicates).","minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["1:1","16:9","9:16","4:5","4:3","3:4","3:2","2:3","5:4","21:9","4:1","1:4","8:1","1:8","iab-300x250","iab-336x280","iab-728x90","iab-970x90","iab-970x250","iab-468x60","iab-160x600","iab-120x600","iab-300x600","iab-300x1050","iab-250x250","iab-320x50","iab-320x100","iab-640x100","iab-320x480","iab-580x400","tv-1920x495"]}},"ad_objective":{"type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"visual_style":{"default":"autodetect","type":"string","enum":["autodetect","benefit","bold_typography","candid","comparison","conceptual","doodle_overlay","dynamic_handoff","essentials","hypermotion","influencer_ugc","ingredient","material_typography","miniature_diorama","narrative_still_life","pas_grid","problem_solution","problem_striker","receipt","shelfie","stickerbomb","testimonial","text_thread","tone_on_tone","ugly","web_search","zine_style"]},"language":{"default":"English","type":"string"},"additional_direction":{"type":"string","maxLength":2000},"image_model":{"default":"bytedance-seedream-5-pro","type":"string","enum":["bytedance-seedream-5-lite","bytedance-seedream-5-pro","bytedance-seedream-4-5","gemini","gemini-pro","gemini-3-1-flash-image","gemini-3-1-flash-image-512","gemini-3-1-flash-image-1k","gemini-3-1-flash-image-4k","gemini-3-1-flash-lite-image","gpt-image-2","flux-2-max","wan-2.7-image","wan-2.7-image-pro","reve-remix"]},"llm_model":{"type":"string"},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_name","website","ad_objective"],"additionalProperties":false}]}}}},"responses":{"202":{"description":"Generation queued.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/CreateStaticAdData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/carousels":{"post":{"operationId":"create_carousel_ad","summary":"Create a carousel ad","description":"Create a carousel ad generation for a brand. Cost: per-panel image credits × panel count + LLM base fee. In auto_panels mode credits are gated at the maximum panel count for the aspect ratio (1:1→12, 3:4→8, 9:16→6), so the estimate is a worst-case ceiling. Poll get_generation_status until completed, or supply webhook_url for a terminal callback.","tags":["Generation creation"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key for replay-safe create retries. Overrides body idempotency_key.","schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"Existing brand","description":"Reference a brand you already have by `brand_id` (from `GET /api/v1/brands`). Do not send `brand_name` or `website`.","type":"object","properties":{"brand_id":{"description":"Existing brand id (from list_brands). Mutually exclusive with brand_name/website.","type":"string","minLength":1},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"num_slides":{"type":"integer","minimum":3,"maximum":12,"description":"Panel count (manual mode) or fallback/cap (auto mode)."},"auto_panels":{"default":true,"description":"When true the planning LLM picks the panel count; credits are gated at the MAX slides for the chosen ratio, so the estimate can exceed num_slides.","type":"boolean"},"slide_aspect_ratio":{"type":"string","enum":["1:1","3:4","9:16"]},"ad_objective":{"type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"visual_style":{"default":"autodetect","type":"string","enum":["autodetect","benefit","essentials","ingredient","panorama","pas","problem_solution","testimonial","type_driven_minimal","corporate_pop","vector_editorial"]},"language":{"default":"English","type":"string"},"additional_direction":{"type":"string","maxLength":2000},"image_model":{"default":"gemini-3-1-flash-image","type":"string","enum":["bytedance-seedream-5-lite","bytedance-seedream-5-pro","bytedance-seedream-4-5","gemini","gemini-pro","gemini-3-1-flash-image","gemini-3-1-flash-image-512","gemini-3-1-flash-image-1k","gemini-3-1-flash-image-4k","gemini-3-1-flash-lite-image","gpt-image-2","flux-2-max","wan-2.7-image","wan-2.7-image-pro","reve-remix"]},"llm_model":{"type":"string"},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_id","num_slides","slide_aspect_ratio","ad_objective"],"additionalProperties":false},{"title":"New or matched brand from website","description":"Send `brand_name` and `website` together. An existing brand with the same website is reused; otherwise the brand is created and scraped automatically. Do not send `brand_id`.","type":"object","properties":{"brand_name":{"description":"Brand name for find-or-create. Requires website.","type":"string","minLength":1},"website":{"description":"Brand website URL. Required with brand_name.","type":"string","format":"uri"},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"num_slides":{"type":"integer","minimum":3,"maximum":12,"description":"Panel count (manual mode) or fallback/cap (auto mode)."},"auto_panels":{"default":true,"description":"When true the planning LLM picks the panel count; credits are gated at the MAX slides for the chosen ratio, so the estimate can exceed num_slides.","type":"boolean"},"slide_aspect_ratio":{"type":"string","enum":["1:1","3:4","9:16"]},"ad_objective":{"type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"visual_style":{"default":"autodetect","type":"string","enum":["autodetect","benefit","essentials","ingredient","panorama","pas","problem_solution","testimonial","type_driven_minimal","corporate_pop","vector_editorial"]},"language":{"default":"English","type":"string"},"additional_direction":{"type":"string","maxLength":2000},"image_model":{"default":"gemini-3-1-flash-image","type":"string","enum":["bytedance-seedream-5-lite","bytedance-seedream-5-pro","bytedance-seedream-4-5","gemini","gemini-pro","gemini-3-1-flash-image","gemini-3-1-flash-image-512","gemini-3-1-flash-image-1k","gemini-3-1-flash-image-4k","gemini-3-1-flash-lite-image","gpt-image-2","flux-2-max","wan-2.7-image","wan-2.7-image-pro","reve-remix"]},"llm_model":{"type":"string"},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_name","website","num_slides","slide_aspect_ratio","ad_objective"],"additionalProperties":false}]}}}},"responses":{"202":{"description":"Generation queued.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/CreateCarouselAdData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/rich-media":{"post":{"operationId":"create_rich_media_ad","summary":"Create a rich-media ad","description":"Create an animated rich-media (HTML5 banner) ad generation for a brand across the requested IAB sizes (max 6 per request). Cost: 250 credits flat. Poll get_generation_status until completed, or supply webhook_url for a terminal callback.","tags":["Generation creation"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Unique key for replay-safe create retries. Overrides body idempotency_key.","schema":{"type":"string","minLength":1,"maxLength":128}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"title":"Existing brand","description":"Reference a brand you already have by `brand_id` (from `GET /api/v1/brands`). Do not send `brand_name` or `website`.","type":"object","properties":{"brand_id":{"description":"Existing brand id (from list_brands). Mutually exclusive with brand_name/website.","type":"string","minLength":1},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"target_sizes":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["300x250","336x280","728x90","468x60","970x90","970x250","160x600","120x600","300x600","300x1050","250x250","580x400","320x50","320x100","300x50","320x480","1920x495"]},"description":"IAB sizes to generate (max 6 per request), e.g. [\"300x250\",\"728x90\"]. Known sizes: 300x250, 336x280, 728x90, 468x60, 970x90, 970x250, 160x600, 120x600, 300x600, 300x1050, 250x250, 580x400, 320x50, 320x100, 300x50, 320x480, 1920x495."},"ad_objective":{"type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"visual_style":{"default":"autodetect","type":"string","enum":["autodetect","modern","minimalist","vibrant","professional","creative","vintage","luxury"]},"language":{"default":"English","type":"string"},"model":{"default":"gpt-5.6-sol","type":"string"},"additional_direction":{"type":"string"},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_id","target_sizes","ad_objective"],"additionalProperties":false},{"title":"New or matched brand from website","description":"Send `brand_name` and `website` together. An existing brand with the same website is reused; otherwise the brand is created and scraped automatically. Do not send `brand_id`.","type":"object","properties":{"brand_name":{"description":"Brand name for find-or-create. Requires website.","type":"string","minLength":1},"website":{"description":"Brand website URL. Required with brand_name.","type":"string","format":"uri"},"idempotency_key":{"description":"Optional client-supplied key; retrying the same call with the same key returns the original result instead of creating a duplicate generation. Deduped for ~24 hours — do not reuse a key for a logically different request.","type":"string","minLength":1,"maxLength":128},"target_sizes":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["300x250","336x280","728x90","468x60","970x90","970x250","160x600","120x600","300x600","300x1050","250x250","580x400","320x50","320x100","300x50","320x480","1920x495"]},"description":"IAB sizes to generate (max 6 per request), e.g. [\"300x250\",\"728x90\"]. Known sizes: 300x250, 336x280, 728x90, 468x60, 970x90, 970x250, 160x600, 120x600, 300x600, 300x1050, 250x250, 580x400, 320x50, 320x100, 300x50, 320x480, 1920x495."},"ad_objective":{"type":"string","enum":["website_visits","store_traffic","phone_calls","brand_awareness","product_launch","sales_promotion"]},"visual_style":{"default":"autodetect","type":"string","enum":["autodetect","modern","minimalist","vibrant","professional","creative","vintage","luxury"]},"language":{"default":"English","type":"string"},"model":{"default":"gpt-5.6-sol","type":"string"},"additional_direction":{"type":"string"},"external_actor_id":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128},"webhook_url":{"description":"HTTPS callback URL for terminal generation events.","type":"string","maxLength":2048,"format":"uri"},"webhook_secret":{"description":"Secret used to HMAC-sign webhook request bodies.","type":"string","minLength":16,"maxLength":256}},"required":["brand_name","website","target_sizes","ad_objective"],"additionalProperties":false}]}}}},"responses":{"202":{"description":"Generation queued.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/CreateRichMediaAdData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/generations":{"get":{"operationId":"list_generations","summary":"List generations","description":"List this account's (or another team's, via team_id from list_teams) creative generations across all four pipelines (static_ad, carousel, rich_media, video), newest first. Filter by type, brand_id, or unified status. Returns up to `limit` (max 50) status-shaped summaries — each carrying team_id/team_name — and an opaque next_cursor when more pages exist — when paginating, pass cursor alone; it carries the original filters and team scope.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"type","in":"query","required":false,"schema":{"type":"string","enum":["static_ad","carousel","rich_media","video"]}},{"name":"brand_id","in":"query","required":false,"schema":{"type":"string","minLength":1}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]}},{"name":"external_actor_id","in":"query","required":false,"schema":{"description":"Opaque end-user id from the calling platform, for attribution only (echoed back on reads; not used for auth or credits).","type":"string","minLength":1,"maxLength":128}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":50}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/ListGenerationsData"}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/generations/{type}/{id}":{"get":{"operationId":"get_generation_status","summary":"Get generation status","description":"Check the status of a creative generation. Returns a unified status (queued | scraping | generating | rendering | completed | rendered | partial | failed) plus the pipeline-native raw_status and, when present, error_message. rendering and rendered are video-only. For a video, rendered means the MP4 is ready and includes its stable video_url, while completed means the composition is authored with no MP4 — either auto_render was false, or the render failed and error_message says why; call render_generation to render or retry. Poll again after poll_after_seconds until status is completed, rendered, partial, or failed — all four are terminal, so do not keep polling a completed video expecting a video_url that will never arrive. If completed, rendered, or partial, call get_generation_result to fetch the assets. If failed, the generation is terminal — do not poll further; get_generation_result will return GENERATION_FAILED rather than assets. Once terminal, always share app_url with the user as a clickable link to view or edit the result in the app.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"type","in":"path","required":true,"description":"Generation type: static_ad | carousel | rich_media | video","example":"video","schema":{"type":"string","enum":["static_ad","carousel","rich_media","video"]}},{"name":"id","in":"path","required":true,"description":"Generation id.","example":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/GenerationStatusData"}}},"examples":{"video-rendered":{"summary":"Video with MP4 ready (terminal; carries video_url)","value":{"ok":true,"data":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"name":"Acme Summer Sale 30s","brand_id":"0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","status":"rendered","raw_status":"rendered","created_at":"2026-07-15T18:20:04.000Z","completed_at":"2026-07-15T18:35:42.000Z","video_url":"https://media.example/video.mp4","poll_after_seconds":300}}},"video-generating":{"summary":"Video still authoring","value":{"ok":true,"data":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"name":"Acme Summer Sale 30s","brand_id":"0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","status":"generating","raw_status":"running","created_at":"2026-07-15T18:20:04.000Z","poll_after_seconds":300}}},"static-ad-completed":{"summary":"Static ad finished","value":{"ok":true,"data":{"generation":{"type":"static_ad","id":"e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f"},"name":"Acme Summer Sale statics","brand_id":"0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/static-ads/e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f","status":"completed","raw_status":"completed","created_at":"2026-07-15T18:20:04.000Z","completed_at":"2026-07-15T18:24:11.000Z","external_actor_id":"customer_874","poll_after_seconds":60}}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/generations/{type}/{id}/result":{"get":{"operationId":"get_generation_result","summary":"Get generation result","description":"Fetch the finished assets of a creative generation. Available once get_generation_status reports completed, rendered, or partial; otherwise returns GENERATION_NOT_READY with the current status and a poll hint. If the generation has failed, returns GENERATION_FAILED (terminal, no poll hint) with error_message when available. Image and bundle URLs are signed and expire after expires_in_seconds; video URLs are stable public URLs (and are also present on rendered video status payloads). A video at completed is authored with no MP4: it is served, but carries no video_url and reports render.rendered false — call render_generation to produce the MP4, unless render.supported is false, in which case only app_url can render it. Every result includes app_url — the in-app page to view and edit the creative (for carousels, whose slides are rendered in-app, app_url is the primary deliverable) — and credits_used, the credits attributed to this generation in the usage log when available. Layer-based static ads and carousels report a render block — when render.rendered is false, call render_generation to materialize deployable JPG files (assets will be empty until then); when render.stale is true the files predate the latest design edit and render_generation will refresh them. Always share app_url with the user as a clickable link to view or edit the result in the app. preview_url (when configured) is a shareable, login-free page to view the creative in a browser — prefer it when giving the user a link they can open without signing in.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"type","in":"path","required":true,"description":"Generation type: static_ad | carousel | rich_media | video","example":"video","schema":{"type":"string","enum":["static_ad","carousel","rich_media","video"]}},{"name":"id","in":"path","required":true,"description":"Generation id.","example":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/GenerationResultData"}}},"examples":{"video-rendered":{"summary":"Video with MP4 ready","value":{"ok":true,"data":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"status":"rendered","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","preview_url":"https://YOUR_HOST/preview/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d?token=SIGNED_TOKEN","credits_used":12000,"video_url":"https://media.example/video.mp4","duration_seconds":30,"aspect_ratio":"9:16","thumbnail_url":"https://media.example/thumbnail.png","render":{"required":true,"rendered":true,"supported":true,"tool":"render_generation"}}}},"video-authored-unrendered":{"summary":"Video authored but not rendered (auto_render: false)","value":{"ok":true,"data":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"status":"completed","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","credits_used":12000,"aspect_ratio":"9:16","render":{"required":true,"rendered":false,"supported":true,"tool":"render_generation"}}}},"static-ad-images":{"summary":"Static ad image assets","value":{"ok":true,"data":{"generation":{"type":"static_ad","id":"e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f"},"status":"completed","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/static-ads/e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f","credits_used":400,"assets":[{"id":"b2c3d4e5-2222-4333-8444-5f6a7b8c9d0e","kind":"image","url":"https://media.example/static-ad-1080x1350.png?signature=SIGNED","width":1080,"height":1350,"aspect_ratio":"4:5","metadata":{"size":"1080x1350"}}],"expires_in_seconds":3600,"render":{"required":true,"rendered":true,"stale":false,"tool":"render_generation"}}}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}},"/api/v1/generations/{type}/{id}/render":{"post":{"operationId":"render_generation","summary":"Render a generation","description":"Render the final deliverable of a completed generation. For a layer-based static ad or carousel, this materializes deployable JPGs (idempotent: an unchanged design returns the previously rendered files — pass force: true to re-render; carousels produce one JPG per slide, in slide order, plus the composite; flat image static ads need no rendering and the call is a no-op that returns the existing assets). For a video, this queues the final MP4 render — an ASYNC operation: the call returns immediately with task_queued and a poll_after_seconds hint, and the agent must call get_generation_result again after that interval to get video_url; an already-rendered reuse response includes video_url immediately (pass force: true to re-render an already-rendered video). Rendering is included in the generation cost (no additional credits). Not applicable to rich_media generations. Always share app_url with the user as a clickable link to view the result.","tags":["Resources"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"type","in":"path","required":true,"description":"Generation type: static_ad | carousel | rich_media | video","example":"video","schema":{"type":"string","enum":["static_ad","carousel","video"]}},{"name":"id","in":"path","required":true,"description":"Generation id.","example":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","schema":{"type":"string","minLength":1}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","content":{"application/json":{"schema":{"type":"object","required":["ok","data"],"properties":{"ok":{"const":true},"data":{"$ref":"#/components/schemas/RenderGenerationData"}}},"examples":{"video-render-queued":{"summary":"Video render started","value":{"ok":true,"data":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"status":"rendering","rendered":0,"reused":0,"task_queued":true,"poll_after_seconds":300,"app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","message":"Video render started — check get_generation_result after poll_after_seconds."}}},"video-already-rendered":{"summary":"Video already rendered (reused)","value":{"ok":true,"data":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"status":"rendered","rendered":0,"reused":1,"video_url":"https://media.example/video.mp4","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","message":"Video already rendered."}}},"static-carousel-rendered":{"summary":"Static/carousel designs rendered","value":{"ok":true,"data":{"generation":{"type":"static_ad","id":"e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f"},"status":"completed","rendered":2,"reused":1,"no_render_needed":false,"app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/static-ads/e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f","assets":[{"id":"b2c3d4e5-2222-4333-8444-5f6a7b8c9d0e","kind":"image","url":"https://media.example/static-ad-1080x1350.png?signature=SIGNED","width":1080,"height":1350,"aspect_ratio":"4:5","metadata":{"size":"1080x1350"}}],"expires_in_seconds":3600}}}}}}},"400":{"description":"VALIDATION_ERROR: The request does not match the tool input schema.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}]}}}},"401":{"description":"UNAUTHORIZED: Authentication is missing or invalid.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}]}}}},"402":{"description":"INSUFFICIENT_CREDITS: The account does not have enough credits.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}]}}}},"403":{"description":"INVALID_SCOPE: The credential lacks the required scope.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}]}}}},"404":{"description":"BRAND_NOT_FOUND: The brand does not exist in the authenticated account. TEAM_NOT_FOUND: The team does not exist or you are not a member of it. GENERATION_NOT_FOUND: The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}]}}}},"409":{"description":"GENERATION_NOT_READY: The generation is not ready for this operation. REQUEST_IN_FLIGHT: A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}]}}}},"410":{"description":"GENERATION_FAILED: The generation reached a terminal failed state.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}]}}}},"429":{"description":"RATE_LIMITED: The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}]}}}},"500":{"description":"INTERNAL_ERROR: An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}]}}}}}}}},"webhooks":{"generationTerminal":{"post":{"summary":"Generation terminal event","description":"Sent for generation.completed, generation.rendered, generation.partial, generation.failed, or generation.render_failed. Deliveries are at-least-once and may arrive out of order; occurred_at records when the event was raised and is preserved across delivery retries. For video, generation.rendered means the MP4 is ready and video_url is populated. generation.completed is sent only when the composition is the final deliverable — i.e. auto_render=false; an auto_render=true video is announced by generation.rendered alone, because authoring is a waypoint rather than a terminal state for it. Statuses delivered here are always terminal (completed / rendered / partial / failed); poll_after_seconds is an artifact of the shared status shape and can be ignored on webhook deliveries.","parameters":[{"name":"X-Adgreetz-Event","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Adgreetz-Delivery-Id","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Adgreetz-Signature","in":"header","required":false,"description":"sha256=<hex HMAC> when webhook_secret was supplied.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPayload"},"examples":{"video-rendered":{"summary":"generation.rendered — MP4 ready","value":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"name":"Acme Summer Sale 30s","brand_id":"0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","status":"rendered","raw_status":"rendered","created_at":"2026-07-15T18:20:04.000Z","completed_at":"2026-07-15T18:35:42.000Z","video_url":"https://media.example/video.mp4","poll_after_seconds":300,"event":"generation.rendered","delivery_id":"run_01JJXG4M9Q0V3T8B2N5C7D6E1F","occurred_at":"2026-07-15T18:35:42.123Z","result":{"generation":{"type":"video","id":"a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d"},"status":"rendered","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/video-ai/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d","preview_url":"https://YOUR_HOST/preview/a1b2c3d4-1111-4222-8333-9e8f7a6b5c4d?token=SIGNED_TOKEN","credits_used":12000,"video_url":"https://media.example/video.mp4","duration_seconds":30,"aspect_ratio":"9:16","thumbnail_url":"https://media.example/thumbnail.png","render":{"required":true,"rendered":true,"supported":true,"tool":"render_generation"}}}},"static-ad-completed":{"summary":"generation.completed — static ad finished","value":{"generation":{"type":"static_ad","id":"e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f"},"name":"Acme Summer Sale statics","brand_id":"0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/static-ads/e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f","status":"completed","raw_status":"completed","created_at":"2026-07-15T18:20:04.000Z","completed_at":"2026-07-15T18:24:11.000Z","external_actor_id":"customer_874","poll_after_seconds":60,"event":"generation.completed","delivery_id":"run_01JJXG4M9Q0V3T8B2N5C7D6E2G","occurred_at":"2026-07-15T18:24:11.456Z","result":{"generation":{"type":"static_ad","id":"e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f"},"status":"completed","app_url":"https://YOUR_HOST/home/brands/0f9e8d7c-7777-4888-8999-6b5a4c3d2e1f/static-ads/e5f6a7b8-4444-4555-8666-1a2b3c4d5e6f","credits_used":400,"assets":[{"id":"b2c3d4e5-2222-4333-8444-5f6a7b8c9d0e","kind":"image","url":"https://media.example/static-ad-1080x1350.png?signature=SIGNED","width":1080,"height":1350,"aspect_ratio":"4:5","metadata":{"size":"1080x1350"}}],"expires_in_seconds":3600,"render":{"required":true,"rendered":true,"stale":false,"tool":"render_generation"}}}}}}}},"responses":{"200":{"description":"Callback accepted."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"agz_live_… or Supabase OAuth access token","description":"Account API key beginning with agz_live_, or an authorized Supabase OAuth access token."}},"schemas":{"ListBrandsData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"name":{"type":"string"},"website":{"anyOf":[{"type":"string"},{"type":"null"}]},"logo_url":{"type":"string"},"team_id":{"type":"string","minLength":1},"team_name":{"type":"string"}},"required":["id","name","website","team_id"]}},"next_cursor":{"type":"string"}},"required":["items"]},"BrandData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","minLength":1},"name":{"type":"string"},"website":{"anyOf":[{"type":"string"},{"type":"null"}]},"description":{"type":"string"},"colors":{},"logo_url":{"type":"string"},"products":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"image_url":{"type":"string"}},"required":["title"]}}},"required":["id","name","website","products"]},"CreditBalanceData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"balance":{"type":"number"},"cost_reference":{"type":"object","properties":{"static_ad":{"type":"string"},"carousel":{"type":"string"},"rich_media":{"type":"string"},"video":{"type":"string"}},"required":["static_ad","carousel","rich_media","video"]}},"required":["balance","cost_reference"]},"CreateVideoAdData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","const":"video"},"id":{"type":"string","minLength":1}},"required":["type","id"]},"brand_id":{"type":"string","minLength":1},"name":{"type":"string"},"app_url":{"type":"string"},"required_credits":{"type":"number"},"status":{"type":"string","const":"queued"}},"required":["generation","brand_id","name","app_url","required_credits","status"]},"CreateStaticAdData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","const":"static_ad"},"id":{"type":"string","minLength":1}},"required":["type","id"]},"brand_id":{"type":"string","minLength":1},"name":{"type":"string"},"app_url":{"type":"string"},"required_credits":{"type":"number"},"status":{"type":"string","const":"queued"}},"required":["generation","brand_id","name","app_url","required_credits","status"]},"CreateCarouselAdData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","const":"carousel"},"id":{"type":"string","minLength":1}},"required":["type","id"]},"brand_id":{"type":"string","minLength":1},"name":{"type":"string"},"app_url":{"type":"string"},"required_credits":{"type":"number"},"status":{"type":"string","const":"queued"}},"required":["generation","brand_id","name","app_url","required_credits","status"]},"CreateRichMediaAdData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","const":"rich_media"},"id":{"type":"string","minLength":1}},"required":["type","id"]},"brand_id":{"type":"string","minLength":1},"name":{"type":"string"},"app_url":{"type":"string"},"required_credits":{"type":"number"},"status":{"type":"string","const":"queued"}},"required":["generation","brand_id","name","app_url","required_credits","status"]},"ListGenerationsData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","enum":["static_ad","carousel","rich_media","video"]},"id":{"type":"string","minLength":1}},"required":["type","id"]},"name":{"type":"string"},"brand_id":{"type":"string","minLength":1},"app_url":{"type":"string"},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"raw_status":{"type":"string"},"error_message":{"type":"string"},"created_at":{"type":"string"},"completed_at":{"type":"string"},"external_actor_id":{"type":"string"},"video_url":{"type":"string"},"poll_after_seconds":{"type":"number"},"team_id":{"type":"string","minLength":1},"team_name":{"type":"string"}},"required":["generation","name","brand_id","app_url","status","raw_status","created_at","poll_after_seconds","team_id"]}},"next_cursor":{"type":"string"}},"required":["items"]},"GenerationStatusData":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","enum":["static_ad","carousel","rich_media","video"]},"id":{"type":"string","minLength":1}},"required":["type","id"]},"name":{"type":"string"},"brand_id":{"type":"string","minLength":1},"app_url":{"type":"string"},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"raw_status":{"type":"string"},"error_message":{"type":"string"},"created_at":{"type":"string"},"completed_at":{"type":"string"},"external_actor_id":{"type":"string"},"video_url":{"type":"string"},"poll_after_seconds":{"type":"number"}},"required":["generation","name","brand_id","app_url","status","raw_status","created_at","poll_after_seconds"]},"GenerationResultData":{"$schema":"https://json-schema.org/draft/2020-12/schema","anyOf":[{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","enum":["static_ad","carousel"]},"id":{"type":"string","minLength":1}},"required":["type","id"]},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"external_actor_id":{"type":"string"},"app_url":{"type":"string"},"preview_url":{"type":"string"},"credits_used":{"type":"number"},"assets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"kind":{"type":"string","const":"image"},"url":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"aspect_ratio":{"type":"string"},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","kind","url","metadata"]}},"expires_in_seconds":{"type":"number"},"render":{"type":"object","properties":{"required":{"type":"boolean","const":true},"rendered":{"type":"boolean"},"stale":{"type":"boolean"},"tool":{"type":"string","const":"render_generation"}},"required":["required","rendered","stale","tool"]}},"required":["generation","status","app_url","assets","expires_in_seconds"]},{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","const":"rich_media"},"id":{"type":"string","minLength":1}},"required":["type","id"]},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"external_actor_id":{"type":"string"},"app_url":{"type":"string"},"preview_url":{"type":"string"},"credits_used":{"type":"number"},"sizes":{"type":"array","items":{"type":"object","properties":{"size":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"}},"required":["size","width","height"]}},"html":{"anyOf":[{"type":"string"},{"type":"null"}]},"html_available":{"type":"boolean"},"bundle_url":{"type":"string"},"expires_in_seconds":{"type":"number"}},"required":["generation","status","app_url","sizes","html","html_available"]},{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","const":"video"},"id":{"type":"string","minLength":1}},"required":["type","id"]},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"external_actor_id":{"type":"string"},"app_url":{"type":"string"},"preview_url":{"type":"string"},"credits_used":{"type":"number"},"video_url":{"type":"string"},"duration_seconds":{"type":"number"},"aspect_ratio":{"type":"string"},"thumbnail_url":{"type":"string"},"render":{"type":"object","properties":{"required":{"type":"boolean","const":true},"rendered":{"type":"boolean"},"supported":{"type":"boolean"},"tool":{"type":"string","const":"render_generation"},"reason":{"type":"string"}},"required":["required","rendered","supported"]}},"required":["generation","status","app_url","aspect_ratio","render"]}]},"RenderGenerationData":{"$schema":"https://json-schema.org/draft/2020-12/schema","anyOf":[{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","enum":["static_ad","carousel","rich_media","video"]},"id":{"type":"string","minLength":1}},"required":["type","id"]},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"rendered":{"type":"number"},"reused":{"type":"number"},"video_url":{"type":"string"},"app_url":{"type":"string"},"message":{"type":"string"}},"required":["generation","status","rendered","reused","app_url","message"]},{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","enum":["static_ad","carousel","rich_media","video"]},"id":{"type":"string","minLength":1}},"required":["type","id"]},"status":{"type":"string","const":"rendering"},"rendered":{"type":"number"},"reused":{"type":"number"},"task_queued":{"type":"boolean","const":true},"poll_after_seconds":{"type":"number"},"app_url":{"type":"string"},"message":{"type":"string"}},"required":["generation","status","rendered","reused","task_queued","poll_after_seconds","app_url","message"]},{"type":"object","properties":{"generation":{"type":"object","properties":{"type":{"type":"string","enum":["static_ad","carousel","rich_media","video"]},"id":{"type":"string","minLength":1}},"required":["type","id"]},"status":{"type":"string","enum":["queued","scraping","generating","rendering","completed","rendered","partial","failed"]},"rendered":{"type":"number"},"reused":{"type":"number"},"no_render_needed":{"type":"boolean"},"app_url":{"type":"string"},"assets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"kind":{"type":"string","const":"image"},"url":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"aspect_ratio":{"type":"string"},"metadata":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["id","kind","url","metadata"]}},"expires_in_seconds":{"type":"number"}},"required":["generation","status","rendered","reused","no_render_needed","app_url"]}]},"ErrorEnvelope":{"type":"object","required":["ok","error"],"properties":{"ok":{"const":false},"error":{"type":"object","required":["code","message"],"properties":{"code":{"enum":["UNAUTHORIZED","INVALID_SCOPE","RATE_LIMITED","VALIDATION_ERROR","BRAND_NOT_FOUND","TEAM_NOT_FOUND","GENERATION_NOT_FOUND","INSUFFICIENT_CREDITS","GENERATION_NOT_READY","REQUEST_IN_FLIGHT","GENERATION_FAILED","INTERNAL_ERROR"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"WebhookPayload":{"allOf":[{"$ref":"#/components/schemas/GenerationStatusData"},{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"event":{"type":"string","enum":["generation.completed","generation.rendered","generation.partial","generation.failed","generation.render_failed"]},"delivery_id":{"type":"string","minLength":1},"occurred_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$","description":"When the lifecycle event was raised. Stable across delivery retries; use it to order delayed callbacks.","example":"2026-07-24T18:42:17.123Z"},"result":{"$ref":"#/components/schemas/GenerationResultData"}},"required":["event","delivery_id","occurred_at"]}]}},"responses":{"UNAUTHORIZED":{"description":"Authentication is missing or invalid.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"UNAUTHORIZED"}}}}}]}}}},"INVALID_SCOPE":{"description":"The credential lacks the required scope.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INVALID_SCOPE"}}}}}]}}}},"RATE_LIMITED":{"description":"The per-key request limit was exceeded.","headers":{"Retry-After":{"description":"Seconds until another request should be attempted.","schema":{"type":"integer","minimum":0}}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"RATE_LIMITED"}}}}}]}}}},"VALIDATION_ERROR":{"description":"The request does not match the tool input schema.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"VALIDATION_ERROR"}}}}}]}}}},"BRAND_NOT_FOUND":{"description":"The brand does not exist in the authenticated account.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"BRAND_NOT_FOUND"}}}}}]}}}},"TEAM_NOT_FOUND":{"description":"The team does not exist or you are not a member of it.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"TEAM_NOT_FOUND"}}}}}]}}}},"GENERATION_NOT_FOUND":{"description":"The generation does not exist in the authenticated account.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_FOUND"}}}}}]}}}},"INSUFFICIENT_CREDITS":{"description":"The account does not have enough credits.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INSUFFICIENT_CREDITS"}}}}}]}}}},"GENERATION_NOT_READY":{"description":"The generation is not ready for this operation.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_NOT_READY"}}}}}]}}}},"REQUEST_IN_FLIGHT":{"description":"A request with this idempotency key is currently executing.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"REQUEST_IN_FLIGHT"}}}}}]}}}},"GENERATION_FAILED":{"description":"The generation reached a terminal failed state.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"GENERATION_FAILED"}}}}}]}}}},"INTERNAL_ERROR":{"description":"An internal error occurred. Use the correlation id if present.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"properties":{"error":{"properties":{"code":{"const":"INTERNAL_ERROR"}}}}}]}}}}}},"x-creative-mcp-tool-count":12}