Documentation Index
Fetch the complete documentation index at: https://adcp-docs-ja.pier1.co.jp/llms.txt
Use this file to discover all available pages before exploring further.
1つ以上のブランド/オペレーターのペアに対してセラーと広告主アカウントを同期します。セラーはアカウントをプロビジョニングまたはリンクし、アカウントごとのステータスとセットアップ手順を返します。ブランドは domain + オプションの brand_id を含む brand オブジェクトで識別され、/.well-known/brand.json 経由で解決されます。
sync_accounts はすべてのセラープロトコルで使用されます: メディアバイエージェント、シグナルエージェント、ガバナンスエージェント、クリエイティブエージェント。バイヤーの意図を宣言し、セラーが内部でアカウントをプロビジョニングまたはリンクします。暗黙的アカウント(require_operator_auth: false)の場合、後続のリクエストには自然キー(brand + operator)を使用します。明示的アカウント(require_operator_auth: true)の場合、セラーが割り当てたアカウント ID を list_accounts で探索します。暗黙的アカウントのサンドボックスには、アカウントエントリに sandbox: true を含める — セラーは実際の支出なしでテストアカウントをプロビジョニングします。明示的アカウントの場合、サンドボックスアカウントは list_accounts で探索する既存のテストアカウントです。
応答時間: 約1秒。アカウントプロビジョニングは同期的; 与信審査や法的レビューには人間の対応が必要な場合がある(setup.url 付きの status: "pending_approval" で示されます)。
リクエストスキーマ: /schemas/v3/account/sync-accounts-request.json
レスポンススキーマ: /schemas/v3/account/sync-accounts-response.json
クイックスタート
単一の広告主アカウントを同期して結果のステータスを確認します。
import { testAgent } from "@adcp/client/testing";
import { SyncAccountsResponseSchema } from "@adcp/client";
const result = await testAgent.syncAccounts({
accounts: [
{
brand: { domain: "acme-corp.com" },
operator: "acme-corp.com",
billing: "operator",
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
const validated = SyncAccountsResponseSchema.parse(result.data);
if ("errors" in validated && validated.errors) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}
for (const account of validated.accounts) {
console.log(`${account.brand.domain}: ${account.status}`);
if (account.status === "pending_approval" && account.setup?.url) {
console.log(` Complete setup at: ${account.setup.url}`);
}
}
リクエストパラメーター
| パラメーター | 型 | 必須 | 説明 |
|---|
accounts | array | Yes | 同期するアカウントエントリの配列(下記参照)。 |
delete_missing | boolean | No | true の場合、このエージェントが以前に同期したがこのリクエストに含まれないアカウントを非アクティブ化します。認証済みエージェントにスコープされます。デフォルト: false。 |
dry_run | boolean | No | true の場合、変更を適用せずにプレビューします。デフォルト: false。 |
push_notification_config | object | No | アカウントステータス変更時の非同期通知用 Webhook(例: pending_approval から active への遷移)。 |
アカウントエントリのフィールド:
| フィールド | 型 | 必須 | 説明 |
|---|
brand | object | Yes | 広告主を識別するブランド参照。domain(brand.json がホストされているハウスドメイン)とオプションの brand_id(マルチブランドハウス用)を含みます。brand-ref を参照。 |
operator | string | Yes | ブランドの代理で活動するエンティティのドメイン(例: pinnacle-media.com)。ブランドが直接運営する場合はブランドのドメインに設定。brand.json の authorized_operators に対して検証されます。 |
billing | string | Yes | 請求先: operator または agent。セラーが受け入れる内容を確認するには get_adcp_capabilities の supported_billing を確認します。セラーはこの請求モデルを受け入れるかリクエストを拒否しなければなりません。 |
payment_terms | string | No | このアカウントの支払い条件: net_15、net_30、net_45、net_60、net_90、prepay。セラーはこれらの条件を受け入れるかアカウントを拒否しなければなりません — 条件は暗黙的に変更されない。省略時、セラーはデフォルト条件を適用します。 |
sandbox | boolean | No | true の場合、実際のプラットフォーム呼び出しや請求なしでサンドボックスアカウントを設定します。暗黙的アカウント(require_operator_auth: false)にのみ適用。明示的アカウントの場合、サンドボックスアカウントは list_accounts で探索する既存のテストアカウント。 |
governance_agents | array | No | このアカウントのガバナンスエージェントエンドポイント。存在する場合、セラーはメディアバイリクエストを確認する前にこれらのエージェントをガバナンス承認のために呼び出さなければなりません。各エントリには url、authentication、エージェントが処理する検証カテゴリをスコープするオプションの categories を含みます。資格情報のローテーションには、更新された authentication で sync_accounts を再呼び出しします。 |
自然キー: タプル (brand, operator, sandbox) がアカウント関係を一意に識別します。{brand: {domain: "acme-corp.com"}, operator: "acme-corp.com"}(直接)は {brand: {domain: "acme-corp.com"}, operator: "pinnacle-media.com"}(代理店経由)とは異なるアカウント。sandbox: true を追加すると、同じブランド/オペレーターのペアに対してサンドボックスアカウントがプロビジョニングされる — 実際のプラットフォーム呼び出しや請求なし。
レスポンス
成功レスポンス:
アカウントごとの結果を含む accounts 配列を返します。操作が成功しても、個々のアカウントが保留中、拒否、または失敗することがあります。
エラーレスポンス:
errors — 操作レベルのエラーの配列(認証失敗、サービス利用不可)。accounts 配列は含まれない。
注: レスポンスは判別共用体を使用 — accounts または errors のいずれか一方のみ、両方は含まれない。
アカウントごとのフィールド:
| フィールド | 説明 |
|---|
brand | リクエストからエコーされます。domain とオプションの brand_id を含むオブジェクト。 |
operator | リクエストからエコーされます。 |
name | アカウントのセラー表示名。 |
action | 実行された内容: created、updated、unchanged、failed。 |
status | アカウントの現在の状態(アカウントステータス を参照)。 |
billing | 適用された請求モデル。リクエストの値と一致します。 |
account_scope | セラーがアカウントをスコープした方法: operator(このオペレーターのブランド間で共有)、brand(このブランドのオペレーター間で共有)、operator_brand(このオペレーター+ブランドのペア専用)、agent(エージェントのデフォルトアカウント)。アカウントスコープ を参照。 |
setup | status: "pending_approval" の場合に存在。与信または法的セットアップ完了の url、必要な内容を説明する message、オプションの expires_at を含みます。 |
rate_card | セラーが割り当てたレートカード識別子(該当する場合)。 |
payment_terms | このアカウントで合意した支払い条件: net_15、net_30、net_45、net_60、net_90、prepay。アカウントがアクティブな場合、すべての請求書の拘束力を持つ条件。 |
credit_limit | 最大未払い残高({amount, currency})。 |
errors | アカウントごとのエラー(action: "failed" の場合のみ存在)。 |
warnings | 非致命的な通知。 |
governance_agents | リクエストで提供された場合にエコーされるガバナンスエージェントエンドポイント。 |
sandbox | これがサンドボックスアカウントかどうか、リクエストからエコーされます。暗黙的アカウントにのみ存在。 |
アカウントステータス
| ステータス | 意味 | 次のステップ |
|---|
active | 使用準備完了 | プロトコル操作で アカウント参照 を使用 |
pending_approval | セラーがレビュー中 | 与信または法的プロセスを完了するために人間が setup.url にアクセスする必要がある場合があります。更新確認のため list_accounts をポーリング。 |
rejected | セラーがリクエストを拒否 | warnings の拒否理由を確認し、調整して再試行するかセラーに連絡 |
payment_required | 与信限度額超過または残高不足 | 資金追加または与信限度額引き上げ。他のアカウントに支出を振り分ける。 |
suspended | アクティブだったが現在停止中 | セラーに連絡して解決 |
closed | アクティブだったが現在終了 | — |
非同期通知
push_notification_config が提供され、セラーが pending_approval を返した場合、アカウントステータスが変更されると(例: 承認 → active、拒否 → rejected)、セラーはWebhook通知を送信します。
通知ペイロードには (brand, operator) の自然キーが含まれるため、バイヤーは元の同期リクエストと関連付けられます。明示的アカウント(require_operator_auth: true)の場合、プロビジョニング後にセラーが割り当てた account_id も通知に含まれます。
{
"brand": { "domain": "nova-brands.com", "brand_id": "glow" },
"operator": "pinnacle-media.com",
"status": "active",
"account_id": "acc_glow_001"
}
バイヤーが push_notification_config を提供しなかった場合、ステータス変更を確認するために list_accounts をポーリングします。
一般的なシナリオ
複数のブランドを同期する代理店
import { testAgent } from "@adcp/client/testing";
import { SyncAccountsResponseSchema } from "@adcp/client";
const result = await testAgent.syncAccounts({
accounts: [
{
brand: { domain: "nova-brands.com", brand_id: "spark" },
operator: "pinnacle-media.com",
billing: "operator",
},
{
brand: { domain: "nova-brands.com", brand_id: "glow" },
operator: "pinnacle-media.com",
billing: "operator",
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
const validated = SyncAccountsResponseSchema.parse(result.data);
if ("errors" in validated && validated.errors) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}
for (const account of validated.accounts) {
if (account.status === "active") {
console.log(`Ready: ${account.brand.domain}/${account.brand.brand_id} → ${account.status}`);
} else if (account.status === "pending_approval") {
console.log(`Setup required for ${account.brand.brand_id}: ${account.setup?.url}`);
// アクティブになるまで list_accounts をポーリング
}
}
ブランドによる直接購入
import { testAgent } from "@adcp/client/testing";
import { SyncAccountsResponseSchema } from "@adcp/client";
const result = await testAgent.syncAccounts({
accounts: [
{
brand: { domain: "acme-corp.com" },
operator: "acme-corp.com",
billing: "operator",
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
const validated = SyncAccountsResponseSchema.parse(result.data);
if ("errors" in validated && validated.errors) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}
const account = validated.accounts[0];
if (account.status === "active") {
console.log(`Ready: ${account.brand.domain} — ${account.status}`);
} else if (account.status === "pending_approval") {
console.log(`Setup required: ${account.setup?.url}`);
// アクティブになるまで list_accounts をポーリング
}
拒否の処理
セラーがリクエストを拒否した場合、アカウントエントリは status: "rejected" を持ちます。
import { testAgent } from "@adcp/client/testing";
import { SyncAccountsResponseSchema } from "@adcp/client";
const result = await testAgent.syncAccounts({
accounts: [
{
brand: { domain: "acme-corp.com", brand_id: "clearance" },
operator: "acme-corp.com",
},
],
});
if (!result.success) {
throw new Error(`Request failed: ${result.error}`);
}
const validated = SyncAccountsResponseSchema.parse(result.data);
if ("errors" in validated && validated.errors) {
throw new Error(`Operation failed: ${JSON.stringify(validated.errors)}`);
}
for (const account of validated.accounts) {
if (account.status === "rejected") {
console.log("Account request was rejected");
if (account.warnings?.length) {
console.log(`Reason: ${account.warnings.join(", ")}`);
}
}
}
エラーハンドリング
| エラーコード | 説明 | 解決策 |
|---|
ACCOUNT_NOT_FOUND | 参照されたアカウントが存在しないか、アクセスできない | account_id を確認するか、再同期する |
BILLING_NOT_SUPPORTED | セラーがリクエストされた請求モデルをサポートしていない | supported_billing の get_adcp_capabilities を確認し、調整または billing を省略 |
PAYMENT_TERMS_NOT_SUPPORTED | セラーがリクエストされた支払い条件を受け入れない | セラーのデフォルトを受け入れるため payment_terms を省略するか、オフラインで交渉 |
PAYMENT_REQUIRED | アカウントが与信限度額に達した | 資金を追加するか、別のアカウントに振り分ける |
ACCOUNT_SUSPENDED | アカウントが停止されている | セラーに連絡して解決 |
BRAND_REQUIRED | ブランド参照なしで請求可能な操作が試みられた | リクエストに brand を含める |
次のステップ