> ## 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.

# validate_property_delivery

> validate_property_delivery は AdCP において配信記録をプロパティリストに照らしてコンプライアンスとサプライパス認可を確認します。

# validate\_property\_delivery

<Info>
  **AdCP 3.0 提案** - このタスクは AdCP 3.0 向けに開発中です。
</Info>

配信記録をプロパティリストに照らして準拠性を検証します。次の 2 点を確認します:

1. **プロパティ準拠**: インプレッションはリスト内プロパティに配信されたか？
2. **サプライパス認可**: セールスエージェントにその在庫を売る権限があったか？

## Use Cases

* **ポストキャンペーン検証**: インプレッションが準拠プロパティに配信されたか確認
* **サプライパス検証**: セールスエージェントがパブリッシャーに認可されていたか確認
* **リアルタイム監視**: 実行中キャンペーンの準拠率を確認
* **監査証跡**: 規制・ブランドセーフティ審査向けレポート生成

## Request

```json theme={null}
{
  "$schema": "/schemas/property/validate-property-delivery-request.json",
  "list_id": "pl_abc123",
  "records": [
    {
      "identifier": { "type": "domain", "value": "www.nytimes.com" },
      "impressions": 103
    },
    {
      "identifier": { "type": "domain", "value": "sketchy-site.example" },
      "impressions": 47
    },
    {
      "identifier": { "type": "android_package", "value": "com.unknown.app" },
      "impressions": 25
    }
  ],
  "include_compliant": false
}
```

### Parameters

| Parameter                   | Type    | Required | Description                                 |
| --------------------------- | ------- | -------- | ------------------------------------------- |
| `list_id`                   | string  | Yes      | 検証対象のプロパティリスト ID                            |
| `records`                   | array   | Yes      | 検証する配信記録（1〜10,000 件）                        |
| `records[].identifier`      | object  | Yes      | プロパティ識別子（`type` と `value`）                  |
| `records[].impressions`     | integer | Yes      | 配信インプレッション数                                 |
| `records[].record_id`       | string  | No       | 相関用のクライアント ID                               |
| `records[].sales_agent_url` | string  | No       | 認可検証に使うセールスエージェント URL（adagents.json と突き合わせ） |
| `include_compliant`         | boolean | No       | 準拠レコードを結果に含めるか（デフォルト false）                 |

## Response

```json theme={null}
{
  "$schema": "/schemas/property/validate-property-delivery-response.json",
  "status": "completed",
  "list_id": "pl_abc123",
  "summary": {
    "total_records": 4,
    "total_impressions": 200,
    "compliant_records": 1,
    "compliant_impressions": 103,
    "non_compliant_records": 1,
    "non_compliant_impressions": 47,
    "not_covered_records": 1,
    "not_covered_impressions": 25,
    "unidentified_records": 1,
    "unidentified_impressions": 25
  },
  "aggregate": {
    "score": 68.7,
    "grade": "C+",
    "label": "68.7% compliant",
    "methodology_url": "https://governance.example.com/methodology/compliance-scoring"
  },
  "results": [
    {
      "identifier": { "type": "domain", "value": "sketchy-site.example" },
      "status": "non_compliant",
      "impressions": 47,
      "features": [
        {
          "feature_id": "record:list_membership",
          "status": "failed",
          "explanation": "Identifier not found in resolved property list"
        }
      ]
    },
    {
      "identifier": { "type": "domain", "value": "new-site.example" },
      "status": "not_covered",
      "impressions": 25
    },
    {
      "identifier": { "type": "android_package", "value": "com.unknown.app" },
      "status": "unidentified",
      "impressions": 25
    }
  ],
  "validated_at": "2026-01-04T19:00:00Z",
  "list_resolved_at": "2026-01-04T12:00:00Z"
}
```

### レスポンスフィールド

| Field              | Type     | Description            |
| ------------------ | -------- | ---------------------- |
| `list_id`          | string   | 検証に用いたプロパティリスト ID      |
| `summary`          | object   | プロパティ準拠検証の生カウント        |
| `aggregate`        | object   | 任意の算出指標（ガバナンスエージェント提供） |
| `results`          | array    | レコード単位の検証結果            |
| `validated_at`     | datetime | 検証日時                   |
| `list_resolved_at` | datetime | 使用したプロパティリストの解決タイムスタンプ |

### Summary フィールド

Summary は生カウントを提供し、率の算出はクライアントサイドで行います:

| Field                                                 | Description                                  |
| ----------------------------------------------------- | -------------------------------------------- |
| `total_records`                                       | Total records validated                      |
| `total_impressions`                                   | Total impressions across all records         |
| `compliant_records` / `compliant_impressions`         | Records/impressions in the property list     |
| `non_compliant_records` / `non_compliant_impressions` | Records/impressions NOT in the property list |
| `not_covered_records` / `not_covered_impressions`     | Identifier recognized but no data available  |
| `unidentified_records` / `unidentified_impressions`   | Identifier type not resolvable               |

### 検証ステータス

| Status          | Meaning             |
| --------------- | ------------------- |
| `compliant`     | 解決済みリストに含まれる        |
| `non_compliant` | 解決済みリストに含まれない       |
| `not_covered`   | 識別子は認識したがデータなし      |
| `unidentified`  | このエージェントでは解決できない識別子 |

## not\_covered と unidentified の違い

いずれも「未知」だが性質が異なります:

**`not_covered`** - 識別子は認識した（例: 有効なドメイン）が、そのプロパティのデータがない場合。例:

* プロパティが新しく DB に未登録
* プロパティは存在するが未評価
* エージェントのカバレッジ外カテゴリ

**`unidentified`** - 識別子を認識できない場合。例:

* クライアントサイドでプロパティ検出に失敗
* サポート外の識別子型（ドメインのみ対応だが App ID を受信など）
* 値が不正

両者とも準拠率計算から除外します。検出やカバレッジの不足を罰するべきではありません。

## Optional Aggregate Metrics

Governance agents can optionally return computed metrics in the `aggregate` field:

```json theme={null}
"aggregate": {
  "score": 68.7,
  "grade": "C+",
  "label": "68.7% compliant",
  "methodology_url": "https://governance.example.com/methodology"
}
```

| Field             | Description                                             |
| ----------------- | ------------------------------------------------------- |
| `score`           | Numeric score (scale is agent-defined, typically 0-100) |
| `grade`           | Letter grade or category (e.g., "A+", "B-", "Gold")     |
| `label`           | Human-readable summary (e.g., "85% compliant")          |
| `methodology_url` | URL explaining how the aggregate was calculated         |

The `aggregate` field is optional and agent-specific. Consumers should not assume a particular format - always check `methodology_url` for interpretation.

## Calculating Your Own Rates

The response always includes raw counts. Calculate rates as needed:

```python theme={null}
# Compliance rate (exclude unverifiable from denominator)
unverifiable = summary.not_covered_impressions + summary.unidentified_impressions
verifiable = summary.total_impressions - unverifiable
compliance_rate = summary.compliant_impressions / verifiable if verifiable > 0 else None
```

In the example above:

* Compliant impressions: 103
* Non-compliant impressions: 47
* not\_covered + unidentified impressions: 50 (excluded)
* Compliance rate: 103 / (200 - 50) = 103 / 150 = 68.7%

## 機能結果

`features[]` の各エントリは `feature_id` と `status` を運びます。データ機能はガバナンスエージェントの機能カタログ（`get_adcp_capabilities` で発見）に由来します。レコードレベルの構造チェックは予約名前空間を使うため、データ機能と同じアイデンティティ空間に収まります。

### 予約された feature\_id プレフィックス

| Prefix      | Scope          | Canonical feature\_ids                                                                         |
| ----------- | -------------- | ---------------------------------------------------------------------------------------------- |
| `record:`   | レコードレベルの構造チェック | `record:list_membership`、`record:excluded`、`record:country_mismatch`、`record:channel_mismatch` |
| `delivery:` | 配信パスチェック       | `delivery:seller_authorization`、`delivery:click_url_presence`                                  |

ガバナンスエージェントは、これらの名前空間内で新しいチェックを追加し、機能カタログで公開してもかまいません（MAY）。

### 機能レベルの失敗

プロパティが特定の機能要件に失敗した場合、エントリは機能を id で参照します。レスポンスは判定と方向性のある説明を運びます。呼び出し元が要件を作成した場合（例: プロパティリストの `feature_requirements`）、評価器は `requirement` をエコーバックして、リスト定義を読み直さずに修正・再試行ループを可能にしてもかまいません（MAY）。

```json theme={null}
{
  "identifier": { "type": "domain", "value": "low-quality-site.example" },
  "status": "non_compliant",
  "impressions": 150,
  "features": [
    {
      "feature_id": "mfa_score",
      "status": "failed",
      "explanation": "Property below MFA score requirement",
      "requirement": { "min_value": 85 }
    }
  ]
}
```

オラクルパターン: レスポンスは**何が**失敗したか（feature\_id）と**どこにルールがあるか**（policy\_id、任意）を伝えます。評価器の内部（信頼度閾値、推論ロジック）は隠されたままです。

## Supply Path Authorization

When `sales_agent_url` is provided in delivery records, the governance agent validates that the sales agent is authorized to sell the property by checking the publisher's `adagents.json`.

### Request with Authorization

```json theme={null}
{
  "list_id": "pl_abc123",
  "records": [
    {
      "identifier": { "type": "domain", "value": "www.nytimes.com" },
      "impressions": 103,
      "sales_agent_url": "https://legitimate-ssp.example.com"
    },
    {
      "identifier": { "type": "domain", "value": "www.nytimes.com" },
      "impressions": 50,
      "sales_agent_url": "https://unauthorized-reseller.example.com"
    }
  ]
}
```

### Response with Authorization

When authorization is validated, each result includes an `authorization` field:

```json theme={null}
{
  "list_id": "pl_abc123",
  "summary": {
    "total_records": 2,
    "total_impressions": 153,
    "compliant_records": 2,
    "compliant_impressions": 153,
    "non_compliant_records": 0,
    "non_compliant_impressions": 0,
    "unknown_records": 0,
    "unknown_impressions": 0
  },
  "authorization_summary": {
    "records_checked": 2,
    "impressions_checked": 153,
    "authorized_records": 1,
    "authorized_impressions": 103,
    "unauthorized_records": 1,
    "unauthorized_impressions": 50,
    "unknown_records": 0,
    "unknown_impressions": 0
  },
  "results": [
    {
      "identifier": { "type": "domain", "value": "www.nytimes.com" },
      "status": "compliant",
      "impressions": 50,
      "authorization": {
        "status": "unauthorized",
        "publisher_domain": "nytimes.com",
        "sales_agent_url": "https://unauthorized-reseller.example.com",
        "violation": {
          "code": "agent_not_authorized",
          "message": "Sales agent not listed in nytimes.com/.well-known/adagents.json"
        }
      }
    }
  ],
  "validated_at": "2026-01-04T19:00:00Z"
}
```

### Authorization Statuses

| Status         | Meaning                                                | Included in authorization\_rate? |
| -------------- | ------------------------------------------------------ | -------------------------------- |
| `authorized`   | Sales agent is listed in publisher's adagents.json     | Yes (numerator)                  |
| `unauthorized` | Sales agent is NOT listed in publisher's adagents.json | Yes (denominator only)           |
| `unknown`      | Could not fetch or parse adagents.json                 | No (excluded)                    |

### Authorization Violation Codes

| Code                    | Description                                                         |
| ----------------------- | ------------------------------------------------------------------- |
| `agent_not_authorized`  | Sales agent URL not found in publisher's authorized\_agents list    |
| `adagents_not_found`    | Publisher's adagents.json could not be fetched (404, timeout, etc.) |
| `adagents_invalid`      | Publisher's adagents.json exists but is malformed                   |
| `property_not_declared` | Property identifier not declared in publisher's adagents.json       |

### Two Independent Checks

Property compliance and authorization are **independent checks**. A record can be:

| Property Status | Authorization Status | Meaning                                                  |
| --------------- | -------------------- | -------------------------------------------------------- |
| compliant       | authorized           | Fully valid - property in list, sold by authorized agent |
| compliant       | unauthorized         | Property is approved but sold by unauthorized reseller   |
| non\_compliant  | authorized           | Authorized agent sold property outside your list         |
| non\_compliant  | unauthorized         | Neither property nor agent validated                     |

Both checks use the same "unknown excludes from rate" pattern - you cannot penalize for detection gaps.

## Best Practices

### Batch Validation

For large-scale validation, batch records up to the 10,000 limit:

```python theme={null}
def validate_delivery_batch(records, list_id, governance_agent):
    """Validate delivery records in batches."""
    batch_size = 10000
    all_results = []

    for i in range(0, len(records), batch_size):
        batch = records[i:i + batch_size]
        response = governance_agent.validate_property_delivery(
            list_id=list_id,
            records=batch
        )
        all_results.extend(response.results)

    return all_results
```

### Sampling Strategy

For real-time monitoring during campaign execution, validate a statistical sample rather than all records:

```python theme={null}
import random

def sample_and_validate(records, sample_size=1000):
    """Validate a random sample for real-time monitoring."""
    sample = random.sample(records, min(sample_size, len(records)))
    return governance_agent.validate_property_delivery(
        list_id=list_id,
        records=sample
    )
```

### Handling Unknown Records

Track unknown rates separately to identify detection gaps:

```python theme={null}
def analyze_validation(response):
    """Analyze validation results with unknown handling."""
    summary = response.summary

    # Core compliance metric
    compliance_rate = summary.compliance_rate

    # Detection quality metric
    unknown_rate = summary.unknown_impressions / summary.total_impressions

    if unknown_rate > 0.1:
        print(f"Warning: {unknown_rate:.1%} of impressions unresolvable")

    return {
        "compliance_rate": compliance_rate,
        "unknown_rate": unknown_rate,
        "non_compliant_impressions": summary.non_compliant_impressions
    }
```

## Related Tasks

* [create\_property\_list](./property_lists#create_property_list) - Create the list to validate against
* [get\_property\_list](./property_lists#get_property_list) - Retrieve current list membership
* [get\_adcp\_capabilities](/docs/protocol/get_adcp_capabilities) - Discover available filter features
