Skip to main content
Transform, generate, or retrieve a creative manifest for a specific format. Supports three modes:
  1. Generation: Create a manifest from a brief or seed assets (message + creative_manifest)
  2. Transformation: Adapt an existing manifest to a different format (creative_manifest + target_format_id)
  3. Library retrieval: Resolve a creative_id from the agent’s library into a manifest with ad-serving assets
For generation and transformation, build_creative takes a creative manifest as input and produces a creative manifest as output. For library retrieval, provide a creative_id (from list_creatives) and the agent resolves it from its library. For information about format IDs and how to reference formats, see Creative Formats - Referencing Formats.

Request parameters

ParameterTypeRequiredDescription
messagestringNoNatural language instructions for the creative agent. For generation, this provides creative direction. For transformation, this guides how to adapt the creative. For refinement, this describes the desired changes.
creative_manifestobjectNoCreative manifest to transform or generate from (see Creative Manifest). For pure generation, this should include the target format_id and any required input assets. For transformation, this is the complete creative to adapt. When creative_id is provided, the agent resolves the creative from its library and this field is ignored.
creative_idstringNoReference to a creative in the agent’s library. The creative agent resolves this to a manifest from its library. Use this instead of creative_manifest when retrieving an existing creative for tag generation or format adaptation.
concept_idstringNoCreative concept containing the creative. Used to disambiguate when the same creative_id exists in multiple concepts.
media_buy_idstringNoBuyer’s media buy reference for tag generation context. When the creative agent is also the ad server (e.g., CM360), this provides the trafficking context needed to generate placement-specific tags. Omit when the platform generates tags at the creative level (Flashtalking, Celtra). This is the buyer’s reference — the seller-assigned identifier from create_media_buy.
package_idstringNoBuyer’s package or line item reference within the media buy. Used with media_buy_id when the creative agent needs line-item-level context. Omit to get a tag not scoped to a specific package — the ad server may return the same tag regardless.
target_format_idobjectConditionalSingle format ID to generate. Object with agent_url and id fields. Mutually exclusive with target_format_ids — provide exactly one.
target_format_idsarrayConditionalArray of format IDs to generate in a single call. Each element is an object with agent_url and id fields. Mutually exclusive with target_format_id — provide exactly one. Returns one manifest per format.
brandobjectNoBrand reference with domain field. Resolves brand identity via /.well-known/brand.json. Provides brand-level context (colors, logos, tone).
qualitystringNoQuality tier: "draft" (fast, lower-fidelity for iteration) or "production" (full quality for final delivery). If omitted, the creative agent uses its own default.
item_limitintegerNoMaximum number of catalog items to use when generating. Caps generation cost for catalog-driven formats.
include_previewbooleanNoWhen true, requests preview renders alongside the manifest. Agents that support this return a preview object in the response. Agents that don’t simply omit it.
preview_inputsarrayNoInput sets for preview generation when include_preview is true. Each entry has name (required), optional macros, and optional context_description. If omitted, the agent generates a single default preview. Only supported with target_format_id (single-format) — ignored for multi-format requests.
preview_qualitystringNoRender quality for inline previews: "draft" or "production". Independent of the build quality — you can build at draft and preview at production, or vice versa. Only used when include_preview is true.
preview_output_formatstringNoOutput format for preview renders: "url" (default) or "html". Only used when include_preview is true.
macro_valuesobjectNoMacro values to pre-substitute into the output manifest’s assets. Keys are universal macro names (e.g., CLICK_URL, CACHEBUSTER); values are the literal substitution strings. The creative agent translates universal macros to its platform’s native syntax. Macros not provided here remain as {MACRO} placeholders for the sales agent to resolve at serve time.
Important: Required input assets should be included in the creative_manifest.assets object, not as separate task parameters. The format definition specifies what assets it requires. Catalog context for dynamic creatives should be provided via the creative_manifest.assets map.

Generation controls

For generative formats, two optional parameters control the generation process:
  • quality: Controls generation fidelity. Use "draft" for rapid iteration (reviewing layouts, copy, composition) and "production" for final renders. Draft outputs may use lower-resolution images, simplified effects, or placeholder elements. To produce a production version of a draft you like, pass the draft’s output manifest back as creative_manifest with quality: "production". Note: preview_creative also accepts quality to control render fidelity independently — see Previewing generative creative.
  • item_limit: For catalog-driven formats, caps how many catalog items are used during generation. A catalog might contain 1,000 products but you only need 4 hero images. The creative agent selects top items based on relevance or catalog ordering. When item_limit exceeds the format’s max_items (from catalog requirements), the creative agent should use the lesser of the two. If omitted, the creative agent decides based on catalog size and format requirements.

Use cases

Pure generation (creating from scratch)

For pure generation, provide a minimal source manifest with the required input assets defined by the format:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create a banner promoting our winter sale with a warm, inviting feel",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250_generative"
  },
  "brand": {
    "domain": "mybrand.com"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250_generative"
    },
    "assets": {
      "offering_catalog": {
        "type": "offering",
        "items": [
          {
            "offering_id": "winter-sale",
            "name": "Winter Sale Collection",
            "description": "50% off all winter items"
          }
        ]
      }
    }
  }
}

Transformation (adapting existing creative)

For transformation, provide the complete source manifest:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Adapt this creative for mobile, making the text larger and CTA more prominent",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250"
    },
    "assets": {
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.example.com/original-banner.png",
        "width": 300,
        "height": 250
      },
      "headline": {
        "asset_type": "text",
        "content": "Winter Sale - 50% Off"
      }
    }
  },
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_mobile_320x50"
  }
}

Format resizing

Transform an existing creative to a different size:
{
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_728x90"
    },
    "assets": { /* complete assets */ }
  },
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250"
  }
}

Library retrieval

Retrieve a creative from the agent’s library and resolve it into a manifest with ad-serving assets. Use this when you know the creative_id from list_creatives and want the creative agent to produce a delivery-ready manifest with tags (HTML, JavaScript, or VAST):
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "creative_id": "ft_88201",
  "concept_id": "concept_holiday_2026",
  "target_format_id": {
    "agent_url": "https://creative.example.com",
    "id": "display_static",
    "width": 300,
    "height": 250
  },
  "macro_values": {
    "CLICK_URL": "https://publisher.example.com/click/abc123"
  }
}
Response — the manifest includes ad-serving tag assets with macros resolved:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.example.com",
      "id": "display_static",
      "width": 300,
      "height": 250
    },
    "assets": {
      "ad_tag": {
        "content": "<script src=\"https://cdn.example.com/frameworks/js/sdk.js\"></script><script>AdSDK.createBanner({clickTag:'https://publisher.example.com/click/abc123',width:300,height:250,id:'ft_88201_{CACHEBUSTER}'});</script>"
      },
      "clickthrough_url": {
        "url": "https://acmecorp.example.com/holiday-sale"
      }
    }
  }
}
The CLICK_URL macro was substituted with the provided value; CACHEBUSTER remains as a placeholder for the sales agent to resolve at serve time.
Cross-agent workflow: When creative generation and media buying are handled by different agents, use build_creative on the creative agent to produce a manifest with tags, then sync_creatives on the sales agent to upload it. When the sales agent implements both protocols, this happens on a single endpoint — see Creative capabilities on sales agents.

Multi-format generation

Generate creatives for multiple formats in a single call using target_format_ids. The agent produces one manifest per format from the same source assets and brief:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create display banners for our spring campaign",
  "target_format_ids": [
    {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_static",
      "width": 300,
      "height": 250
    },
    {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_static",
      "width": 728,
      "height": 90
    },
    {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_static",
      "width": 320,
      "height": 50
    }
  ],
  "brand": {
    "domain": "acmecorp.com"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_static"
    },
    "assets": {
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.acmecorp.com/spring-hero.png",
        "width": 1200,
        "height": 628
      },
      "headline": {
        "asset_type": "text",
        "content": "Spring Collection Now Available"
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://acmecorp.com/spring"
      }
    }
  }
}
The response uses creative_manifests (array) instead of creative_manifest (singular). Each manifest is a complete creative manifest with its own format_id, ready for sync_creatives or preview_creative:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifests": [
    {
      "format_id": {
        "agent_url": "https://creative.adcontextprotocol.org",
        "id": "display_static",
        "width": 300,
        "height": 250
      },
      "assets": {
        "banner_image": {
          "asset_type": "image",
          "url": "https://cdn.creative-agent.com/generated/spring_300x250.png",
          "width": 300,
          "height": 250
        },
        "headline": { "asset_type": "text", "content": "Spring Collection Now Available" },
        "clickthrough_url": { "asset_type": "url", "url": "https://acmecorp.com/spring" }
      }
    },
    {
      "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "display_static", "width": 728, "height": 90 },
      "assets": { /* same structure, adapted for 728x90 */ }
    },
    {
      "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "display_static", "width": 320, "height": 50 },
      "assets": { /* same structure, adapted for 320x50 */ }
    }
  ]
}
Multi-format requests are atomic — if any format fails (e.g., FORMAT_NOT_SUPPORTED), the entire request fails with an error response. The response array order corresponds to the target_format_ids request order. Match manifests to requested formats by array position or by comparing the format_id on each manifest.

Multi-format workflow

After a multi-format build, preview all results using preview_creative batch mode. Each element of creative_manifests in the build response becomes a creative_manifest in the batch preview request:
{
  "request_type": "batch",
  "quality": "draft",
  "requests": [
    { "creative_manifest": { /* 300x250 manifest from build response */ } },
    { "creative_manifest": { /* 728x90 manifest from build response */ } },
    { "creative_manifest": { /* 320x50 manifest from build response */ } }
  ]
}
To refine a single format from a multi-format build, call build_creative again with target_format_id (singular) and pass back that format’s manifest. You don’t need to rebuild all formats — just iterate on the one that needs work.
Multi-format requests with include_preview: true generate one default preview per format. Custom preview_inputs are only supported with single-format requests. For multi-format builds where you need context-specific previews (device variants, different contexts), use a separate preview_creative batch call after building.

Response format

Single-format response

When the request uses target_format_id, the response contains a single creative manifest:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250"
    },
    "assets": {
      "offering_catalog": {
        "type": "offering",
        "catalog_id": "winter-sale"
      },
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.example.com/generated-banner.png",
        "width": 300,
        "height": 250
      },
      "headline": {
        "asset_type": "text",
        "content": "50% Off Winter Sale"
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://mybrand.com/winter-sale"
      }
    }
  }
}

Multi-format response

When the request uses target_format_ids, the response contains an array of creative manifests:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifests": [
    {
      "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "display_static", "width": 300, "height": 250 },
      "assets": { /* ... */ }
    },
    {
      "format_id": { "agent_url": "https://creative.adcontextprotocol.org", "id": "display_static", "width": 728, "height": 90 },
      "assets": { /* ... */ }
    }
  ]
}

Field descriptions

  • creative_manifest: (single-format) The complete creative manifest ready for use with sync_creatives or preview_creative
  • creative_manifests: (multi-format) Array of complete creative manifests, one per requested format. Each contains its own format_id.
  • format_id: The target format (matches the requested format)
  • assets: Map of asset keys to asset content — includes creative content (images, text, URLs), catalogs, briefs, and anything else the format requires
  • expires_at: Optional ISO 8601 timestamp when generated asset URLs in the manifest expire. Set to the earliest expiration across all generated assets. Re-build the creative after this time to get fresh URLs. Not present when the manifest contains no expiring URLs (e.g., pure text generation or assembly-only transforms).
  • preview: Optional. Present when include_preview was true in the request and the agent supports inline preview. Contains the same content fields as a preview_creative single response (previews, interactive_url, expires_at) minus the response_type discriminator, so clients can reuse the same preview rendering logic. For single-format responses, each entry in previews[] corresponds to an input set from preview_inputs. For multi-format responses, each entry includes a format_id and corresponds to one requested format (one default preview per format; preview_inputs is ignored).
  • preview_error: Optional. Standard error object (code, message, recovery) present when include_preview was true but preview generation failed. The recovery field indicates whether the failure is transient (retry later), correctable, or terminal. Distinguishes “agent doesn’t support inline preview” (field absent, no error) from “preview generation failed” (field present with structured error).

Compliance errors

If the manifest includes a brief asset with compliance requirements that the creative agent cannot satisfy, the agent MUST return an error — not a partial success. Unsatisfied disclosures are a hard failure.
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "errors": [
    {
      "code": "COMPLIANCE_UNSATISFIED",
      "message": "Required disclosure cannot be rendered in this format",
      "field": "creative_manifest.assets.brief.compliance.required_disclosures[0]",
      "details": {
        "disclosure_text": "Past performance is not indicative of future results.",
        "position": "footer",
        "reason": "Format display_mobile_320x50 does not support footer position"
      },
      "suggestion": "Use a format that supports footer disclosures, or change position to 'overlay'"
    }
  ]
}
Creative agents MUST validate that all required_disclosures can be satisfied in the target format before generating the creative. If any disclosure cannot be placed as specified, the entire request fails. This ensures regulated creatives are never served without required legal text.

Response timing

How the creative agent responds depends on how long the operation will take:
Expected durationStatusCaller experience
Under 30 secondscompletedResult returned directly — synchronous
Over 30 seconds, server actively processingworkingOut-of-band status updates while the server continues processing. Caller holds the connection — still synchronous from their perspective
Blocked on external dependency (human review, approval)submittedTruly async — caller should configure a webhook via push_notification_config and move on
The creative agent decides which path to take based on the work involved. Library retrieval is instant. Simple transformations take seconds. AI generation varies — a quick banner might complete in 10 seconds, a complex video composition might take minutes.

working is a progress signal, not a polling trigger

When the server expects to take more than 30 seconds but is actively processing, it sends working as an out-of-band MCP status update. This keeps the client informed (“I’m on it”) without requiring the caller to switch to a polling or webhook pattern. The connection stays open and the result arrives when it’s ready.

When to go async

submitted means the operation is blocked on something outside the server’s control:
  • Human creative review — brand guidelines require approval before returning
  • External approval workflows — third-party compliance or legal review
For these cases, configure a webhook via push_notification_config to receive the result. See Async Operations and Push Notifications.

Human-in-the-loop

The agent may return status: "input-required" when it needs human input — for example, when brand guidelines require creative approval or when the agent needs clarification on creative direction:
{
  "reason": "CREATIVE_DIRECTION_NEEDED"
}
Reason codes:
  • APPROVAL_REQUIRED — Creative needs human approval before finalizing
  • CREATIVE_DIRECTION_NEEDED — Agent needs clarification on creative brief or direction
  • ASSET_SELECTION_NEEDED — Agent needs the caller to choose between asset options

Workflow integration

Typical generation workflow

  1. Build: Use build_creative to generate/transform the manifest
  2. Preview: Use preview_creative to see how it renders (see preview_creative)
  3. Sync: Use sync_creatives to traffic the finalized creative
You can combine steps 1 and 2 by setting include_preview: true on the build request. If the agent supports it, the response includes a preview object alongside the manifest — same content fields as preview_creative, no extra round trip. If the agent doesn’t support inline preview, the field is simply absent and you fall back to a separate preview_creative call. Always check for the presence of preview rather than assuming it will be there when requested. Use preview_quality to control render fidelity independently from build quality. For example, build at quality: "draft" (fast concept generation) but preview at preview_quality: "production" (full-fidelity render to show stakeholders the layout). If preview_quality is omitted, the agent uses its own default.
// Build at draft quality, but preview at production quality for stakeholder review
{
  "message": "Create a display banner for our winter sale",
  "target_format_id": {"agent_url": "...", "id": "display_300x250_generative"},
  "brand": { "domain": "mybrand.com" },
  "quality": "draft",
  "include_preview": true,
  "preview_quality": "production",
  "creative_manifest": {
    "format_id": {"agent_url": "...", "id": "display_300x250_generative"},
    "assets": {
      "product_catalog": {
        "type": "product",
        "catalog_id": "winter-products"
      }
    }
  }
}

// Or: Build first, preview separately
// Step 1: Build
{
  "message": "Create a display banner for our winter sale",
  "target_format_id": {"agent_url": "...", "id": "display_300x250_generative"},
  "brand": { "domain": "mybrand.com" },
  "creative_manifest": {
    "format_id": {"agent_url": "...", "id": "display_300x250_generative"},
    "assets": {
      "product_catalog": {
        "type": "product",
        "catalog_id": "winter-products"
      }
    }
  }
}

// Step 2: Preview (using the output manifest from step 1)
{
  "request_type": "single",
  "format_id": {"agent_url": "...", "id": "display_300x250"},
  "creative_manifest": {
    /* output from build_creative - includes all assets */
  },
  "inputs": [{"name": "Desktop view"}, {"name": "Mobile view"}]
}

// Step 3: Sync (if preview looks good)
{
  "creative_manifests": [{ /* approved manifest from build_creative */ }]
}
Key insight: The manifest carries everything. Briefs, catalogs, images, text — all live in the assets map and flow through from input to output. No need to pass them separately at each step.

Examples

Example 1: Pure generation (generative format)

Generate a creative from scratch using a generative format:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create a display banner for our winter sale. Use warm colors and emphasize the 50% discount",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250_generative"
  },
  "brand": {
    "domain": "mybrand.com"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250_generative"
    },
    "assets": {
      "offering_catalog": {
        "type": "offering",
        "items": [
          {
            "offering_id": "winter-sale",
            "name": "Winter Sale Collection",
            "description": "50% off all winter items"
          }
        ]
      }
    }
  }
}
Response:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250"
    },
    "assets": {
      "offering_catalog": {
        "type": "offering",
        "catalog_id": "winter-sale"
      },
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/generated/banner_12345.png",
        "width": 300,
        "height": 250
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://mybrand.com/winter-sale"
      }
    }
  }
}

Example 2: Format transformation

Transform an existing 728x90 leaderboard to a 300x250 banner:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Adapt this leaderboard creative to a 300x250 banner format",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_728x90"
    },
    "assets": {
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.mybrand.com/leaderboard.png",
        "width": 728,
        "height": 90
      },
      "headline": {
        "asset_type": "text",
        "content": "Spring Sale - 30% Off Everything"
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://mybrand.com/spring"
      }
    }
  },
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250"
  }
}
Response:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250"
    },
    "assets": {
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/resized/banner_67890.png",
        "width": 300,
        "height": 250
      },
      "headline": {
        "asset_type": "text",
        "content": "Spring Sale - 30% Off"
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://mybrand.com/spring"
      }
    }
  }
}

Example 3: Transformation with specific instructions

Adapt a creative for mobile with specific design changes:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Make this mobile-friendly: increase text size, simplify the layout, and make the CTA button more prominent",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x600"
    },
    "assets": {
      "background_image": {
        "asset_type": "image",
        "url": "https://cdn.mybrand.com/bg.jpg",
        "width": 300,
        "height": 600
      },
      "headline": {
        "asset_type": "text",
        "content": "Discover Our New Collection"
      },
      "body_text": {
        "asset_type": "text",
        "content": "Shop the latest styles with free shipping on orders over $50"
      },
      "cta_text": {
        "asset_type": "text",
        "content": "Shop Now"
      }
    }
  },
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_mobile_320x50"
  }
}
Response:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_mobile_320x50"
    },
    "assets": {
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/mobile/banner_mobile_123.png",
        "width": 320,
        "height": 50
      },
      "headline": {
        "asset_type": "text",
        "content": "New Collection - Shop Now"
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://mybrand.com/new"
      }
    }
  }
}

Example 4: Generation with creative brief

Generate a creative using structured campaign context via brand and a brief asset on the manifest:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create a display banner for the holiday campaign targeting gift shoppers",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250_generative"
  },
  "brand": {
    "domain": "acmecorp.com"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250_generative"
    },
    "assets": {
      "brief": {
        "name": "Holiday Sale 2025",
        "objective": "conversion",
        "audience": "Holiday gift shoppers aged 25-55",
        "territory": "festive savings",
        "messaging": {
          "headline": "Holiday Deals Are Here",
          "cta": "Shop Now",
          "key_messages": [
            "Up to 50% off select items",
            "Free shipping on orders over $50"
          ]
        },
        "reference_assets": [
          {
            "url": "https://cdn.acmecorp.com/holiday-mood-board.pdf",
            "role": "mood_board",
            "description": "Holiday campaign mood board with festive color palette"
          }
        ]
      },
      "offering_catalog": {
        "type": "offering",
        "items": [
          {
            "offering_id": "holiday-sale",
            "name": "Holiday Sale Collection",
            "description": "Up to 50% off select holiday items"
          }
        ]
      }
    }
  }
}

Example 5: Generation with compliance requirements

Generate a financial services creative with regulatory disclosures and prohibited claims:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create a display banner promoting retirement planning advisory services",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250_generative"
  },
  "brand": {
    "domain": "pinnaclewealth.com"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250_generative"
    },
    "assets": {
      "brief": {
        "name": "Retirement Advisory Q1 2026",
        "objective": "consideration",
        "audience": "Pre-retirees aged 50-65 with investable assets",
        "territory": "trusted financial guidance",
        "messaging": {
          "headline": "Plan Your Retirement with Confidence",
          "cta": "Schedule a Consultation",
          "key_messages": [
            "Personalized retirement planning",
            "Tax-efficient investment strategies"
          ]
        },
        "compliance": {
          "required_disclosures": [
            {
              "text": "Past performance is not indicative of future results.",
              "position": "footer",
              "jurisdictions": ["US"],
              "regulation": "SEC Rule 156"
            },
            {
              "text": "Securities offered through Pinnacle Wealth Securities, LLC. Member FINRA/SIPC.",
              "position": "footer",
              "jurisdictions": ["US"],
              "regulation": "FINRA Rule 2210"
            },
            {
              "text": "Capital at risk. The value of investments can go down as well as up.",
              "position": "prominent",
              "jurisdictions": ["GB"],
              "regulation": "FCA COBS 4.5"
            },
            {
              "text": "Pinnacle Wealth Advisors is a registered investment adviser.",
              "position": "footer"
            }
          ],
          "prohibited_claims": [
            "guaranteed returns",
            "risk-free investment",
            "outperform the market"
          ]
        }
      }
    }
  }
}
Compliance requirements differ by jurisdiction: the US requires SEC-mandated disclosures while the UK requires FCA-mandated risk warnings. The third disclosure (no jurisdictions) applies globally. The prohibited_claims array tells the creative agent which claims to avoid in generated copy.

Example 6: Commerce media with brief and product catalog

Generate a sponsored product carousel with campaign context, compliance disclosures, and a synced product catalog:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create a product carousel highlighting the top 4 sale items",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "sponsored_product_carousel"
  },
  "brand": {
    "domain": "novabrands.com"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "sponsored_product_carousel"
    },
    "assets": {
      "brief": {
        "name": "Spring Sale 2026",
        "objective": "conversion",
        "audience": "Value-conscious shoppers aged 25-45",
        "messaging": {
          "headline": "Spring Sale — Up to 40% Off",
          "cta": "Shop Now"
        },
        "compliance": {
          "required_disclosures": [
            {
              "text": "Sponsored",
              "position": "prominent"
            },
            {
              "text": "Prices may vary by location. See store for details.",
              "position": "footer"
            }
          ]
        }
      },
      "product_catalog": {
        "type": "product",
        "catalog_id": "spring_sale_2026"
      }
    }
  }
}
The brief and product catalog travel together in the manifest’s assets map. The format declares both a brief and catalog asset type — the buying agent discovers this via list_creative_formats and syncs the required catalog before submitting.

Example 7: Build with inline preview

Build a creative and get preview renders in the same response:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create a banner for our spring campaign",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250_generative"
  },
  "brand": {
    "domain": "novabrands.com"
  },
  "include_preview": true,
  "preview_inputs": [
    { "name": "Default" },
    { "name": "Dark mode", "macros": { "COLOR_SCHEME": "dark" } }
  ],
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250_generative"
    },
    "assets": {
      "offering_catalog": {
        "type": "offering",
        "items": [
          {
            "offering_id": "spring-promo",
            "name": "Spring Collection",
            "description": "30% off new arrivals"
          }
        ]
      }
    }
  }
}
Response (when the agent supports inline preview):
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250"
    },
    "assets": {
      "offering_catalog": {
        "type": "offering",
        "catalog_id": "spring-promo"
      },
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/generated/spring_abc123.png",
        "width": 300,
        "height": 250
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://novabrands.com/spring"
      }
    }
  },
  "preview": {
    "previews": [
      {
        "preview_id": "prev_default",
        "renders": [
          {
            "render_id": "r1",
            "output_format": "url",
            "preview_url": "https://preview.creative-agent.com/abc123/default",
            "role": "primary",
            "dimensions": { "width": 300, "height": 250 }
          }
        ],
        "input": { "name": "Default" }
      },
      {
        "preview_id": "prev_dark",
        "renders": [
          {
            "render_id": "r2",
            "output_format": "url",
            "preview_url": "https://preview.creative-agent.com/abc123/dark",
            "role": "primary",
            "dimensions": { "width": 300, "height": 250 }
          }
        ],
        "input": { "name": "Dark mode", "macros": { "COLOR_SCHEME": "dark" } }
      }
    ],
    "expires_at": "2026-03-13T06:00:00Z"
  },
  "expires_at": "2026-03-13T06:00:00Z"
}
The preview object contains the same content fields as a preview_creative single response (previews, interactive_url, expires_at). If the agent does not support inline preview, this field is absent — the buyer agent falls back to a separate preview_creative call. If preview generation fails, the response includes preview_error with a standard error object (code, message, recovery) instead.

Example 8: Draft generation with item limit

Generate a draft-quality creative from a large catalog, capping the number of items:
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Create hero images for our top sale items",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "sponsored_product_carousel"
  },
  "brand": {
    "domain": "novabrands.com"
  },
  "quality": "draft",
  "item_limit": 4,
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "sponsored_product_carousel"
    },
    "assets": {
      "product_catalog": {
        "type": "product",
        "catalog_id": "spring_sale_2026"
      }
    }
  }
}
The catalog may contain hundreds of products, but item_limit: 4 ensures only 4 hero images are generated. quality: "draft" produces fast, lower-fidelity output for review. Response:
{
  "$schema": "/schemas/media-buy/build-creative-response.json",
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "sponsored_product_carousel"
    },
    "assets": {
      "product_catalog": {
        "type": "product",
        "catalog_id": "spring_sale_2026"
      },
      "card_1_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/draft/card1_abc123.jpg",
        "width": 400,
        "height": 400
      },
      "card_2_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/draft/card2_def456.jpg",
        "width": 400,
        "height": 400
      },
      "card_3_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/draft/card3_ghi789.jpg",
        "width": 400,
        "height": 400
      },
      "card_4_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/draft/card4_jkl012.jpg",
        "width": 400,
        "height": 400
      }
    }
  },
  "expires_at": "2026-03-02T06:00:00Z"
}
The expires_at field signals when the generated CDN URLs expire. Re-build after this time to get fresh URLs. Once the direction is approved, re-submit the output manifest with quality: "production" for final renders.

Key concepts

Brand vs creative brief

BrandCreative Brief
ScopeBrand identityCampaign context
LifespanStable across campaignsSpecific to a campaign or flight
ContainsColors, logos, fonts, toneAudience, territory, messaging, compliance, reference assets
LegalBrand-level disclaimers (always-on)Campaign-specific regulatory disclosures (regional, product-based)
SourceBrand registry / /.well-known/brand.jsonAgency or brand team
Lives onResolved via domain lookupThe manifest’s assets map (assets.brief)
Both are optional. brand provides stable brand identity (colors, logos, tone) resolved via the domain’s /.well-known/brand.json. The brief is an asset on the manifest (assets.brief), so it travels with the creative through regeneration, resizing, and auditing. The message field provides per-request natural language instructions. Precedence: The brand parameter is the authoritative source for creative rendering context (colors, logos, tone). Layering: The brief asset on the manifest provides structured direction; message on the request provides per-request natural language overrides. When both provide conflicting direction, message takes precedence as the most specific instruction.

Transformation model

build_creative follows a manifest-in, manifest-out model:
  • Input: Creative manifest (can be minimal or complete — everything lives in assets)
  • Process: Transform/generate based on message and manifest content
  • Output: Target creative manifest ready for preview or sync (brief carries forward)

Pure generation vs transformation

  • Pure Generation: Provide minimal creative_manifest with just the format_id, catalog assets (if the format renders catalog items), and any required seed assets. The creative agent generates output assets from scratch using message as guidance.
  • Transformation: Provide complete creative_manifest with all existing assets. The creative agent adapts existing assets to the target format, optionally following guidance in message.

Integration with other tasks

  1. build_creative → Generates manifest (optionally with inline preview via include_preview)
  2. preview_creative → Renders the manifest separately (see preview_creative)
  3. sync_creatives → Traffics the finalized manifest
Use include_preview: true to combine build and preview into one call. If the agent doesn’t support it, the response simply omits the preview field — fall back to a separate preview_creative call. Either way, the preview content fields (previews, interactive_url, expires_at) are the same. This separation allows you to:
  • Build once, preview multiple times with different contexts
  • Iterate on build without re-syncing
  • Preview before committing to traffic

Iterative refinement

build_creative supports multi-turn iteration without a mode flag. The presence and combination of fields determines the operation:
  • Generation: message + minimal creative_manifest (empty or seed assets) + target_format_id
  • Transformation: full creative_manifest + message + target_format_id
  • Library retrieval: creative_id + target_format_id + optional macro_values
  • Refinement: previous output as creative_manifest + message with changes
To refine, pass the previous response’s creative_manifest back as input with a new message. Alternatively, update the brief asset (assets.brief) to change the creative direction — the brief is the buyer-owned source of truth for what the creative should be.
{
  "$schema": "/schemas/media-buy/build-creative-request.json",
  "message": "Make the headline bolder and increase the contrast on the CTA button",
  "target_format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_300x250_generative"
  },
  "creative_manifest": {
    "format_id": {
      "agent_url": "https://creative.adcontextprotocol.org",
      "id": "display_300x250"
    },
    "assets": {
      "banner_image": {
        "asset_type": "image",
        "url": "https://cdn.creative-agent.com/generated/banner_12345.png",
        "width": 300,
        "height": 250
      },
      "headline": {
        "asset_type": "text",
        "content": "50% Off Winter Sale"
      },
      "clickthrough_url": {
        "asset_type": "url",
        "url": "https://mybrand.com/winter-sale"
      }
    }
  }
}

Error codes

CodeDescription
FORMAT_NOT_SUPPORTEDThe target_format_id is not supported by this creative agent
INVALID_MANIFESTThe creative_manifest is malformed or missing required assets for the target format
CREATIVE_NOT_FOUNDThe creative_id does not exist in the agent’s library (or in the specified concept_id)
COMPLIANCE_UNSATISFIEDA required disclosure from the brief cannot be rendered in the target format (e.g., format does not support the required disclosure position)