Skip to main content
メディアバイ向けにクリエイティブアセットをアップロード・管理します。バルクアップロード、アップサート、生成クリエイティブに対応しています。 応答時間: 即時〜数日(completed または、承認に数時間〜数日かかる場合は submitted を返す) Request Schema: /schemas/v2/media-buy/sync-creatives-request.json Response Schema: /schemas/v2/media-buy/sync-creatives-response.json

クイックスタート

クリエイティブアセットをアップロード:
import { testAgent } from "@adcp/client/testing";
import { SyncCreativesResponseSchema } from "@adcp/client";

const result = await testAgent.syncCreatives({
  creatives: [
    {
      creative_id: "creative_video_001",
      name: "Summer Sale 30s",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "video_standard_30s",
      },
      assets: {
        video: {
          url: "https://cdn.example.com/summer-sale-30s.mp4",
          width: 1920,
          height: 1080,
          duration_ms: 30000,
        },
      },
    },
  ],
});

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

// Validate response against schema
const validated = SyncCreativesResponseSchema.parse(result.data);

// Check for operation-level errors first (discriminated union)
if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("creatives" in validated) {
  console.log(`Synced ${validated.creatives.length} creatives`);
}
Note: 承認が必要な場合、レスポンスは status: "submitted"task_id を返します。扱い方は Async Approval Workflow を参照してください。

リクエストパラメーター

ParameterTypeRequiredDescription
creativesCreative[]Yesアップロード/更新するクリエイティブ(最大 100 件)
creative_idsstring[]No同期対象を特定の creative_id に限定するオプションフィルター。指定したものだけが影響を受け、他は変更されない。部分更新やエラー再試行に便利。
assignmentsobjectNocreative_id をキー、package_id 配列を値にした割り当てマップ(バルク割り当て用)
dry_runbooleanNotrue の場合、適用せずに変更内容をプレビュー(デフォルト: false)
validation_modestringNo検証の厳しさ: "strict"(デフォルト)または "lenient"
delete_missingbooleanNotrue の場合、この同期に含まれないクリエイティブをアーカイブ(デフォルト: false)。アクティブで一時停止していないパッケージに割り当て済みのものは削除不可。

Creative オブジェクト

FieldTypeRequiredDescription
creative_idstringYesクリエイティブの一意識別子
namestringYes人が読める名前
format_idFormatIdYesフォーマット指定(agent_urlid を持つ構造体)
assetsobjectYesロール名をキーにしたアセット(例: {video: {...}}
tagsstring[]No検索用タグ

アセット構造

アセットはロール名をキーに持ち、各ロールにアセット詳細を含みます。
test=false
{
  "assets": {
    "video": {
      "url": "https://cdn.example.com/video.mp4",
      "width": 1920,
      "height": 1080,
      "duration_ms": 30000
    },
    "thumbnail": {
      "url": "https://cdn.example.com/thumb.jpg",
      "width": 300,
      "height": 250
    }
  }
}

Assignments 構造

割り当てはリクエストレベルで、creative_id を package_id にマッピングします。
test=false
{
  "assignments": {
    "creative_video_001": ["pkg_premium", "pkg_standard"],
    "creative_display_002": ["pkg_standard"]
  }
}

レスポンス

成功レスポンス:
  • creatives - 処理した各クリエイティブの結果(成功/失敗どちらも含む)
  • dry_run - ドライランかどうかを示すブール値(任意)
エラーレスポンス:
  • errors - 認証失敗・サービス不通などのオペレーションエラー配列
Note: レスポンスは判別可能なユニオン。成功フィールドか errors のどちらかのみ返される(両方はない)。個別クリエイティブのエラーは action: "failed" のとき各クリエイティブの errors 配列に含まれる。 成功レスポンスの各クリエイティブに含まれるもの:
  • リクエストの全フィールド
  • platform_id - プラットフォーム内部 ID(actionfailed 以外の場合)
  • action - 実施内容: created, updated, unchanged, failed, deleted
  • errors - エラーメッセージ配列(action: "failed" の場合のみ)
  • warnings - 非致命的な警告配列(任意)
全フィールドはスキーマ参照: sync-creatives-response.json

主なシナリオ

バルクアップロード

複数クリエイティブを一括アップロード:
import { testAgent } from "@adcp/client/testing";
import { SyncCreativesResponseSchema } from "@adcp/client";

const result = await testAgent.syncCreatives({
  creatives: [
    {
      creative_id: "creative_display_001",
      name: "Summer Sale Banner 300x250",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "display_300x250",
      },
      assets: {
        image: {
          url: "https://cdn.example.com/banner-300x250.jpg",
          width: 300,
          height: 250,
        },
      },
    },
    {
      creative_id: "creative_video_002",
      name: "Product Demo 15s",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "video_standard_15s",
      },
      assets: {
        video: {
          url: "https://cdn.example.com/demo-15s.mp4",
          width: 1920,
          height: 1080,
          duration_ms: 15000,
        },
      },
    },
    {
      creative_id: "creative_display_002",
      name: "Summer Sale Banner 728x90",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "display_728x90",
      },
      assets: {
        image: {
          url: "https://cdn.example.com/banner-728x90.jpg",
          width: 728,
          height: 90,
        },
      },
    },
  ],
});

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

const validated = SyncCreativesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("creatives" in validated) {
  console.log(`Successfully synced ${validated.creatives.length} creatives`);
  validated.creatives.forEach((creative) => {
    console.log(`  ${creative.name}: ${creative.platform_creative_id}`);
  });
}

生成クリエイティブ

クリエイティブエージェントを使ってブランドマニフェストから生成します。ワークフローの詳細は Generative Creatives guide を参照してください。
import { testAgent } from "@adcp/client/testing";
import { SyncCreativesResponseSchema } from "@adcp/client";

const result = await testAgent.syncCreatives({
  creatives: [
    {
      creative_id: "creative_gen_001",
      name: "AI-Generated Summer Banner",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "display_300x250",
      },
      assets: {
        manifest: {
          url: "https://cdn.example.com/brand-manifest.json",
        },
      },
    },
  ],
});

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

const validated = SyncCreativesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors) {
  throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}

if ("creatives" in validated) {
  console.log(
    "Generative creative synced:",
    validated.creatives[0].creative_id
  );
}

ドライラン検証

アップロードせずに設定を検証:
import { testAgent } from "@adcp/client/testing";
import { SyncCreativesResponseSchema } from "@adcp/client";

const result = await testAgent.syncCreatives({
  dry_run: true,
  creatives: [
    {
      creative_id: "creative_test_001",
      name: "Test Creative",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "video_standard_30s",
      },
      assets: {
        video: {
          url: "https://cdn.example.com/test-video.mp4",
          width: 1920,
          height: 1080,
          duration_ms: 30000,
        },
      },
    },
  ],
});

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

const validated = SyncCreativesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors && validated.errors.length > 0) {
  console.log("Validation errors found:");
  validated.errors.forEach((error) => console.log(`  - ${error.message}`));
} else {
  console.log("Validation passed! Ready to sync.");
}

creative_ids フィルターで範囲を限定して更新

大規模ライブラリから特定クリエイティブだけを更新し、他は変更しない:
import { testAgent } from "@adcp/client/testing";
import { SyncCreativesResponseSchema } from "@adcp/client";

// Update just 2 creatives out of 100+ in the library
const result = await testAgent.syncCreatives({
  creative_ids: ["creative_video_001", "creative_display_001"],
  creatives: [
    {
      creative_id: "creative_video_001",
      name: "Summer Sale 30s - Updated",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "video_standard_30s",
      },
      assets: {
        video: {
          url: "https://cdn.example.com/updated-video.mp4",
          width: 1920,
          height: 1080,
          duration_ms: 30000,
        },
      },
    },
    {
      creative_id: "creative_display_001",
      name: "Summer Sale Banner - Updated",
      format_id: {
        agent_url: "https://creative.adcontextprotocol.org",
        id: "display_300x250",
      },
      assets: {
        image: {
          url: "https://cdn.example.com/updated-banner.jpg",
          width: 300,
          height: 250,
        },
      },
    },
  ],
});

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

const validated = SyncCreativesResponseSchema.parse(result.data);

if ("errors" in validated && validated.errors) {
  throw new Error(`Update failed: ${JSON.stringify(validated.errors)}`);
}

if ("creatives" in validated) {
  console.log(
    `Updated ${validated.creatives.length} creatives, others untouched`
  );
}
creative_ids フィルターを使う理由:
  • 範囲限定更新: ライブラリに 100+ 件あっても指定したものだけ変更
  • エラー復旧: バルク同期で失敗したクリエイティブだけ再試行
  • パフォーマンス: 対象が明確ならパブリッシャー側で処理最適化しやすい
  • 安全性: 明示的な対象指定で意図しない変更を防ぐ

非同期承認ワークフロー

ブランドセーフティ/ポリシー審査が必要な場合、初回レスポンスは status: "submitted"。Webhook かポーリングで結果を取得します。 最終レスポンスは status: "completed" でクリエイティブごとの結果を含みます:
  • 承認されたクリエイティブ: action: "created"platform_id
  • 拒否されたクリエイティブ: action: "failed"errors 配列に詳細
オペレーションステータス(completed)は審査完了を示し、各クリエイティブの結果は action フィールドにあります。 オペレーションレベルの失敗(認証エラー、サービス不可など)の場合、creatives 配列なしで status: "failed" を返します。 参照: Webhook 設定は Webhooks を参照。

同期モード

Upsert(デフォルト)

  • creative_id をキーに新規作成または更新
  • パッケージ割り当てはマージ(加算)
  • 指定フィールドだけ更新し、他は保持
  • creative_ids フィルターで対象を限定可能

Dry Run

  • 実際に変更せずリクエストを検証
  • エラーと警告を返却
  • アセット処理やクリエイティブ作成は行わない
  • 事前チェック用途に利用

エラーハンドリング

Error CodeDescriptionResolution
INVALID_FORMATプロダクトでサポートされていないフォーマットlist_creative_formats で対応フォーマットを確認
ASSET_PROCESSING_FAILEDアセットファイルが壊れている/不正コーデック・寸法・尺などフォーマット要件を満たしているか確認
PACKAGE_NOT_FOUNDメディアバイ内に該当パッケージ ID が存在しないcreate_media_buy のレスポンスで package_id を確認
BRAND_SAFETY_VIOLATIONブランドセーフティ審査に失敗パブリッシャーのブランドセーフティ基準に照らして内容を見直す
FORMAT_MISMATCHアセットがフォーマット要件に一致しないアセット種別・仕様がフォーマット定義に合致しているか確認
CREATIVE_IN_ACTIVE_DELIVERYアクティブで一時停止していないパッケージに割り当て済み(更新や delete_missing での削除をブロック)先にパッケージを一時停止し、update_media_buy で割り当て解除、または別 creative_id で新規作成

ベストプラクティス

  1. アップサートを使う - 同じ creative_id で既存を更新し重複を防ぐ(ただしアクティブ配信中は更新不可、#7 を参照)。
  2. 先に検証する - dry_run: true で本番アップロード前にエラーを検出し、帯域と処理時間を節約。
  3. 割り当てはまとめて送る - 1 回の同期にすべてのパッケージ割り当てを含め、更新間の競合を防ぐ。
  4. CDN ホストのアセットを使う - 公開 CDN URL で高速処理。プラットフォームが直接取得でき、プロキシ遅延を回避。
  5. ブランドマニフェストを検証 - 生成クリエイティブではマニフェストスキーマを事前確認し、処理失敗を防止。
  6. フォーマット対応を確認 - アップロード前に list_creative_formats でプロダクトがフォーマットをサポートするか確認。
  7. アクティブ配信の保護 - アクティブで一時停止していないパッケージに割り当てたクリエイティブは delete_missing で削除・更新不可。先にパッケージを一時停止し解除するか、新しい creative_id で作成。

次のステップ