Skip to main content
Discover creative formats supported by a creative agent. Returns full format specifications including asset requirements and technical constraints. Response Time: ~1 second (database lookup) Authentication: None required (public endpoint for format discovery) Request Schema: /schemas/v3/creative/list-creative-formats-request.json Response Schema: /schemas/v3/creative/list-creative-formats-response.json

Behavior by agent type

Any agent implementing the Creative Protocol can serve list_creative_formats. The response varies based on what the agent does: Dedicated creative agents (like https://creative.adcontextprotocol.org):
  • Return authoritative format definitions they own
  • Provide full specifications for building and validating creatives
Sales agents implementing only Media Buy Protocol (like https://test-agent.adcontextprotocol.org):
  • Return only formats used by active products
  • Reference creative agents for authoritative format specifications
  • Filter results based on what’s actually purchasable
Sales agents implementing both protocols — return their own self-hosted format definitions alongside referenced formats. See Creative capabilities on sales agents. See list_creative_formats (Sales Agent) for sales agent-specific behavior.

Request Parameters

ParameterTypeRequiredDescription
format_idsFormatID[]NoReturn only specific format IDs (from get_products response)
typestringNo(deprecated) Filter by type: audio, video, display, dooh. Prefer asset_types filter instead.
asset_typesstring[]NoFilter to formats accepting these asset types: image, video, audio, text, html, javascript, url. Uses OR logic. Recommended over type filter.
max_widthintegerNoMaximum width in pixels (inclusive) - matches if ANY render fits
max_heightintegerNoMaximum height in pixels (inclusive) - matches if ANY render fits
min_widthintegerNoMinimum width in pixels (inclusive)
min_heightintegerNoMinimum height in pixels (inclusive)
is_responsivebooleanNoFilter for responsive formats (adapt to container size)
name_searchstringNoSearch formats by name (case-insensitive partial match)
wcag_levelstringNoFilter to formats meeting at least this WCAG level: A, AA, AAA. See Accessibility.
disclosure_positionsstring[]NoFilter to formats that support all of these disclosure positions. Matches against disclosure_capabilities when present, otherwise falls back to supported_disclosure_positions.
disclosure_persistencestring[]NoFilter to formats whose disclosure_capabilities include all of these persistence modes on at least one position. Values: continuous, initial, flexible.
output_format_idsFormatID[]NoFilter to formats whose output_format_ids includes any of these. Returns formats that can produce these outputs — inspect their input_format_ids to see what inputs they accept.
input_format_idsFormatID[]NoFilter to formats whose input_format_ids includes any of these. Returns formats that accept these creatives as input — inspect their output_format_ids to see what they can produce.
paginationobjectNoPagination: max_results (1-100, default 50) and cursor (opaque cursor from previous response)

Multi-Render Dimension Filtering

Formats may produce multiple rendered pieces (e.g., video + companion banner). Dimension filters use “any render fits” logic:
  • max_width: 300, max_height: 250 - Returns formats where AT LEAST ONE render is ≤ 300×250
  • Use case: “Find formats that can render into my 300×250 ad slot”
  • Example: Format with primary video (1920×1080) + companion banner (300×250) matches because companion fits

Response

FieldDescription
formatsArray of full format definitions (format_id, name, assets, renders). The type field is deprecated and may be omitted.
creative_agentsOptional array of other creative agents providing additional formats
See Format schema for complete format object structure.

Recursive Discovery

Creative agents may reference other creative agents that provide additional formats:
{
  "creative_agents": [{
    "agent_url": "https://creative.adcontextprotocol.org",
    "agent_name": "AdCP Reference Creative Agent",
    "capabilities": ["validation", "assembly", "preview"]
  }]
}
Buyers can recursively query creative_agents. Track visited URLs to avoid infinite loops.

Catalog requirements

Formats declare catalog needs as catalog asset types in their assets array. This tells buyers which catalogs to sync before submitting creatives for that format.
{
  "format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "product_carousel_4x"
  },
  "name": "Product Carousel (4 items)",
  "assets": [
    {
      "item_type": "individual",
      "asset_id": "product_catalog",
      "asset_type": "catalog",
      "required": true,
      "requirements": {
        "catalog_type": "product",
        "min_items": 4,
        "required_fields": ["name", "price", "image_url"]
      }
    }
  ]
}
Catalog assets use asset_type: "catalog" with a requirements object containing:
FieldTypeDescription
catalog_typestringRequired. The catalog type (e.g., product, store, job)
min_itemsintegerMinimum items the catalog must contain
max_itemsintegerMaximum items the format can render. Items beyond this limit are ignored
required_fieldsstring[]Fields that must be present on every item
feed_formatsstring[]Accepted feed formats (e.g., google_merchant_center, linkedin_jobs)
When catalog assets are present, buyers should sync the required catalogs via sync_catalogs before submitting creatives. See Catalogs for the full lifecycle.

Common Scenarios

Get Specs for Product Format IDs

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// Get full specs for formats returned by get_products
const result = await testAgent.listCreativeFormats({
  format_ids: [
    {
      agent_url: 'https://creative.adcontextprotocol.org',
      id: 'video_15s_hosted'
    },
    {
      agent_url: 'https://creative.adcontextprotocol.org',
      id: 'display_300x250'
    }
  ]
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

// Validate response against schema
const validated = ListCreativeFormatsResponseSchema.parse(result.data);
validated.formats.forEach(format => {
  console.log(`${format.name}: ${format.assets.length} assets required`);
});

Find Formats by Asset Types

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// Find formats that accept images and text
const result = await testAgent.listCreativeFormats({
  asset_types: ['image', 'text']
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
console.log(`Found ${validated.formats.length} formats`);

// Examine asset requirements
validated.formats.forEach(format => {
  console.log(`\n${format.name}:`);
  format.assets.forEach(asset => {
    const label = asset.asset_role ?? asset.asset_id;
    console.log(`  - ${label}: ${asset.asset_type}`);
  });
});

Find Third-Party Tag Formats

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// Find formats that accept JavaScript or HTML tags
const result = await testAgent.listCreativeFormats({
  asset_types: ['javascript', 'html'],
  max_width: 970,
  max_height: 250
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
console.log(`Found ${validated.formats.length} third-party tag formats ≤ 970×250`);

validated.formats.forEach(format => {
  const renders = format.renders || [];
  if (renders.length > 0) {
    const dims = renders[0].dimensions;
    console.log(`${format.name}: ${dims.width}×${dims.height}`);
  }
});

Filter by Type and Dimensions

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// Find video formats
const result = await testAgent.listCreativeFormats({
  type: 'video'
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
console.log(`Found ${validated.formats.length} video formats`);

validated.formats.forEach(format => {
  const assetTypes = format.assets.map(a => a.asset_type).join(', ');
  console.log(`${format.name}: ${assetTypes}`);
});

Search by Name

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// Find mobile-optimized formats
const result = await testAgent.listCreativeFormats({
  name_search: 'mobile'
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
console.log(`Found ${validated.formats.length} mobile formats`);

validated.formats.forEach(format => {
  console.log(`- ${format.name} (${format.type})`);
});

Responsive Formats

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// Find formats that adapt to container size
const result = await testAgent.listCreativeFormats({
  is_responsive: true,
  type: 'display'
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
console.log(`Found ${validated.formats.length} responsive display formats`);

validated.formats.forEach(format => {
  console.log(`${format.name}: Adapts to container`);
});

Discover Build Capabilities

Some formats declare the output formats they can produce via output_format_ids. A creative builder (like a multi-publisher template tool) may accept one asset group and produce many publisher-specific formats. A format transformer may accept an existing creative and reformat it. The format schema expresses both sides of the relationship:
  • input_format_ids — existing creative formats this format accepts as input
  • output_format_ids — concrete output formats this format can produce
These filters are ANDed — a format must match all specified filters. Within each filter, matching is OR (any ID in the array matches). A bare format ID (no dimension parameters) matches all parameterized variants of that format; a parameterized ID is an exact match. Note: asset_types and these filters target different things. A format that takes only creative manifests as input will have no entries in its assets array, so combining asset_types with input_format_ids will typically return no results. Serve-time dynamic creative (DCO platforms that render from data feeds at ad serving time) is not expressed through these fields — those platforms describe their inputs via assets and their output via the format itself.

Given output formats I need, what inputs are accepted?

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// I need portrait video — what can generate it?
const result = await testAgent.listCreativeFormats({
  output_format_ids: [
    { agent_url: 'https://creative.adcontextprotocol.org', id: 'video_9x16_15s' }
  ]
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
validated.formats.forEach(format => {
  const inputs = format.input_format_ids?.map(f => f.id) ?? ['(from brief)'];
  console.log(`${format.name} accepts: ${inputs.join(', ')}`);
});

Given an input format I have, what outputs can it produce?

import { testAgent } from '@adcp/client/testing';
import { ListCreativeFormatsResponseSchema } from '@adcp/client';

// I have a landscape 16:9 video — what can I transform it into?
const result = await testAgent.listCreativeFormats({
  input_format_ids: [
    { agent_url: 'https://creative.adcontextprotocol.org', id: 'video_16x9_30s' }
  ]
});

if (!result.success) {
  throw new Error(`Request failed: ${result.error}`);
}

const validated = ListCreativeFormatsResponseSchema.parse(result.data);
validated.formats.forEach(format => {
  const outputs = format.output_format_ids?.map(f => f.id) ?? [];
  console.log(`${format.name}${outputs.join(', ')}`);
});

Format Structure

Each format includes:
FieldDescription
format_idStructured identifier with agent_url and id
nameHuman-readable format name
type(deprecated) Format type (audio, video, display, dooh). Use asset_types filter instead.
assetsArray of all assets with required boolean indicating mandatory vs optional
rendersArray of rendered output pieces (dimensions, role)
input_format_idsCreative formats this format accepts as input manifests (omitted for formats that work from raw assets)
output_format_idsOutput formats this format can produce (omitted for formats that produce a single fixed output)

Asset Roles

Common asset roles help identify asset purposes:
  • hero_image - Primary visual
  • hero_video - Primary video content
  • logo - Brand logo
  • headline - Primary text
  • body_text - Secondary text
  • call_to_action - CTA button text

Asset Types Filter Logic

The asset_types parameter uses OR logic - formats matching ANY specified asset type are returned. Example: asset_types: ['html', 'javascript', 'image']
  • Returns formats accepting html OR javascript OR image
  • Use case: “Show me formats I can use with any of my available asset types”
To find formats requiring specific combinations, filter results after retrieval:
test=false
// Find formats requiring BOTH image AND text
const result = await agent.listCreativeFormats();
const imageAndText = result.formats.filter(format => {
  const assetTypes = format.assets.map(a => a.asset_type);
  return assetTypes.includes('image') && assetTypes.includes('text');
});

Dimension Filtering for Multi-Render Formats

Some formats produce multiple rendered pieces:
  • Video with companion banner - Primary video (1920×1080) + banner (300×250)
  • Adaptive displays - Desktop (728×90) + mobile (320×50)
  • DOOH installations - Multiple screens with different dimensions
Dimension filters match if at least one render fits:
test=false
// Find formats with ANY render ≤ 300×250
const result = await agent.listCreativeFormats({
  max_width: 300,
  max_height: 250
});

// Returns formats where at least one render fits 300×250 slot
// May also include larger companion pieces

Implementation Requirements

When implementing list_creative_formats for a creative agent:
  1. Return authoritative formats - Include full specifications for formats you define
  2. Reference other agents - Use creative_agents to delegate to other creative agents
  3. Include capabilities - Indicate what operations you support (validation, assembly, generation, preview)
  4. Support filtering - Implement filter parameters (type, asset_types, dimensions, etc.)

Error Handling

Error CodeDescriptionResolution
FORMAT_NOT_FOUNDRequested format_id doesn’t existVerify format_id from get_products response
INVALID_REQUESTInvalid filter parametersCheck parameter types and values
AGENT_NOT_FOUNDReferenced creative agent unavailableFormat may be from deprecated agent

Best Practices

1. Use format_ids Parameter Most efficient way to get specs for formats returned by get_products. 2. Cache Format Specifications Format specs rarely change - cache by format_id to reduce API calls. 3. Filter by Asset Types for Third-Party Tags Search for asset_types: ['html'] or ['javascript'] to find tag-accepting formats. 4. Consider Multi-Render Formats Check renders array length - some formats produce multiple pieces requiring multiple placements. 5. Validate Asset Requirements Ensure your creative assets match format specifications before building creatives.

Next Steps

After discovering formats:
  1. Build Creatives: Use build_creative to assemble assets into format
  2. Preview: Use preview_creative to see visual output
  3. Validate: Use sync_creatives with dry_run: true
  4. Upload: Use sync_creatives to upload to an agent-hosted creative library

Learn More